summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:22 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-03-03 18:28:22 -0800
commitd1ceeffdc951169c079c2d35f8b8cd26481dcc3a (patch)
tree4b825dc642cb6eb9a060e54bf8d69288fbee4904
parent8d6d7ea32d2e40489fa8be26618167fb6e2dfb40 (diff)
downloadelfcopy-d1ceeffdc951169c079c2d35f8b8cd26481dcc3a.tar.gz
auto import from //depot/cupcake/@135843
-rwxr-xr-xAndroid.mk52
-rw-r--r--MODULE_LICENSE_GPL0
-rw-r--r--NOTICE340
-rw-r--r--common.c35
-rw-r--r--common.h49
-rw-r--r--debug.c39
-rw-r--r--debug.h94
-rw-r--r--dwarf.c3960
-rw-r--r--dwarf.h122
-rw-r--r--dwarf2.h836
-rw-r--r--elfcopy.c2992
-rw-r--r--elfcopy.h94
-rw-r--r--fixdwarf.c577
-rw-r--r--fixdwarf.h14
-rw-r--r--hash.c76
-rw-r--r--hash.h22
-rw-r--r--rangesort.c335
-rw-r--r--rangesort.h105
18 files changed, 0 insertions, 9742 deletions
diff --git a/Android.mk b/Android.mk
deleted file mode 100755
index 67f92af..0000000
--- a/Android.mk
+++ /dev/null
@@ -1,52 +0,0 @@
-LOCAL_PATH:= $(call my-dir)
-
-#
-# libelfcopy
-#
-
-include $(CLEAR_VARS)
-
-LOCAL_SRC_FILES += \
- common.c \
- debug.c \
- elfcopy.c \
- hash.c \
- rangesort.c \
- fixdwarf.c \
- dwarf.c
-
-ifeq ($(HOST_OS),linux)
-endif
-ifeq ($(HOST_OS),darwin)
-endif
-
-LOCAL_MODULE:=libelfcopy
-
-#LOCAL_LDLIBS += -ldl
-LOCAL_CFLAGS += -O2 -g
-LOCAL_CFLAGS += -fno-function-sections -fno-data-sections -fno-inline
-LOCAL_CFLAGS += -Wall -Wno-unused-function #-Werror
-LOCAL_CFLAGS += -DBIG_ENDIAN=1
-LOCAL_CFLAGS += -DARM_SPECIFIC_HACKS
-LOCAL_CFLAGS += -DDEBUG
-LOCAL_CFLAGS += -DSTRIP_SECTIONS
-LOCAL_CFLAGS += -DSTRIP_STATIC_SYMBOLS
-LOCAL_CFLAGS += -DMOVE_SECTIONS_IN_RANGES
-#LOCAL_CFLAGS += -DSORT_LOCATION_LIST_OFFSETS
-
-
-# dwarf.c
-LOCAL_CFLAGS += -DATTRIBUTE_UNUSED="__attribute__((unused))"
-LOCAL_CFLAGS += -DTRUE=1
-LOCAL_CFLAGS += -DFALSE=0
-LOCAL_CFLAGS += -Dprogram_name=\"libelfcopy\"
-
-LOCAL_STATIC_LIBRARIES := libelf libebl libebl_arm
-
-LOCAL_C_INCLUDES:= \
- $(LOCAL_PATH)/ \
- external/elfutils/lib/ \
- external/elfutils/libelf/ \
- external/elfutils/libebl/
-
-include $(BUILD_HOST_STATIC_LIBRARY)
diff --git a/MODULE_LICENSE_GPL b/MODULE_LICENSE_GPL
deleted file mode 100644
index e69de29..0000000
--- a/MODULE_LICENSE_GPL
+++ /dev/null
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 623b625..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,340 +0,0 @@
- 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 Library 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 Library General
-Public License instead of this License.
diff --git a/common.c b/common.c
deleted file mode 100644
index b90cf41..0000000
--- a/common.c
+++ /dev/null
@@ -1,35 +0,0 @@
-#include <stdlib.h>
-#include <common.h>
-#include <debug.h>
-
-void map_over_sections(Elf *elf,
- section_match_fn_t match,
- void *user_data)
-{
- Elf_Scn* section = NULL;
- while ((section = elf_nextscn(elf, section)) != NULL) {
- if (match(elf, section, user_data))
- return;
- }
-}
-
-void map_over_segments(Elf *elf,
- segment_match_fn_t match,
- void *user_data)
-{
- Elf32_Ehdr *ehdr;
- Elf32_Phdr *phdr;
- int index;
-
- ehdr = elf32_getehdr(elf);
- phdr = elf32_getphdr(elf);
-
- INFO("Scanning over %d program segments...\n",
- ehdr->e_phnum);
-
- for (index = ehdr->e_phnum; index; index--) {
- if (match(elf, phdr++, user_data))
- return;
- }
-}
-
diff --git a/common.h b/common.h
deleted file mode 100644
index dacf930..0000000
--- a/common.h
+++ /dev/null
@@ -1,49 +0,0 @@
-#ifndef COMMON_H
-#define COMMON_H
-
-#include <libelf.h>
-#include <elf.h>
-
-#define unlikely(expr) __builtin_expect (expr, 0)
-#define likely(expr) __builtin_expect (expr, 1)
-
-#define MIN(a,b) ((a)<(b)?(a):(b)) /* no side effects in arguments allowed! */
-
-typedef int (*section_match_fn_t)(Elf *, Elf_Scn *, void *);
-void map_over_sections(Elf *, section_match_fn_t, void *);
-
-typedef int (*segment_match_fn_t)(Elf *, Elf32_Phdr *, void *);
-void map_over_segments(Elf *, segment_match_fn_t, void *);
-
-typedef struct {
- Elf_Scn *sect;
- Elf32_Shdr *hdr;
- Elf_Data *data;
- size_t index;
-} section_info_t;
-
-static inline void get_section_info(Elf_Scn *sect, section_info_t *info)
-{
- info->sect = sect;
- info->data = elf_getdata(sect, 0);
- info->hdr = elf32_getshdr(sect);
- info->index = elf_ndxscn(sect);
-}
-
-static inline int is_host_little(void)
-{
- short val = 0x10;
- return ((char *)&val)[0] != 0;
-}
-
-static inline long switch_endianness(long val)
-{
- long newval;
- ((char *)&newval)[3] = ((char *)&val)[0];
- ((char *)&newval)[2] = ((char *)&val)[1];
- ((char *)&newval)[1] = ((char *)&val)[2];
- ((char *)&newval)[0] = ((char *)&val)[3];
- return newval;
-}
-
-#endif/*COMMON_H*/
diff --git a/debug.c b/debug.c
deleted file mode 100644
index e7e16d4..0000000
--- a/debug.c
+++ /dev/null
@@ -1,39 +0,0 @@
-#include <debug.h>
-#include <stdio.h>
-#include <ctype.h>
-
-#define NUM_COLS (32)
-
-/* returns the number of non-zero non-printable characters. */
-
-int dump_hex_buffer(FILE *s, void *b, size_t len, size_t elsize) {
- int num_nonprintable = 0;
- int i, last;
- char *pchr = (char *)b;
- fputc('\n', s);
- for (i = last = 0; i < len; i++) {
- if (!elsize) {
- if (i && !(i % 4)) fprintf(s, " ");
- if (i && !(i % 8)) fprintf(s, " ");
- } else {
- if (i && !(i % elsize)) fprintf(s, " ");
- }
-
- if (i && !(i % NUM_COLS)) {
- while (last < i) {
- if (isprint(pchr[last]))
- fputc(pchr[last], s);
- else {
- fputc('.', s);
- if(pchr[last])
- num_nonprintable++;
- }
- last++;
- }
- fprintf(s, " (%d)\n", i);
- }
- fprintf(s, "%02x", (unsigned char)pchr[i]);
- }
- if (i && (i % NUM_COLS)) fputs("\n", s);
- return num_nonprintable;
-}
diff --git a/debug.h b/debug.h
deleted file mode 100644
index 16d627d..0000000
--- a/debug.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef DEBUG_H
-#define DEBUG_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <common.h>
-
-#ifdef DEBUG
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, "%s(%d): ", __FILE__, __LINE__); \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* Debug enabled */
- #define ASSERT(x) do { \
- if (unlikely(!(x))) { \
- fprintf(stderr, \
- "ASSERTION FAILURE %s:%d: [%s]\n", \
- __FILE__, __LINE__, #x); \
- exit(1); \
- } \
-} while(0)
-
-#else
-
- #define FAILIF(cond, msg...) do { \
- if (unlikely(cond)) { \
- fprintf(stderr, ##msg); \
- exit(1); \
- } \
-} while(0)
-
-/* No debug */
- #define ASSERT(x) do { } while(0)
-
-#endif/* DEBUG */
-
-#define FAILIF_LIBELF(cond, function) \
- FAILIF(cond, "%s(): %s\n", #function, elf_errmsg(elf_errno()));
-
-static inline void *MALLOC(unsigned int size) {
- void *m = malloc(size);
- FAILIF(NULL == m, "malloc(%d) failed!\n", size);
- return m;
-}
-
-static inline void *CALLOC(unsigned int num_entries, unsigned int entry_size) {
- void *m = calloc(num_entries, entry_size);
- FAILIF(NULL == m, "calloc(%d, %d) failed!\n", num_entries, entry_size);
- return m;
-}
-
-static inline void *REALLOC(void *ptr, unsigned int size) {
- void *m = realloc(ptr, size);
- FAILIF(NULL == m, "realloc(%p, %d) failed!\n", ptr, size);
- return m;
-}
-
-static inline void FREE(void *ptr) {
- free(ptr);
-}
-
-static inline void FREEIF(void *ptr) {
- if (ptr) FREE(ptr);
-}
-
-#define PRINT(x...) do { \
- extern int quiet_flag; \
- if(likely(!quiet_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define ERROR(x...) fprintf(stderr, ##x)
-
-#define INFO(x...) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- fprintf(stdout, ##x); \
-} while(0)
-
-#define PUTCHAR(c) do { \
- extern int verbose_flag; \
- if(unlikely(verbose_flag)) \
- putc((c), stdout); \
-} while(0)
-
-/* Prints a hex and ASCII dump of the selected buffer to the selected stream. */
-int dump_hex_buffer(FILE *s, void *b, size_t l, size_t elsize);
-
-#endif/*DEBUG_H*/
diff --git a/dwarf.c b/dwarf.c
deleted file mode 100644
index 33d7469..0000000
--- a/dwarf.c
+++ /dev/null
@@ -1,3960 +0,0 @@
-/* dwarf.c -- display DWARF contents of a BFD binary file
- Copyright 2005, 2006
- Free Software Foundation, Inc.
-
- This file is part of GNU Binutils.
-
- 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. */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "debug.h"
-
-#define _(val) val
-#define __str(s) #s
-#define printf INFO
-#define putchar PUTCHAR
-
-#include "dwarf.h"
-
-static int have_frame_base;
-static int need_base_address;
-
-static unsigned int last_pointer_size = 0;
-static int warned_about_missing_comp_units = FALSE;
-
-static unsigned int num_debug_info_entries = 0;
-static debug_info *debug_information = NULL;
-
-dwarf_vma eh_addr_size;
-int is_relocatable;
-
-int do_debug_info;
-int do_debug_abbrevs;
-int do_debug_lines;
-int do_debug_pubnames;
-int do_debug_aranges;
-int do_debug_ranges;
-int do_debug_frames;
-int do_debug_frames_interp;
-int do_debug_macinfo;
-int do_debug_str;
-int do_debug_loc;
-
-dwarf_vma (*byte_get) (unsigned char *, int);
-
-static void *xmalloc(size_t sz);
-static void *cmalloc (size_t, size_t);
-static void *xcmalloc (size_t, size_t);
-static void *xcrealloc (void *, size_t, size_t);
-
-static void error (const char *, ...); // ATTRIBUTE_PRINTF_1; //HACK
-static void warn (const char *, ...); // ATTRIBUTE_PRINTF_1; //HACK
-
-
-dwarf_vma
-byte_get_little_endian (unsigned char *field, int size)
-{
- switch (size)
- {
- case 1:
- return *field;
-
- case 2:
- return ((unsigned int) (field[0]))
- | (((unsigned int) (field[1])) << 8);
-
- case 4:
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
-
- case 8:
- if (sizeof (dwarf_vma) == 8)
- return ((dwarf_vma) (field[0]))
- | (((dwarf_vma) (field[1])) << 8)
- | (((dwarf_vma) (field[2])) << 16)
- | (((dwarf_vma) (field[3])) << 24)
- | (((dwarf_vma) (field[4])) << 32)
- | (((dwarf_vma) (field[5])) << 40)
- | (((dwarf_vma) (field[6])) << 48)
- | (((dwarf_vma) (field[7])) << 56);
- else if (sizeof (dwarf_vma) == 4)
- /* We want to extract data from an 8 byte wide field and
- place it into a 4 byte wide field. Since this is a little
- endian source we can just use the 4 byte extraction code. */
- return ((unsigned long) (field[0]))
- | (((unsigned long) (field[1])) << 8)
- | (((unsigned long) (field[2])) << 16)
- | (((unsigned long) (field[3])) << 24);
-
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
-}
-
-dwarf_vma
-byte_get_big_endian (unsigned char *field, int size)
-{
- switch (size)
- {
- case 1:
- return *field;
-
- case 2:
- return ((unsigned int) (field[1])) | (((int) (field[0])) << 8);
-
- case 4:
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
-
- case 8:
- if (sizeof (dwarf_vma) == 8)
- return ((dwarf_vma) (field[7]))
- | (((dwarf_vma) (field[6])) << 8)
- | (((dwarf_vma) (field[5])) << 16)
- | (((dwarf_vma) (field[4])) << 24)
- | (((dwarf_vma) (field[3])) << 32)
- | (((dwarf_vma) (field[2])) << 40)
- | (((dwarf_vma) (field[1])) << 48)
- | (((dwarf_vma) (field[0])) << 56);
- else if (sizeof (dwarf_vma) == 4)
- {
- /* Although we are extracing data from an 8 byte wide field,
- we are returning only 4 bytes of data. */
- field += 4;
- return ((unsigned long) (field[3]))
- | (((unsigned long) (field[2])) << 8)
- | (((unsigned long) (field[1])) << 16)
- | (((unsigned long) (field[0])) << 24);
- }
-
- default:
- error (_("Unhandled data length: %d\n"), size);
- abort ();
- }
-}
-
-static dwarf_vma
-byte_get_signed (unsigned char *field, int size)
-{
- dwarf_vma x = byte_get (field, size);
-
- switch (size)
- {
- case 1:
- return (x ^ 0x80) - 0x80;
- case 2:
- return (x ^ 0x8000) - 0x8000;
- case 4:
- return (x ^ 0x80000000) - 0x80000000;
- case 8:
- return x;
- default:
- abort ();
- }
-}
-
-static unsigned long int
-read_leb128 (unsigned char *data, unsigned int *length_return, int sign)
-{
- unsigned long int result = 0;
- unsigned int num_read = 0;
- unsigned int shift = 0;
- unsigned char byte;
-
- do
- {
- byte = *data++;
- num_read++;
-
- result |= ((unsigned long int) (byte & 0x7f)) << shift;
-
- shift += 7;
-
- }
- while (byte & 0x80);
-
- if (length_return != NULL)
- *length_return = num_read;
-
- if (sign && (shift < 8 * sizeof (result)) && (byte & 0x40))
- result |= -1L << shift;
-
- return result;
-}
-
-typedef struct State_Machine_Registers
-{
- unsigned long address;
- unsigned int file;
- unsigned int line;
- unsigned int column;
- int is_stmt;
- int basic_block;
- int end_sequence;
-/* This variable hold the number of the last entry seen
- in the File Table. */
- unsigned int last_file_entry;
-} SMR;
-
-static SMR state_machine_regs;
-
-static void
-reset_state_machine (int is_stmt)
-{
- state_machine_regs.address = 0;
- state_machine_regs.file = 1;
- state_machine_regs.line = 1;
- state_machine_regs.column = 0;
- state_machine_regs.is_stmt = is_stmt;
- state_machine_regs.basic_block = 0;
- state_machine_regs.end_sequence = 0;
- state_machine_regs.last_file_entry = 0;
-}
-
-/* Handled an extend line op.
- Returns the number of bytes read. */
-
-static int
-process_extended_line_op (unsigned char *data, int is_stmt)
-{
- unsigned char op_code;
- unsigned int bytes_read;
- unsigned int len;
- unsigned char *name;
- unsigned long adr;
-
- len = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
-
- if (len == 0)
- {
- warn (_("badly formed extended line op encountered!\n"));
- return bytes_read;
- }
-
- len += bytes_read;
- op_code = *data++;
-
- printf (_(" Extended opcode %d: "), op_code);
-
- switch (op_code)
- {
- case DW_LNE_end_sequence:
- printf (_("End of Sequence\n\n"));
- reset_state_machine (is_stmt);
- break;
-
- case DW_LNE_set_address:
- adr = byte_get (data, len - bytes_read - 1);
- printf (_("set Address to 0x%lx\n"), adr);
- state_machine_regs.address = adr;
- value_hook(data, len - bytes_read - 1, adr);
- break;
-
- case DW_LNE_define_file:
- printf (_(" define new File Table entry\n"));
- printf (_(" Entry\tDir\tTime\tSize\tName\n"));
-
- ++state_machine_regs.last_file_entry;
- printf (_(" %d\t"), state_machine_regs.last_file_entry);
- name = data;
- data += strlen ((char *) data) + 1;
- unsigned long val;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- data += bytes_read;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- data += bytes_read;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- printf (_("%s\n\n"), name);
- break;
-
- default:
- printf (_("UNKNOWN: length %d\n"), len - bytes_read);
- break;
- }
-
- return len;
-}
-
-static const char *
-fetch_indirect_string (unsigned long offset)
-{
- struct dwarf_section *section = &debug_displays [str].section;
-
- if (section->start == NULL)
- return _("<no .debug_str section>");
-
- /* DWARF sections under Mach-O have non-zero addresses. */
- offset -= section->address;
- if (offset > section->size)
- {
- warn (_("DW_FORM_strp offset too big: %lx\n"), offset);
- return _("<offset is too big>");
- }
-
- return (const char *) section->start + offset;
-}
-
-/* FIXME: There are better and more efficient ways to handle
- these structures. For now though, I just want something that
- is simple to implement. */
-typedef struct abbrev_attr
-{
- unsigned long attribute;
- unsigned long form;
- struct abbrev_attr *next;
-}
-abbrev_attr;
-
-typedef struct abbrev_entry
-{
- unsigned long entry;
- unsigned long tag;
- int children;
- struct abbrev_attr *first_attr;
- struct abbrev_attr *last_attr;
- struct abbrev_entry *next;
-}
-abbrev_entry;
-
-static abbrev_entry *first_abbrev = NULL;
-static abbrev_entry *last_abbrev = NULL;
-
-static void
-free_abbrevs (void)
-{
- abbrev_entry *abbrev;
-
- for (abbrev = first_abbrev; abbrev;)
- {
- abbrev_entry *next = abbrev->next;
- abbrev_attr *attr;
-
- for (attr = abbrev->first_attr; attr;)
- {
- abbrev_attr *next = attr->next;
-
- free (attr);
- attr = next;
- }
-
- free (abbrev);
- abbrev = next;
- }
-
- last_abbrev = first_abbrev = NULL;
-}
-
-static void
-add_abbrev (unsigned long number, unsigned long tag, int children)
-{
- abbrev_entry *entry;
-
- entry = malloc (sizeof (*entry));
-
- if (entry == NULL)
- /* ugg */
- return;
-
- entry->entry = number;
- entry->tag = tag;
- entry->children = children;
- entry->first_attr = NULL;
- entry->last_attr = NULL;
- entry->next = NULL;
-
- if (first_abbrev == NULL)
- first_abbrev = entry;
- else
- last_abbrev->next = entry;
-
- last_abbrev = entry;
-}
-
-static void
-add_abbrev_attr (unsigned long attribute, unsigned long form)
-{
- abbrev_attr *attr;
-
- attr = malloc (sizeof (*attr));
-
- if (attr == NULL)
- /* ugg */
- return;
-
- attr->attribute = attribute;
- attr->form = form;
- attr->next = NULL;
-
- if (last_abbrev->first_attr == NULL)
- last_abbrev->first_attr = attr;
- else
- last_abbrev->last_attr->next = attr;
-
- last_abbrev->last_attr = attr;
-}
-
-/* Processes the (partial) contents of a .debug_abbrev section.
- Returns NULL if the end of the section was encountered.
- Returns the address after the last byte read if the end of
- an abbreviation set was found. */
-
-static unsigned char *
-process_abbrev_section (unsigned char *start, unsigned char *end)
-{
- if (first_abbrev != NULL)
- return NULL;
-
- while (start < end)
- {
- unsigned int bytes_read;
- unsigned long entry;
- unsigned long tag;
- unsigned long attribute;
- int children;
-
- entry = read_leb128 (start, & bytes_read, 0);
- start += bytes_read;
-
- /* A single zero is supposed to end the section according
- to the standard. If there's more, then signal that to
- the caller. */
- if (entry == 0)
- return start == end ? NULL : start;
-
- tag = read_leb128 (start, & bytes_read, 0);
- start += bytes_read;
-
- children = *start++;
-
- add_abbrev (entry, tag, children);
-
- do
- {
- unsigned long form;
-
- attribute = read_leb128 (start, & bytes_read, 0);
- start += bytes_read;
-
- form = read_leb128 (start, & bytes_read, 0);
- start += bytes_read;
-
- if (attribute != 0)
- add_abbrev_attr (attribute, form);
- }
- while (attribute != 0);
- }
-
- return NULL;
-}
-
-static char *
-get_TAG_name (unsigned long tag)
-{
- switch (tag)
- {
- case DW_TAG_padding: return "DW_TAG_padding";
- case DW_TAG_array_type: return "DW_TAG_array_type";
- case DW_TAG_class_type: return "DW_TAG_class_type";
- case DW_TAG_entry_point: return "DW_TAG_entry_point";
- case DW_TAG_enumeration_type: return "DW_TAG_enumeration_type";
- case DW_TAG_formal_parameter: return "DW_TAG_formal_parameter";
- case DW_TAG_imported_declaration: return "DW_TAG_imported_declaration";
- case DW_TAG_label: return "DW_TAG_label";
- case DW_TAG_lexical_block: return "DW_TAG_lexical_block";
- case DW_TAG_member: return "DW_TAG_member";
- case DW_TAG_pointer_type: return "DW_TAG_pointer_type";
- case DW_TAG_reference_type: return "DW_TAG_reference_type";
- case DW_TAG_compile_unit: return "DW_TAG_compile_unit";
- case DW_TAG_string_type: return "DW_TAG_string_type";
- case DW_TAG_structure_type: return "DW_TAG_structure_type";
- case DW_TAG_subroutine_type: return "DW_TAG_subroutine_type";
- case DW_TAG_typedef: return "DW_TAG_typedef";
- case DW_TAG_union_type: return "DW_TAG_union_type";
- case DW_TAG_unspecified_parameters: return "DW_TAG_unspecified_parameters";
- case DW_TAG_variant: return "DW_TAG_variant";
- case DW_TAG_common_block: return "DW_TAG_common_block";
- case DW_TAG_common_inclusion: return "DW_TAG_common_inclusion";
- case DW_TAG_inheritance: return "DW_TAG_inheritance";
- case DW_TAG_inlined_subroutine: return "DW_TAG_inlined_subroutine";
- case DW_TAG_module: return "DW_TAG_module";
- case DW_TAG_ptr_to_member_type: return "DW_TAG_ptr_to_member_type";
- case DW_TAG_set_type: return "DW_TAG_set_type";
- case DW_TAG_subrange_type: return "DW_TAG_subrange_type";
- case DW_TAG_with_stmt: return "DW_TAG_with_stmt";
- case DW_TAG_access_declaration: return "DW_TAG_access_declaration";
- case DW_TAG_base_type: return "DW_TAG_base_type";
- case DW_TAG_catch_block: return "DW_TAG_catch_block";
- case DW_TAG_const_type: return "DW_TAG_const_type";
- case DW_TAG_constant: return "DW_TAG_constant";
- case DW_TAG_enumerator: return "DW_TAG_enumerator";
- case DW_TAG_file_type: return "DW_TAG_file_type";
- case DW_TAG_friend: return "DW_TAG_friend";
- case DW_TAG_namelist: return "DW_TAG_namelist";
- case DW_TAG_namelist_item: return "DW_TAG_namelist_item";
- case DW_TAG_packed_type: return "DW_TAG_packed_type";
- case DW_TAG_subprogram: return "DW_TAG_subprogram";
- case DW_TAG_template_type_param: return "DW_TAG_template_type_param";
- case DW_TAG_template_value_param: return "DW_TAG_template_value_param";
- case DW_TAG_thrown_type: return "DW_TAG_thrown_type";
- case DW_TAG_try_block: return "DW_TAG_try_block";
- case DW_TAG_variant_part: return "DW_TAG_variant_part";
- case DW_TAG_variable: return "DW_TAG_variable";
- case DW_TAG_volatile_type: return "DW_TAG_volatile_type";
- case DW_TAG_MIPS_loop: return "DW_TAG_MIPS_loop";
- case DW_TAG_format_label: return "DW_TAG_format_label";
- case DW_TAG_function_template: return "DW_TAG_function_template";
- case DW_TAG_class_template: return "DW_TAG_class_template";
- /* DWARF 2.1 values. */
- case DW_TAG_dwarf_procedure: return "DW_TAG_dwarf_procedure";
- case DW_TAG_restrict_type: return "DW_TAG_restrict_type";
- case DW_TAG_interface_type: return "DW_TAG_interface_type";
- case DW_TAG_namespace: return "DW_TAG_namespace";
- case DW_TAG_imported_module: return "DW_TAG_imported_module";
- case DW_TAG_unspecified_type: return "DW_TAG_unspecified_type";
- case DW_TAG_partial_unit: return "DW_TAG_partial_unit";
- case DW_TAG_imported_unit: return "DW_TAG_imported_unit";
- /* UPC values. */
- case DW_TAG_upc_shared_type: return "DW_TAG_upc_shared_type";
- case DW_TAG_upc_strict_type: return "DW_TAG_upc_strict_type";
- case DW_TAG_upc_relaxed_type: return "DW_TAG_upc_relaxed_type";
- default:
- {
- static char buffer[100];
-
- snprintf (buffer, sizeof (buffer), _("Unknown TAG value: %lx"), tag);
- return buffer;
- }
- }
-}
-
-static char *
-get_FORM_name (unsigned long form)
-{
- switch (form)
- {
- case DW_FORM_addr: return "DW_FORM_addr";
- case DW_FORM_block2: return "DW_FORM_block2";
- case DW_FORM_block4: return "DW_FORM_block4";
- case DW_FORM_data2: return "DW_FORM_data2";
- case DW_FORM_data4: return "DW_FORM_data4";
- case DW_FORM_data8: return "DW_FORM_data8";
- case DW_FORM_string: return "DW_FORM_string";
- case DW_FORM_block: return "DW_FORM_block";
- case DW_FORM_block1: return "DW_FORM_block1";
- case DW_FORM_data1: return "DW_FORM_data1";
- case DW_FORM_flag: return "DW_FORM_flag";
- case DW_FORM_sdata: return "DW_FORM_sdata";
- case DW_FORM_strp: return "DW_FORM_strp";
- case DW_FORM_udata: return "DW_FORM_udata";
- case DW_FORM_ref_addr: return "DW_FORM_ref_addr";
- case DW_FORM_ref1: return "DW_FORM_ref1";
- case DW_FORM_ref2: return "DW_FORM_ref2";
- case DW_FORM_ref4: return "DW_FORM_ref4";
- case DW_FORM_ref8: return "DW_FORM_ref8";
- case DW_FORM_ref_udata: return "DW_FORM_ref_udata";
- case DW_FORM_indirect: return "DW_FORM_indirect";
- default:
- {
- static char buffer[100];
-
- snprintf (buffer, sizeof (buffer), _("Unknown FORM value: %lx"), form);
- return buffer;
- }
- }
-}
-
-static unsigned char *
-display_block (unsigned char *data, unsigned long length)
-{
- printf (_(" %lu byte block: "), length);
-
- unsigned long val;
- while (length --) {
- val = (unsigned long) byte_get (data++, 1);
- printf ("%lx ", val);
- }
-
- return data;
-}
-
-static int
-decode_location_expression (unsigned char * data,
- unsigned int pointer_size,
- unsigned long length,
- unsigned long cu_offset)
-{
- unsigned op;
- unsigned int bytes_read;
- unsigned long uvalue;
- unsigned char *end = data + length;
- int need_frame_base = 0;
- unsigned long val = 0, val2;
-
- while (data < end)
- {
- op = *data++;
-
- switch (op)
- {
- case DW_OP_addr:
- val = (unsigned long) byte_get (data, pointer_size);
- printf ("DW_OP_addr: %lx",
- val);
- value_hook(data, pointer_size, val);
- data += pointer_size;
- break;
- case DW_OP_deref:
- printf ("DW_OP_deref");
- break;
- case DW_OP_const1u:
- val = byte_get (data++, 1);
- printf ("DW_OP_const1u: %lu", val);
- break;
- case DW_OP_const1s:
- val = byte_get_signed (data++, 1);
- printf ("DW_OP_const1s: %ld", (long) val);
- break;
- case DW_OP_const2u:
- val = (unsigned long) byte_get (data, 2);
- printf ("DW_OP_const2u: %lu", val);
- data += 2;
- break;
- case DW_OP_const2s:
- val = byte_get_signed (data, 2);
- printf ("DW_OP_const2s: %ld", (long)val);
- data += 2;
- break;
- case DW_OP_const4u:
- val = (unsigned long) byte_get (data, 4);
- printf ("DW_OP_const4u: %lu", val);
- data += 4;
- break;
- case DW_OP_const4s:
- val = byte_get_signed (data, 4);
- printf ("DW_OP_const4s: %ld", (long) val);
- data += 4;
- break;
- case DW_OP_const8u:
- val = (unsigned long) byte_get (data, 4);
- val2 = (unsigned long) byte_get (data + 4, 4);
- printf ("DW_OP_const8u: %lu %lu", val, val2);
- data += 8;
- break;
- case DW_OP_const8s:
- val = byte_get (data, 4);
- val2 = byte_get (data + 4, 4);
- printf ("DW_OP_const8s: %ld %ld", (long) val, (long) val2);
- data += 8;
- break;
- case DW_OP_constu:
- val = read_leb128 (data, &bytes_read, 0);
- printf ("DW_OP_constu: %lu", val);
- data += bytes_read;
- break;
- case DW_OP_consts:
- val = read_leb128 (data, &bytes_read, 1);
- printf ("DW_OP_consts: %ld", val);
- data += bytes_read;
- break;
- case DW_OP_dup:
- printf ("DW_OP_dup");
- break;
- case DW_OP_drop:
- printf ("DW_OP_drop");
- break;
- case DW_OP_over:
- printf ("DW_OP_over");
- break;
- case DW_OP_pick:
- val = (unsigned long) byte_get (data++, 1);
- printf ("DW_OP_pick: %ld", val);
- break;
- case DW_OP_swap:
- printf ("DW_OP_swap");
- break;
- case DW_OP_rot:
- printf ("DW_OP_rot");
- break;
- case DW_OP_xderef:
- printf ("DW_OP_xderef");
- break;
- case DW_OP_abs:
- printf ("DW_OP_abs");
- break;
- case DW_OP_and:
- printf ("DW_OP_and");
- break;
- case DW_OP_div:
- printf ("DW_OP_div");
- break;
- case DW_OP_minus:
- printf ("DW_OP_minus");
- break;
- case DW_OP_mod:
- printf ("DW_OP_mod");
- break;
- case DW_OP_mul:
- printf ("DW_OP_mul");
- break;
- case DW_OP_neg:
- printf ("DW_OP_neg");
- break;
- case DW_OP_not:
- printf ("DW_OP_not");
- break;
- case DW_OP_or:
- printf ("DW_OP_or");
- break;
- case DW_OP_plus:
- printf ("DW_OP_plus");
- break;
- case DW_OP_plus_uconst:
- val = read_leb128 (data, &bytes_read, 0);
- printf ("DW_OP_plus_uconst: %lu", val);
- data += bytes_read;
- break;
- case DW_OP_shl:
- printf ("DW_OP_shl");
- break;
- case DW_OP_shr:
- printf ("DW_OP_shr");
- break;
- case DW_OP_shra:
- printf ("DW_OP_shra");
- break;
- case DW_OP_xor:
- printf ("DW_OP_xor");
- break;
- case DW_OP_bra:
- val = byte_get_signed (data, 2);
- printf ("DW_OP_bra: %ld", (long) val);
- data += 2;
- break;
- case DW_OP_eq:
- printf ("DW_OP_eq");
- break;
- case DW_OP_ge:
- printf ("DW_OP_ge");
- break;
- case DW_OP_gt:
- printf ("DW_OP_gt");
- break;
- case DW_OP_le:
- printf ("DW_OP_le");
- break;
- case DW_OP_lt:
- printf ("DW_OP_lt");
- break;
- case DW_OP_ne:
- printf ("DW_OP_ne");
- break;
- case DW_OP_skip:
- val = byte_get_signed (data, 2);
- printf ("DW_OP_skip: %ld", (long) val);
- data += 2;
- break;
-
- case DW_OP_lit0:
- case DW_OP_lit1:
- case DW_OP_lit2:
- case DW_OP_lit3:
- case DW_OP_lit4:
- case DW_OP_lit5:
- case DW_OP_lit6:
- case DW_OP_lit7:
- case DW_OP_lit8:
- case DW_OP_lit9:
- case DW_OP_lit10:
- case DW_OP_lit11:
- case DW_OP_lit12:
- case DW_OP_lit13:
- case DW_OP_lit14:
- case DW_OP_lit15:
- case DW_OP_lit16:
- case DW_OP_lit17:
- case DW_OP_lit18:
- case DW_OP_lit19:
- case DW_OP_lit20:
- case DW_OP_lit21:
- case DW_OP_lit22:
- case DW_OP_lit23:
- case DW_OP_lit24:
- case DW_OP_lit25:
- case DW_OP_lit26:
- case DW_OP_lit27:
- case DW_OP_lit28:
- case DW_OP_lit29:
- case DW_OP_lit30:
- case DW_OP_lit31:
- printf ("DW_OP_lit%d", op - DW_OP_lit0);
- break;
-
- case DW_OP_reg0:
- case DW_OP_reg1:
- case DW_OP_reg2:
- case DW_OP_reg3:
- case DW_OP_reg4:
- case DW_OP_reg5:
- case DW_OP_reg6:
- case DW_OP_reg7:
- case DW_OP_reg8:
- case DW_OP_reg9:
- case DW_OP_reg10:
- case DW_OP_reg11:
- case DW_OP_reg12:
- case DW_OP_reg13:
- case DW_OP_reg14:
- case DW_OP_reg15:
- case DW_OP_reg16:
- case DW_OP_reg17:
- case DW_OP_reg18:
- case DW_OP_reg19:
- case DW_OP_reg20:
- case DW_OP_reg21:
- case DW_OP_reg22:
- case DW_OP_reg23:
- case DW_OP_reg24:
- case DW_OP_reg25:
- case DW_OP_reg26:
- case DW_OP_reg27:
- case DW_OP_reg28:
- case DW_OP_reg29:
- case DW_OP_reg30:
- case DW_OP_reg31:
- printf ("DW_OP_reg%d", op - DW_OP_reg0);
- break;
-
- case DW_OP_breg0:
- case DW_OP_breg1:
- case DW_OP_breg2:
- case DW_OP_breg3:
- case DW_OP_breg4:
- case DW_OP_breg5:
- case DW_OP_breg6:
- case DW_OP_breg7:
- case DW_OP_breg8:
- case DW_OP_breg9:
- case DW_OP_breg10:
- case DW_OP_breg11:
- case DW_OP_breg12:
- case DW_OP_breg13:
- case DW_OP_breg14:
- case DW_OP_breg15:
- case DW_OP_breg16:
- case DW_OP_breg17:
- case DW_OP_breg18:
- case DW_OP_breg19:
- case DW_OP_breg20:
- case DW_OP_breg21:
- case DW_OP_breg22:
- case DW_OP_breg23:
- case DW_OP_breg24:
- case DW_OP_breg25:
- case DW_OP_breg26:
- case DW_OP_breg27:
- case DW_OP_breg28:
- case DW_OP_breg29:
- case DW_OP_breg30:
- case DW_OP_breg31:
- val = read_leb128 (data, &bytes_read, 1);
- printf ("DW_OP_breg%d: %ld", op - DW_OP_breg0,
- val);
- data += bytes_read;
- break;
-
- case DW_OP_regx:
- val = read_leb128 (data, &bytes_read, 0);
- printf ("DW_OP_regx: %lu", val);
- data += bytes_read;
- break;
- case DW_OP_fbreg:
- need_frame_base = 1;
- val = read_leb128 (data, &bytes_read, 1);
- printf ("DW_OP_fbreg: %ld", val);
- data += bytes_read;
- break;
- case DW_OP_bregx:
- uvalue = read_leb128 (data, &bytes_read, 0);
- data += bytes_read;
- val = read_leb128 (data, &bytes_read, 1);
- printf ("DW_OP_bregx: %lu %ld", uvalue, val);
- data += bytes_read;
- break;
- case DW_OP_piece:
- val = read_leb128 (data, &bytes_read, 0);
- printf ("DW_OP_piece: %lu", val);
- data += bytes_read;
- break;
- case DW_OP_deref_size:
- val = byte_get (data++, 1);
- printf ("DW_OP_deref_size: %ld", (long) val);
- break;
- case DW_OP_xderef_size:
- val = byte_get (data++, 1);
- printf ("DW_OP_xderef_size: %ld", (long) val);
- break;
- case DW_OP_nop:
- printf ("DW_OP_nop");
- break;
-
- /* DWARF 3 extensions. */
- case DW_OP_push_object_address:
- printf ("DW_OP_push_object_address");
- break;
- case DW_OP_call2:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
- this ought to be an 8-byte wide computation. */
- val = (unsigned long)((long) byte_get (data, 2) + cu_offset);
- printf ("DW_OP_call2: <%lx>", (long) val);
- data += 2;
- break;
- case DW_OP_call4:
- /* XXX: Strictly speaking for 64-bit DWARF3 files
- this ought to be an 8-byte wide computation. */
- val = (unsigned long)((long) byte_get (data, 4) + cu_offset);
- printf ("DW_OP_call4: <%lx>", (long) val);
- data += 4;
- break;
- case DW_OP_call_ref:
- printf ("DW_OP_call_ref");
- break;
-
- /* GNU extensions. */
- case DW_OP_GNU_push_tls_address:
- printf ("DW_OP_GNU_push_tls_address");
- break;
-
- default:
- if (op >= DW_OP_lo_user
- && op <= DW_OP_hi_user)
- printf (_("(User defined location op)"));
- else
- printf (_("(Unknown location op)"));
- /* No way to tell where the next op is, so just bail. */
- return need_frame_base;
- }
-
- /* Separate the ops. */
- if (data < end)
- printf ("; ");
- }
-
- return need_frame_base;
-}
-
-static unsigned char *
-read_and_display_attr_value (unsigned long attribute,
- unsigned long form,
- unsigned char *data,
- unsigned long cu_offset,
- unsigned long pointer_size,
- unsigned long offset_size,
- int dwarf_version,
- debug_info *debug_info_p,
- int do_loc)
-{
- unsigned long uvalue = 0;
- unsigned char *block_start = NULL;
- unsigned int bytes_read;
- unsigned long val;
-
- switch (form)
- {
- default:
- break;
-
- case DW_FORM_ref_addr:
- if (dwarf_version == 2)
- {
- uvalue = byte_get (data, pointer_size);
- data += pointer_size;
- }
- else if (dwarf_version == 3)
- {
- uvalue = byte_get (data, offset_size);
- data += offset_size;
- }
- else
- {
- error (_("Internal error: DWARF version is not 2 or 3.\n"));
- }
- break;
-
- case DW_FORM_addr:
- uvalue = byte_get (data, pointer_size);
- if (!do_loc)
- value_hook(data, pointer_size, uvalue);
- data += pointer_size;
- break;
-
- case DW_FORM_strp:
- uvalue = byte_get (data, offset_size);
- data += offset_size;
- break;
-
- case DW_FORM_ref1:
- case DW_FORM_flag:
- case DW_FORM_data1:
- uvalue = byte_get (data++, 1);
- break;
-
- case DW_FORM_ref2:
- case DW_FORM_data2:
- uvalue = byte_get (data, 2);
- data += 2;
- break;
-
- case DW_FORM_ref4:
- case DW_FORM_data4:
- uvalue = byte_get (data, 4);
- data += 4;
- break;
-
- case DW_FORM_sdata:
- uvalue = read_leb128 (data, & bytes_read, 1);
- data += bytes_read;
- break;
-
- case DW_FORM_ref_udata:
- case DW_FORM_udata:
- uvalue = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
- break;
-
- case DW_FORM_indirect:
- form = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
- if (!do_loc)
- printf (" %s", get_FORM_name (form));
- return read_and_display_attr_value (attribute, form, data,
- cu_offset, pointer_size,
- offset_size, dwarf_version,
- debug_info_p, do_loc);
- }
-
- switch (form)
- {
- case DW_FORM_ref_addr:
- if (!do_loc)
- printf (" <#%lx>", uvalue);
- break;
-
- case DW_FORM_ref1:
- case DW_FORM_ref2:
- case DW_FORM_ref4:
- case DW_FORM_ref_udata:
- if (!do_loc)
- printf (" <%lx>", uvalue + cu_offset);
- break;
-
- case DW_FORM_data4:
- case DW_FORM_addr:
- if (!do_loc)
- printf (" %#lx", uvalue);
- break;
-
- case DW_FORM_flag:
- case DW_FORM_data1:
- case DW_FORM_data2:
- case DW_FORM_sdata:
- case DW_FORM_udata:
- if (!do_loc)
- printf (" %ld", uvalue);
- break;
-
- case DW_FORM_ref8:
- case DW_FORM_data8:
- if (!do_loc)
- {
- uvalue = byte_get (data, 4);
- printf (" %lx", uvalue);
- val = byte_get (data + 4, 4);
- printf (" %lx", val);
- }
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- {
- if (sizeof (uvalue) == 8)
- uvalue = byte_get (data, 8);
- else
- error (_("DW_FORM_data8 is unsupported when sizeof (unsigned long) != 8\n"));
- }
- data += 8;
- break;
-
- case DW_FORM_string:
- if (!do_loc)
- printf (" %s", data);
- data += strlen ((char *) data) + 1;
- break;
-
- case DW_FORM_block:
- uvalue = read_leb128 (data, & bytes_read, 0);
- block_start = data + bytes_read;
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue);
- break;
-
- case DW_FORM_block1:
- uvalue = byte_get (data, 1);
- block_start = data + 1;
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue);
- break;
-
- case DW_FORM_block2:
- uvalue = byte_get (data, 2);
- block_start = data + 2;
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue);
- break;
-
- case DW_FORM_block4:
- uvalue = byte_get (data, 4);
- block_start = data + 4;
- if (do_loc)
- data = block_start + uvalue;
- else
- data = display_block (block_start, uvalue);
- break;
-
- case DW_FORM_strp:
- if (!do_loc)
- printf (_(" (indirect string, offset: 0x%lx): %s"),
- uvalue, fetch_indirect_string (uvalue));
- break;
-
- case DW_FORM_indirect:
- /* Handled above. */
- break;
-
- default:
- warn (_("Unrecognized form: %lu\n"), form);
- break;
- }
-
- /* For some attributes we can display further information. */
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- {
- switch (attribute)
- {
- case DW_AT_frame_base:
- have_frame_base = 1;
- case DW_AT_location:
- case DW_AT_data_member_location:
- case DW_AT_vtable_elem_location:
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_stride:
- case DW_AT_upper_bound:
- case DW_AT_lower_bound:
- if (form == DW_FORM_data4 || form == DW_FORM_data8)
- {
- /* Process location list. */
- unsigned int max = debug_info_p->max_loc_offsets;
- unsigned int num = debug_info_p->num_loc_offsets;
-
- if (max == 0 || num >= max)
- {
-#ifdef SORT_LOCATION_LIST_OFFSETS
- if (max == 0)
- debug_info_p->last_loc_offset = uvalue;
-#endif
- max += 1024;
- debug_info_p->loc_offsets
- = xcrealloc (debug_info_p->loc_offsets,
- max, sizeof (*debug_info_p->loc_offsets));
- debug_info_p->have_frame_base
- = xcrealloc (debug_info_p->have_frame_base,
- max, sizeof (*debug_info_p->have_frame_base));
- debug_info_p->max_loc_offsets = max;
- }
- debug_info_p->loc_offsets [num] = uvalue;
- debug_info_p->have_frame_base [num] = have_frame_base;
- debug_info_p->num_loc_offsets++;
-#ifdef SORT_LOCATION_LIST_OFFSETS
- if (debug_info_p->last_loc_offset != -1UL &&
- debug_info_p->last_loc_offset > uvalue)
- {
- /* The location offsets are not in ascending order! */
- debug_info_p->last_loc_offset = -1UL;
- }
-#endif
- }
- break;
-
- case DW_AT_low_pc:
- if (need_base_address)
- debug_info_p->base_address = uvalue;
- break;
-
- case DW_AT_ranges:
- if (form == DW_FORM_data4 || form == DW_FORM_data8)
- {
- /* Process range list. */
- unsigned int max = debug_info_p->max_range_lists;
- unsigned int num = debug_info_p->num_range_lists;
-
- if (max == 0 || num >= max)
- {
- max += 1024;
- debug_info_p->range_lists
- = xcrealloc (debug_info_p->range_lists,
- max, sizeof (*debug_info_p->range_lists));
- debug_info_p->max_range_lists = max;
- }
- debug_info_p->range_lists [num] = uvalue;
- debug_info_p->num_range_lists++;
- }
- break;
-
- default:
- break;
- }
- }
-
- if (do_loc)
- return data;
-
- printf ("\t");
-
- switch (attribute)
- {
- case DW_AT_inline:
- switch (uvalue)
- {
- case DW_INL_not_inlined:
- printf (_("(not inlined)"));
- break;
- case DW_INL_inlined:
- printf (_("(inlined)"));
- break;
- case DW_INL_declared_not_inlined:
- printf (_("(declared as inline but ignored)"));
- break;
- case DW_INL_declared_inlined:
- printf (_("(declared as inline and inlined)"));
- break;
- default:
- printf (_(" (Unknown inline attribute value: %lx)"), uvalue);
- break;
- }
- break;
-
- case DW_AT_language:
- switch (uvalue)
- {
- case DW_LANG_C: printf ("(non-ANSI C)"); break;
- case DW_LANG_C89: printf ("(ANSI C)"); break;
- case DW_LANG_C_plus_plus: printf ("(C++)"); break;
- case DW_LANG_Fortran77: printf ("(FORTRAN 77)"); break;
- case DW_LANG_Fortran90: printf ("(Fortran 90)"); break;
- case DW_LANG_Modula2: printf ("(Modula 2)"); break;
- case DW_LANG_Pascal83: printf ("(ANSI Pascal)"); break;
- case DW_LANG_Ada83: printf ("(Ada)"); break;
- case DW_LANG_Cobol74: printf ("(Cobol 74)"); break;
- case DW_LANG_Cobol85: printf ("(Cobol 85)"); break;
- /* DWARF 2.1 values. */
- case DW_LANG_C99: printf ("(ANSI C99)"); break;
- case DW_LANG_Ada95: printf ("(ADA 95)"); break;
- case DW_LANG_Fortran95: printf ("(Fortran 95)"); break;
- /* MIPS extension. */
- case DW_LANG_Mips_Assembler: printf ("(MIPS assembler)"); break;
- /* UPC extension. */
- case DW_LANG_Upc: printf ("(Unified Parallel C)"); break;
- default:
- printf ("(Unknown: %lx)", uvalue);
- break;
- }
- break;
-
- case DW_AT_encoding:
- switch (uvalue)
- {
- case DW_ATE_void: printf ("(void)"); break;
- case DW_ATE_address: printf ("(machine address)"); break;
- case DW_ATE_boolean: printf ("(boolean)"); break;
- case DW_ATE_complex_float: printf ("(complex float)"); break;
- case DW_ATE_float: printf ("(float)"); break;
- case DW_ATE_signed: printf ("(signed)"); break;
- case DW_ATE_signed_char: printf ("(signed char)"); break;
- case DW_ATE_unsigned: printf ("(unsigned)"); break;
- case DW_ATE_unsigned_char: printf ("(unsigned char)"); break;
- /* DWARF 2.1 value. */
- case DW_ATE_imaginary_float: printf ("(imaginary float)"); break;
- case DW_ATE_decimal_float: printf ("(decimal float)"); break;
- default:
- if (uvalue >= DW_ATE_lo_user
- && uvalue <= DW_ATE_hi_user)
- printf ("(user defined type)");
- else
- printf ("(unknown type)");
- break;
- }
- break;
-
- case DW_AT_accessibility:
- switch (uvalue)
- {
- case DW_ACCESS_public: printf ("(public)"); break;
- case DW_ACCESS_protected: printf ("(protected)"); break;
- case DW_ACCESS_private: printf ("(private)"); break;
- default:
- printf ("(unknown accessibility)");
- break;
- }
- break;
-
- case DW_AT_visibility:
- switch (uvalue)
- {
- case DW_VIS_local: printf ("(local)"); break;
- case DW_VIS_exported: printf ("(exported)"); break;
- case DW_VIS_qualified: printf ("(qualified)"); break;
- default: printf ("(unknown visibility)"); break;
- }
- break;
-
- case DW_AT_virtuality:
- switch (uvalue)
- {
- case DW_VIRTUALITY_none: printf ("(none)"); break;
- case DW_VIRTUALITY_virtual: printf ("(virtual)"); break;
- case DW_VIRTUALITY_pure_virtual:printf ("(pure_virtual)"); break;
- default: printf ("(unknown virtuality)"); break;
- }
- break;
-
- case DW_AT_identifier_case:
- switch (uvalue)
- {
- case DW_ID_case_sensitive: printf ("(case_sensitive)"); break;
- case DW_ID_up_case: printf ("(up_case)"); break;
- case DW_ID_down_case: printf ("(down_case)"); break;
- case DW_ID_case_insensitive: printf ("(case_insensitive)"); break;
- default: printf ("(unknown case)"); break;
- }
- break;
-
- case DW_AT_calling_convention:
- switch (uvalue)
- {
- case DW_CC_normal: printf ("(normal)"); break;
- case DW_CC_program: printf ("(program)"); break;
- case DW_CC_nocall: printf ("(nocall)"); break;
- default:
- if (uvalue >= DW_CC_lo_user
- && uvalue <= DW_CC_hi_user)
- printf ("(user defined)");
- else
- printf ("(unknown convention)");
- }
- break;
-
- case DW_AT_ordering:
- switch (uvalue)
- {
- case -1: printf ("(undefined)"); break;
- case 0: printf ("(row major)"); break;
- case 1: printf ("(column major)"); break;
- }
- break;
-
- case DW_AT_frame_base:
- have_frame_base = 1;
- case DW_AT_location:
- case DW_AT_data_member_location:
- case DW_AT_vtable_elem_location:
- case DW_AT_allocated:
- case DW_AT_associated:
- case DW_AT_data_location:
- case DW_AT_stride:
- case DW_AT_upper_bound:
- case DW_AT_lower_bound:
- if (block_start)
- {
- int need_frame_base;
-
- printf ("(");
- need_frame_base = decode_location_expression (block_start,
- pointer_size,
- uvalue,
- cu_offset);
- printf (")");
- if (need_frame_base && !have_frame_base)
- printf (_(" [without DW_AT_frame_base]"));
- }
- else if (form == DW_FORM_data4 || form == DW_FORM_data8)
- printf (_("(location list)"));
-
- break;
-
- default:
- break;
- }
-
- return data;
-}
-
-static char *
-get_AT_name (unsigned long attribute)
-{
- switch (attribute)
- {
- case DW_AT_sibling: return "DW_AT_sibling";
- case DW_AT_location: return "DW_AT_location";
- case DW_AT_name: return "DW_AT_name";
- case DW_AT_ordering: return "DW_AT_ordering";
- case DW_AT_subscr_data: return "DW_AT_subscr_data";
- case DW_AT_byte_size: return "DW_AT_byte_size";
- case DW_AT_bit_offset: return "DW_AT_bit_offset";
- case DW_AT_bit_size: return "DW_AT_bit_size";
- case DW_AT_element_list: return "DW_AT_element_list";
- case DW_AT_stmt_list: return "DW_AT_stmt_list";
- case DW_AT_low_pc: return "DW_AT_low_pc";
- case DW_AT_high_pc: return "DW_AT_high_pc";
- case DW_AT_language: return "DW_AT_language";
- case DW_AT_member: return "DW_AT_member";
- case DW_AT_discr: return "DW_AT_discr";
- case DW_AT_discr_value: return "DW_AT_discr_value";
- case DW_AT_visibility: return "DW_AT_visibility";
- case DW_AT_import: return "DW_AT_import";
- case DW_AT_string_length: return "DW_AT_string_length";
- case DW_AT_common_reference: return "DW_AT_common_reference";
- case DW_AT_comp_dir: return "DW_AT_comp_dir";
- case DW_AT_const_value: return "DW_AT_const_value";
- case DW_AT_containing_type: return "DW_AT_containing_type";
- case DW_AT_default_value: return "DW_AT_default_value";
- case DW_AT_inline: return "DW_AT_inline";
- case DW_AT_is_optional: return "DW_AT_is_optional";
- case DW_AT_lower_bound: return "DW_AT_lower_bound";
- case DW_AT_producer: return "DW_AT_producer";
- case DW_AT_prototyped: return "DW_AT_prototyped";
- case DW_AT_return_addr: return "DW_AT_return_addr";
- case DW_AT_start_scope: return "DW_AT_start_scope";
- case DW_AT_stride_size: return "DW_AT_stride_size";
- case DW_AT_upper_bound: return "DW_AT_upper_bound";
- case DW_AT_abstract_origin: return "DW_AT_abstract_origin";
- case DW_AT_accessibility: return "DW_AT_accessibility";
- case DW_AT_address_class: return "DW_AT_address_class";
- case DW_AT_artificial: return "DW_AT_artificial";
- case DW_AT_base_types: return "DW_AT_base_types";
- case DW_AT_calling_convention: return "DW_AT_calling_convention";
- case DW_AT_count: return "DW_AT_count";
- case DW_AT_data_member_location: return "DW_AT_data_member_location";
- case DW_AT_decl_column: return "DW_AT_decl_column";
- case DW_AT_decl_file: return "DW_AT_decl_file";
- case DW_AT_decl_line: return "DW_AT_decl_line";
- case DW_AT_declaration: return "DW_AT_declaration";
- case DW_AT_discr_list: return "DW_AT_discr_list";
- case DW_AT_encoding: return "DW_AT_encoding";
- case DW_AT_external: return "DW_AT_external";
- case DW_AT_frame_base: return "DW_AT_frame_base";
- case DW_AT_friend: return "DW_AT_friend";
- case DW_AT_identifier_case: return "DW_AT_identifier_case";
- case DW_AT_macro_info: return "DW_AT_macro_info";
- case DW_AT_namelist_items: return "DW_AT_namelist_items";
- case DW_AT_priority: return "DW_AT_priority";
- case DW_AT_segment: return "DW_AT_segment";
- case DW_AT_specification: return "DW_AT_specification";
- case DW_AT_static_link: return "DW_AT_static_link";
- case DW_AT_type: return "DW_AT_type";
- case DW_AT_use_location: return "DW_AT_use_location";
- case DW_AT_variable_parameter: return "DW_AT_variable_parameter";
- case DW_AT_virtuality: return "DW_AT_virtuality";
- case DW_AT_vtable_elem_location: return "DW_AT_vtable_elem_location";
- /* DWARF 2.1 values. */
- case DW_AT_allocated: return "DW_AT_allocated";
- case DW_AT_associated: return "DW_AT_associated";
- case DW_AT_data_location: return "DW_AT_data_location";
- case DW_AT_stride: return "DW_AT_stride";
- case DW_AT_entry_pc: return "DW_AT_entry_pc";
- case DW_AT_use_UTF8: return "DW_AT_use_UTF8";
- case DW_AT_extension: return "DW_AT_extension";
- case DW_AT_ranges: return "DW_AT_ranges";
- case DW_AT_trampoline: return "DW_AT_trampoline";
- case DW_AT_call_column: return "DW_AT_call_column";
- case DW_AT_call_file: return "DW_AT_call_file";
- case DW_AT_call_line: return "DW_AT_call_line";
- /* SGI/MIPS extensions. */
- case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde";
- case DW_AT_MIPS_loop_begin: return "DW_AT_MIPS_loop_begin";
- case DW_AT_MIPS_tail_loop_begin: return "DW_AT_MIPS_tail_loop_begin";
- case DW_AT_MIPS_epilog_begin: return "DW_AT_MIPS_epilog_begin";
- case DW_AT_MIPS_loop_unroll_factor: return "DW_AT_MIPS_loop_unroll_factor";
- case DW_AT_MIPS_software_pipeline_depth:
- return "DW_AT_MIPS_software_pipeline_depth";
- case DW_AT_MIPS_linkage_name: return "DW_AT_MIPS_linkage_name";
- case DW_AT_MIPS_stride: return "DW_AT_MIPS_stride";
- case DW_AT_MIPS_abstract_name: return "DW_AT_MIPS_abstract_name";
- case DW_AT_MIPS_clone_origin: return "DW_AT_MIPS_clone_origin";
- case DW_AT_MIPS_has_inlines: return "DW_AT_MIPS_has_inlines";
- /* GNU extensions. */
- case DW_AT_sf_names: return "DW_AT_sf_names";
- case DW_AT_src_info: return "DW_AT_src_info";
- case DW_AT_mac_info: return "DW_AT_mac_info";
- case DW_AT_src_coords: return "DW_AT_src_coords";
- case DW_AT_body_begin: return "DW_AT_body_begin";
- case DW_AT_body_end: return "DW_AT_body_end";
- case DW_AT_GNU_vector: return "DW_AT_GNU_vector";
- /* UPC extension. */
- case DW_AT_upc_threads_scaled: return "DW_AT_upc_threads_scaled";
- default:
- {
- static char buffer[100];
-
- snprintf (buffer, sizeof (buffer), _("Unknown AT value: %lx"),
- attribute);
- return buffer;
- }
- }
-}
-
-static unsigned char *
-read_and_display_attr (unsigned long attribute,
- unsigned long form,
- unsigned char *data,
- unsigned long cu_offset,
- unsigned long pointer_size,
- unsigned long offset_size,
- int dwarf_version,
- debug_info *debug_info_p,
- int do_loc)
-{
- if (!do_loc)
- printf (" %-18s:", get_AT_name (attribute));
- data = read_and_display_attr_value (attribute, form, data, cu_offset,
- pointer_size, offset_size,
- dwarf_version, debug_info_p,
- do_loc);
- if (!do_loc)
- printf ("\n");
- return data;
-}
-
-
-/* Process the contents of a .debug_info section. If do_loc is non-zero
- then we are scanning for location lists and we do not want to display
- anything to the user. */
-
-static int
-process_debug_info (struct dwarf_section *section, void *file,
- int do_loc)
-{
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
- unsigned char *section_begin;
- unsigned int unit;
- unsigned int num_units = 0;
-
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- {
- unsigned long length;
-
- /* First scan the section to get the number of comp units. */
- for (section_begin = start, num_units = 0; section_begin < end;
- num_units ++)
- {
- /* Read the first 4 bytes. For a 32-bit DWARF section, this
- will be the length. For a 64-bit DWARF section, it'll be
- the escape code 0xffffffff followed by an 8 byte length. */
- length = byte_get (section_begin, 4);
-
- if (length == 0xffffffff)
- {
- length = byte_get (section_begin + 4, 8);
- section_begin += length + 12;
- }
- else
- section_begin += length + 4;
- }
-
- if (num_units == 0)
- {
- error (_("No comp units in %s section ?"), section->name);
- return 0;
- }
-
- /* Then allocate an array to hold the information. */
- debug_information = cmalloc (num_units,
- sizeof (* debug_information));
- if (debug_information == NULL)
- {
- error (_("Not enough memory for a debug info array of %u entries.\n"),
- num_units);
- return 0;
- }
- }
-
- if (!do_loc)
- {
- printf (_("The section %s contains:\n\n"), section->name);
-
- load_debug_section (str, file);
- }
-
- load_debug_section (abbrev, file);
- if (debug_displays [abbrev].section.start == NULL)
- {
- warn (_("Unable to locate %s section!\n"),
- debug_displays [abbrev].section.name);
- return 0;
- }
-
- for (section_begin = start, unit = 0; start < end; unit++)
- {
- DWARF2_Internal_CompUnit compunit;
- unsigned char *hdrptr;
- unsigned char *cu_abbrev_offset_ptr;
- unsigned char *tags;
- int level;
- unsigned long cu_offset;
- int offset_size;
- int initial_length_size;
-
- hdrptr = start;
-
- compunit.cu_length = byte_get (hdrptr, 4);
- hdrptr += 4;
-
- if (compunit.cu_length == 0xffffffff)
- {
- compunit.cu_length = byte_get (hdrptr, 8);
- hdrptr += 8;
- offset_size = 8;
- initial_length_size = 12;
- }
- else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- compunit.cu_version = byte_get (hdrptr, 2);
- hdrptr += 2;
-
- cu_offset = start - section_begin;
- start += compunit.cu_length + initial_length_size;
-
- cu_abbrev_offset_ptr = hdrptr;
- compunit.cu_abbrev_offset = byte_get (hdrptr, offset_size);
- hdrptr += offset_size;
-
- compunit.cu_pointer_size = byte_get (hdrptr, 1);
- hdrptr += 1;
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- {
- debug_information [unit].cu_offset = cu_offset;
- debug_information [unit].pointer_size
- = compunit.cu_pointer_size;
- debug_information [unit].base_address = 0;
- debug_information [unit].loc_offsets = NULL;
- debug_information [unit].have_frame_base = NULL;
- debug_information [unit].max_loc_offsets = 0;
- debug_information [unit].num_loc_offsets = 0;
-#ifdef SORT_LOCATION_LIST_OFFSETS
- debug_information [unit].last_loc_offset = 0;
-#endif
- debug_information [unit].range_lists = NULL;
- debug_information [unit].max_range_lists= 0;
- debug_information [unit].num_range_lists = 0;
- }
-
- tags = hdrptr;
-
- if (!do_loc)
- {
- printf (_(" Compilation Unit @ offset 0x%lx:\n"), cu_offset);
- printf (_(" Length: %ld\n"), compunit.cu_length);
- printf (_(" Version: %d\n"), compunit.cu_version);
- printf (_(" Abbrev Offset: %ld\n"), compunit.cu_abbrev_offset);
- printf (_(" Pointer Size: %d\n"), compunit.cu_pointer_size);
- }
-
- if (compunit.cu_version != 2 && compunit.cu_version != 3)
- {
- warn (_("Only version 2 and 3 DWARF debug information is currently supported.\n"));
- continue;
- }
-
- free_abbrevs ();
-
- /* Process the abbrevs used by this compilation unit. DWARF
- sections under Mach-O have non-zero addresses. */
- process_abbrev_section
- ((unsigned char *) debug_displays [abbrev].section.start
- + compunit.cu_abbrev_offset - debug_displays [abbrev].section.address,
- (unsigned char *) debug_displays [abbrev].section.start
- + debug_displays [abbrev].section.size);
-
- level = 0;
- while (tags < start)
- {
- unsigned int bytes_read;
- unsigned long abbrev_number;
- abbrev_entry *entry;
- abbrev_attr *attr;
-
- abbrev_number = read_leb128 (tags, & bytes_read, 0);
- tags += bytes_read;
-
- /* A null DIE marks the end of a list of children. */
- if (abbrev_number == 0)
- {
- --level;
- continue;
- }
-
- /* Scan through the abbreviation list until we reach the
- correct entry. */
- for (entry = first_abbrev;
- entry && entry->entry != abbrev_number;
- entry = entry->next)
- continue;
-
- if (entry == NULL)
- {
- warn (_("Unable to locate entry %lu in the abbreviation table\n"),
- abbrev_number);
- return 0;
- }
-
- if (!do_loc)
- printf (_(" <%d><%lx>: Abbrev Number: %lu (%s)\n"),
- level,
- (unsigned long) (tags - section_begin
- - bytes_read),
- abbrev_number,
- get_TAG_name (entry->tag));
-
- switch (entry->tag)
- {
- default:
- need_base_address = 0;
- break;
- case DW_TAG_compile_unit:
- need_base_address = 1;
- break;
- case DW_TAG_entry_point:
- case DW_TAG_inlined_subroutine:
- case DW_TAG_subprogram:
- need_base_address = 0;
- /* Assuming that there is no DW_AT_frame_base. */
- have_frame_base = 0;
- break;
- }
-
- for (attr = entry->first_attr; attr; attr = attr->next)
- tags = read_and_display_attr (attr->attribute,
- attr->form,
- tags, cu_offset,
- compunit.cu_pointer_size,
- offset_size,
- compunit.cu_version,
- &debug_information [unit],
- do_loc);
-
- if (entry->children)
- ++level;
- }
- }
-
- /* Set num_debug_info_entries here so that it can be used to check if
- we need to process .debug_loc and .debug_ranges sections. */
- if ((do_loc || do_debug_loc || do_debug_ranges)
- && num_debug_info_entries == 0)
- num_debug_info_entries = num_units;
-
- if (!do_loc)
- {
- printf ("\n");
- }
-
- return 1;
-}
-
-/* Locate and scan the .debug_info section in the file and record the pointer
- sizes and offsets for the compilation units in it. Usually an executable
- will have just one pointer size, but this is not guaranteed, and so we try
- not to make any assumptions. Returns zero upon failure, or the number of
- compilation units upon success. */
-
-static unsigned int
-load_debug_info (void * file)
-{
- /* Reset the last pointer size so that we can issue correct error
- messages if we are displaying the contents of more than one section. */
- last_pointer_size = 0;
- warned_about_missing_comp_units = FALSE;
-
- /* If we already have the information there is nothing else to do. */
- if (num_debug_info_entries > 0)
- return num_debug_info_entries;
-
- if (load_debug_section (info, file)
- && process_debug_info (&debug_displays [info].section, file, 1))
- return num_debug_info_entries;
- else
- return 0;
-}
-
-static int
-display_debug_lines (struct dwarf_section *section, void *file)
-{
- unsigned char *start = section->start;
- unsigned char *data = start;
- unsigned char *end = start + section->size;
- unsigned long val;
-
- printf (_("\nDump of debug contents of section %s:\n\n"),
- section->name);
-
- load_debug_info (file);
-
- while (data < end)
- {
- DWARF2_Internal_LineInfo info;
- unsigned char *standard_opcodes;
- unsigned char *end_of_sequence;
- unsigned char *hdrptr;
- int initial_length_size;
- int offset_size;
- int i;
-
- hdrptr = data;
-
- /* Check the length of the block. */
- info.li_length = byte_get (hdrptr, 4);
- hdrptr += 4;
-
- if (info.li_length == 0xffffffff)
- {
- /* This section is 64-bit DWARF 3. */
- info.li_length = byte_get (hdrptr, 8);
- hdrptr += 8;
- offset_size = 8;
- initial_length_size = 12;
- }
- else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- if (info.li_length + initial_length_size > section->size)
- {
- warn
- (_("The line info appears to be corrupt - the section is too small\n"));
- return 0;
- }
-
- /* Check its version number. */
- info.li_version = byte_get (hdrptr, 2);
- hdrptr += 2;
- if (info.li_version != 2 && info.li_version != 3)
- {
- warn (_("Only DWARF version 2 and 3 line info is currently supported.\n"));
- return 0;
- }
-
- info.li_prologue_length = byte_get (hdrptr, offset_size);
- hdrptr += offset_size;
- info.li_min_insn_length = byte_get (hdrptr, 1);
- hdrptr++;
- info.li_default_is_stmt = byte_get (hdrptr, 1);
- hdrptr++;
- info.li_line_base = byte_get (hdrptr, 1);
- hdrptr++;
- info.li_line_range = byte_get (hdrptr, 1);
- hdrptr++;
- info.li_opcode_base = byte_get (hdrptr, 1);
- hdrptr++;
-
- /* Sign extend the line base field. */
- info.li_line_base <<= 24;
- info.li_line_base >>= 24;
-
- printf (_(" Length: %ld\n"), info.li_length);
- printf (_(" DWARF Version: %d\n"), info.li_version);
- printf (_(" Prologue Length: %d\n"), info.li_prologue_length);
- printf (_(" Minimum Instruction Length: %d\n"), info.li_min_insn_length);
- printf (_(" Initial value of 'is_stmt': %d\n"), info.li_default_is_stmt);
- printf (_(" Line Base: %d\n"), info.li_line_base);
- printf (_(" Line Range: %d\n"), info.li_line_range);
- printf (_(" Opcode Base: %d\n"), info.li_opcode_base);
-
- end_of_sequence = data + info.li_length + initial_length_size;
-
- reset_state_machine (info.li_default_is_stmt);
-
- /* Display the contents of the Opcodes table. */
- standard_opcodes = hdrptr;
-
- printf (_("\n Opcodes:\n"));
-
- for (i = 1; i < info.li_opcode_base; i++)
- printf (_(" Opcode %d has %d args\n"), i, standard_opcodes[i - 1]);
-
- /* Display the contents of the Directory table. */
- data = standard_opcodes + info.li_opcode_base - 1;
-
- if (*data == 0)
- printf (_("\n The Directory Table is empty.\n"));
- else
- {
- printf (_("\n The Directory Table:\n"));
-
- while (*data != 0)
- {
- printf (_(" %s\n"), data);
-
- data += strlen ((char *) data) + 1;
- }
- }
-
- /* Skip the NUL at the end of the table. */
- data++;
-
- /* Display the contents of the File Name table. */
- if (*data == 0)
- printf (_("\n The File Name Table is empty.\n"));
- else
- {
- printf (_("\n The File Name Table:\n"));
- printf (_(" Entry\tDir\tTime\tSize\tName\n"));
-
- while (*data != 0)
- {
- unsigned char *name;
- unsigned int bytes_read;
-
- ++state_machine_regs.last_file_entry;
- printf (_(" %d\t"), state_machine_regs.last_file_entry);
- name = data;
-
- data += strlen ((char *) data) + 1;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- data += bytes_read;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- data += bytes_read;
- val = read_leb128 (data, & bytes_read, 0);
- printf (_("%lu\t"), val);
- data += bytes_read;
- printf (_("%s\n"), name);
- }
- }
-
- /* Skip the NUL at the end of the table. */
- data++;
-
- /* Now display the statements. */
- printf (_("\n Line Number Statements:\n"));
-
- while (data < end_of_sequence)
- {
- unsigned char op_code;
- int adv;
- unsigned long int uladv;
- unsigned int bytes_read;
-
- op_code = *data++;
-
- if (op_code >= info.li_opcode_base)
- {
- op_code -= info.li_opcode_base;
- uladv = (op_code / info.li_line_range) * info.li_min_insn_length;
- state_machine_regs.address += uladv;
- printf (_(" Special opcode %d: advance Address by %lu to 0x%lx"),
- op_code, uladv, state_machine_regs.address);
- adv = (op_code % info.li_line_range) + info.li_line_base;
- state_machine_regs.line += adv;
- printf (_(" and Line by %d to %d\n"),
- adv, state_machine_regs.line);
- }
- else switch (op_code)
- {
- case DW_LNS_extended_op:
- data += process_extended_line_op (data, info.li_default_is_stmt);
- break;
-
- case DW_LNS_copy:
- printf (_(" Copy\n"));
- break;
-
- case DW_LNS_advance_pc:
- uladv = read_leb128 (data, & bytes_read, 0);
- uladv *= info.li_min_insn_length;
- data += bytes_read;
- state_machine_regs.address += uladv;
- printf (_(" Advance PC by %lu to 0x%lx\n"), uladv,
- state_machine_regs.address);
- break;
-
- case DW_LNS_advance_line:
- adv = read_leb128 (data, & bytes_read, 1);
- data += bytes_read;
- state_machine_regs.line += adv;
- printf (_(" Advance Line by %d to %d\n"), adv,
- state_machine_regs.line);
- break;
-
- case DW_LNS_set_file:
- adv = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
- printf (_(" Set File Name to entry %d in the File Name Table\n"),
- adv);
- state_machine_regs.file = adv;
- break;
-
- case DW_LNS_set_column:
- uladv = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
- printf (_(" Set column to %lu\n"), uladv);
- state_machine_regs.column = uladv;
- break;
-
- case DW_LNS_negate_stmt:
- adv = state_machine_regs.is_stmt;
- adv = ! adv;
- printf (_(" Set is_stmt to %d\n"), adv);
- state_machine_regs.is_stmt = adv;
- break;
-
- case DW_LNS_set_basic_block:
- printf (_(" Set basic block\n"));
- state_machine_regs.basic_block = 1;
- break;
-
- case DW_LNS_const_add_pc:
- uladv = (((255 - info.li_opcode_base) / info.li_line_range)
- * info.li_min_insn_length);
- state_machine_regs.address += uladv;
- printf (_(" Advance PC by constant %lu to 0x%lx\n"), uladv,
- state_machine_regs.address);
- break;
-
- case DW_LNS_fixed_advance_pc:
- uladv = byte_get (data, 2);
- data += 2;
- state_machine_regs.address += uladv;
- printf (_(" Advance PC by fixed size amount %lu to 0x%lx\n"),
- uladv, state_machine_regs.address);
- break;
-
- case DW_LNS_set_prologue_end:
- printf (_(" Set prologue_end to true\n"));
- break;
-
- case DW_LNS_set_epilogue_begin:
- printf (_(" Set epilogue_begin to true\n"));
- break;
-
- case DW_LNS_set_isa:
- uladv = read_leb128 (data, & bytes_read, 0);
- data += bytes_read;
- printf (_(" Set ISA to %lu\n"), uladv);
- break;
-
- default:
- printf (_(" Unknown opcode %d with operands: "), op_code);
-
- for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
- {
- val = read_leb128 (data, &bytes_read, 0);
- printf ("0x%lx%s", val,
- i == 1 ? "" : ", ");
- data += bytes_read;
- }
- putchar ('\n');
- break;
- }
- }
- putchar ('\n');
- }
-
- return 1;
-}
-
-static int
-display_debug_pubnames (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- DWARF2_Internal_PubNames pubnames;
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
-
- printf (_("Contents of the %s section:\n\n"), section->name);
-
- while (start < end)
- {
- unsigned char *data;
- unsigned long offset;
- int offset_size, initial_length_size;
-
- data = start;
-
- pubnames.pn_length = byte_get (data, 4);
- data += 4;
- if (pubnames.pn_length == 0xffffffff)
- {
- pubnames.pn_length = byte_get (data, 8);
- data += 8;
- offset_size = 8;
- initial_length_size = 12;
- }
- else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- pubnames.pn_version = byte_get (data, 2);
- data += 2;
- pubnames.pn_offset = byte_get (data, offset_size);
- data += offset_size;
- pubnames.pn_size = byte_get (data, offset_size);
- data += offset_size;
-
- start += pubnames.pn_length + initial_length_size;
-
- if (pubnames.pn_version != 2 && pubnames.pn_version != 3)
- {
- static int warned = 0;
-
- if (! warned)
- {
- warn (_("Only DWARF 2 and 3 pubnames are currently supported\n"));
- warned = 1;
- }
-
- continue;
- }
-
- printf (_(" Length: %ld\n"),
- pubnames.pn_length);
- printf (_(" Version: %d\n"),
- pubnames.pn_version);
- printf (_(" Offset into .debug_info section: %ld\n"),
- pubnames.pn_offset);
- printf (_(" Size of area in .debug_info section: %ld\n"),
- pubnames.pn_size);
-
- printf (_("\n Offset\tName\n"));
-
- do
- {
- offset = byte_get (data, offset_size);
-
- if (offset != 0)
- {
- data += offset_size;
- printf (" %-6ld\t\t%s\n", offset, data);
- data += strlen ((char *) data) + 1;
- }
- }
- while (offset != 0);
- }
-
- printf ("\n");
- return 1;
-}
-
-static int
-display_debug_macinfo (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
- unsigned char *curr = start;
- unsigned int bytes_read;
- enum dwarf_macinfo_record_type op;
-
- printf (_("Contents of the %s section:\n\n"), section->name);
-
- while (curr < end)
- {
- unsigned int lineno;
- const char *string;
-
- op = *curr;
- curr++;
-
- switch (op)
- {
- case DW_MACINFO_start_file:
- {
- unsigned int filenum;
-
- lineno = read_leb128 (curr, & bytes_read, 0);
- curr += bytes_read;
- filenum = read_leb128 (curr, & bytes_read, 0);
- curr += bytes_read;
-
- printf (_(" DW_MACINFO_start_file - lineno: %d filenum: %d\n"),
- lineno, filenum);
- }
- break;
-
- case DW_MACINFO_end_file:
- printf (_(" DW_MACINFO_end_file\n"));
- break;
-
- case DW_MACINFO_define:
- lineno = read_leb128 (curr, & bytes_read, 0);
- curr += bytes_read;
- string = (char *) curr;
- curr += strlen (string) + 1;
- printf (_(" DW_MACINFO_define - lineno : %d macro : %s\n"),
- lineno, string);
- break;
-
- case DW_MACINFO_undef:
- lineno = read_leb128 (curr, & bytes_read, 0);
- curr += bytes_read;
- string = (char *) curr;
- curr += strlen (string) + 1;
- printf (_(" DW_MACINFO_undef - lineno : %d macro : %s\n"),
- lineno, string);
- break;
-
- case DW_MACINFO_vendor_ext:
- {
- unsigned int constant;
-
- constant = read_leb128 (curr, & bytes_read, 0);
- curr += bytes_read;
- string = (char *) curr;
- curr += strlen (string) + 1;
- printf (_(" DW_MACINFO_vendor_ext - constant : %d string : %s\n"),
- constant, string);
- }
- break;
- }
- }
-
- return 1;
-}
-
-static int
-display_debug_abbrev (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- abbrev_entry *entry;
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
-
- printf (_("Contents of the %s section:\n\n"), section->name);
-
- do
- {
- free_abbrevs ();
-
- start = process_abbrev_section (start, end);
-
- if (first_abbrev == NULL)
- continue;
-
- printf (_(" Number TAG\n"));
-
- for (entry = first_abbrev; entry; entry = entry->next)
- {
- abbrev_attr *attr;
-
- printf (_(" %ld %s [%s]\n"),
- entry->entry,
- get_TAG_name (entry->tag),
- entry->children ? _("has children") : _("no children"));
-
- for (attr = entry->first_attr; attr; attr = attr->next)
- printf (_(" %-18s %s\n"),
- get_AT_name (attr->attribute),
- get_FORM_name (attr->form));
- }
- }
- while (start);
-
- printf ("\n");
-
- return 1;
-}
-
-#ifdef SORT_LOCATION_LIST_OFFSETS
-static int compare_loc_offsets(const void *l, const void *r)
-{
- return *(long *)l - *(long *)r;
-}
-#endif
-
-static int
-display_debug_loc (struct dwarf_section *section, void *file)
-{
- unsigned char *start = section->start;
- unsigned char *section_end;
- unsigned long bytes;
- unsigned char *section_begin = start;
- unsigned int first = 0;
- unsigned int i;
- unsigned int j;
- int seen_first_offset = 0;
- unsigned char *next, *last_overlap;
-
- bytes = section->size;
- section_end = start + bytes;
-
- if (bytes == 0)
- {
- printf (_("\nThe %s section is empty.\n"), section->name);
- return 0;
- }
-
- load_debug_info (file);
-
- {
- unsigned int num_loc_list = 0;
- unsigned long last_offset = 0;
- int use_debug_info = 1;
- /* Check the order of location list in .debug_info section. If
- offsets of location lists are in the ascending order, we can
- use `debug_information' directly. */
- for (i = 0; i < num_debug_info_entries; i++)
- {
- unsigned int num;
-
- num = debug_information [i].num_loc_offsets;
- num_loc_list += num;
- ASSERT(num_loc_list == 0 || section->start != NULL);
-
- /* Check if we can use `debug_information' directly. */
- if (use_debug_info && num != 0)
- {
- if (!seen_first_offset)
- {
- /* This is the first location list. */
- last_offset = debug_information [i].loc_offsets [0];
- first = i;
- seen_first_offset = 1;
- j = 1;
- }
- else
- j = 0;
-
- for (; j < num; j++)
- {
- unsigned long offset = debug_information [i].loc_offsets [j];
- if (last_offset > offset)
- {
- if (offset < section->size) {
- use_debug_info = 0;
- break;
- }
- else
- continue;
- }
-
- if (offset < section->size)
- last_offset = offset;
- else
- error(_("Not updating location-list at offset 0x%x, that offset is garbage.\n"),
- offset);
- }
- }
- }
-
- if (!use_debug_info)
- /* FIXME: Should we handle this case? */
- error (_("Location lists in .debug_info section aren't in ascending order!\n"));
- }
-
- if (!seen_first_offset)
- error (_("No location lists in .debug_info section!\n"));
-
- /* DWARF sections under Mach-O have non-zero addresses. */
- if (debug_information [first].loc_offsets [0] != section->address)
- warn (_("Location lists in %s section start at 0x%lx\n"),
- section->name, debug_information [first].loc_offsets [0]);
-
- printf (_("Contents of the %s section:\n\n"), section->name);
- printf (_(" Offset Begin End Expression\n"));
-
- seen_first_offset = 0;
- for (i = first; i < num_debug_info_entries; i++)
- {
- unsigned long begin;
- unsigned long end;
- unsigned short length;
- unsigned long offset;
- unsigned int pointer_size;
- unsigned long cu_offset;
- unsigned long base_address;
- int need_frame_base;
- int has_frame_base;
-
-
- pointer_size = debug_information [i].pointer_size;
- cu_offset = debug_information [i].cu_offset;
-
-#ifdef SORT_LOCATION_LIST_OFFSETS
- if (debug_information[i].last_loc_offset == -1UL &&
- debug_information [i].num_loc_offsets) {
- error (_("Location lists in .debug_info section aren't in ascending order! Sorting %d of them now...\n"),
- debug_information[i].num_loc_offsets);
- qsort(debug_information[i].loc_offsets,
- debug_information[i].num_loc_offsets,
- sizeof(long),
- compare_loc_offsets);
- debug_information[i].last_loc_offset = 0; /* use any non-negative value to indicate that this is sorted now */
- if (0) {
- /* Look for repeating offsets. */
- int cnt;
- int repeat_idx = 0;
- for (cnt = 1; cnt < debug_information[i].num_loc_offsets; cnt++) {
- if (debug_information[i].loc_offsets[repeat_idx] == debug_information[i].loc_offsets[cnt]) {
- continue;
- }
- if (repeat_idx + 1 < cnt) {
- error(_("VALUE %x REPEATS IN [%d, %d) (%d TIMES)!\n"),
- debug_information[i].loc_offsets[repeat_idx],
- repeat_idx,
- cnt,
- cnt - repeat_idx);
- }
- repeat_idx = cnt;
- }
- }
- }
-#endif
-
- last_overlap = NULL;
- for (j = 0; j < debug_information [i].num_loc_offsets; j++)
- {
- has_frame_base = debug_information [i].have_frame_base [j];
- /* DWARF sections under Mach-O have non-zero addresses. */
- offset = debug_information [i].loc_offsets [j] - section->address;
- if (offset >= section->size) {
- error(_("Location offset 0x%x from CU %d is beyond section's end, skipping...\n"),
- offset, i);
- continue;
- }
- else
- /* Check to see if the location list is preceded immediately by a
- NULL entry for the previous location list, or is the first one
- in the section. If not, continue, because the offset is
- garbabe (assuming that the debug_loc section is correct.)
- */
- if (offset) {
- if (offset < 2*pointer_size) {
- error(_("Location offset 0x%x from CU %d is not preceded by a valid location list, skipping...\n"),
- offset, i);
- continue;
- }
- /* There is a chance that we may hit an incorrect offset that is precede by two zeros which are
- actually values of a location expression and not the terminating sequence of the location
- list, so this check can generate a false negative (i.e., we can decide that the location offset
- is OK when it is not), but this risk is small. Anyway, a well-formed DWARF record should not
- be corrupt.
- */
- if (0 != byte_get (section_begin + offset - pointer_size, pointer_size) ||
- 0 != byte_get (section_begin + offset - 2*pointer_size, pointer_size)) {
- error(_("Location offset 0x%x from CU %d is not preceded by the end of a location list, skipping...\n"),
- offset, i);
- continue;
- }
- }
-
- next = section_begin + offset;
- base_address = debug_information [i].base_address;
-
- if (!seen_first_offset)
- seen_first_offset = 1;
- else
- {
- if (start < next)
- warn (_("There is a hole [0x%lx - 0x%lx] in .debug_loc section.\n"),
- (long)(start - section_begin), (long)(next - section_begin));
- else if (start > next) {
- last_overlap = start;
- warn (_("There is an overlap of %ld bytes [0x%lx - 0x%lx] in .debug_loc section.\n"),
- (long)(start - next),
- (long)(start - section_begin), (long)(next - section_begin));
- }
- }
- start = next;
-
- if (offset >= bytes)
- {
- warn (_("Offset 0x%lx is bigger than .debug_loc section size.\n"),
- offset);
- continue;
- }
-
- while (1)
- {
- if (start + 2 * pointer_size > section_end)
- {
- warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
- offset);
- break;
- }
-
- begin = byte_get (start, pointer_size);
- start += pointer_size;
- end = byte_get (start, pointer_size);
- start += pointer_size;
-
- if (begin == 0 && end == 0)
- {
- printf (_(" %8.8lx <End of list>\n"), offset);
- break;
- }
-
- /* Check base address specifiers. */
- if (begin == -1UL && end != -1UL)
- {
- base_address = end;
- printf (_(" %8.8lx %8.8lx %8.8lx (base address)\n"),
- offset, begin, end);
- continue;
- }
-
- /* Call hook to adjust location start and end values. */
- if (start > last_overlap)
- base_value_pair_hook(
- start - 2*pointer_size, pointer_size,
- base_address, begin, end);
-
- if (start + 2 > section_end)
- {
- warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
- offset);
- break;
- }
-
- length = byte_get (start, 2);
- start += 2;
-
- if (start + length > section_end)
- {
- warn (_("Location list starting at offset 0x%lx is not terminated.\n"),
- offset);
- break;
- }
-
- printf (" %8.8lx %8.8lx %8.8lx (",
- offset, begin + base_address, end + base_address);
- need_frame_base = decode_location_expression (start,
- pointer_size,
- length,
- cu_offset);
- putchar (')');
-
- if (need_frame_base && !has_frame_base)
- printf (_(" [without DW_AT_frame_base]"));
-
- if (begin == end)
- printf (" (start == end)");
- else if (begin > end)
- printf(" (start > end)");
-
- putchar ('\n');
-
- start += length;
- }
- }
- }
- return 1;
-}
-
-static int
-display_debug_str (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- unsigned char *start = section->start;
- unsigned long bytes = section->size;
- dwarf_vma addr = section->address;
-
- if (bytes == 0)
- {
- printf (_("\nThe %s section is empty.\n"), section->name);
- return 0;
- }
-
- printf (_("Contents of the %s section:\n\n"), section->name);
-
- while (bytes)
- {
- int j;
- int k;
- int lbytes;
-
- lbytes = (bytes > 16 ? 16 : bytes);
-
- printf (" 0x%8.8lx ", (unsigned long) addr);
-
- for (j = 0; j < 16; j++)
- {
- if (j < lbytes)
- printf ("%2.2x", start[j]);
- else
- printf (" ");
-
- if ((j & 3) == 3)
- printf (" ");
- }
-
- for (j = 0; j < lbytes; j++)
- {
- k = start[j];
- if (k >= ' ' && k < 0x80)
- printf ("%c", k);
- else
- printf (".");
- }
-
- putchar ('\n');
-
- start += lbytes;
- addr += lbytes;
- bytes -= lbytes;
- }
-
- putchar ('\n');
-
- return 1;
-}
-
-
-static int
-display_debug_info (struct dwarf_section *section, void *file)
-{
- return process_debug_info (section, file, 0);
-}
-
-
-static int
-display_debug_aranges (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
-
- printf (_("The section %s contains:\n\n"), section->name);
-
- while (start < end)
- {
- unsigned char *hdrptr;
- DWARF2_Internal_ARange arange;
- unsigned char *ranges;
- unsigned long length;
- unsigned long address;
- int excess;
- int offset_size;
- int initial_length_size;
-
- hdrptr = start;
-
- arange.ar_length = byte_get (hdrptr, 4);
- hdrptr += 4;
-
- if (arange.ar_length == 0xffffffff)
- {
- arange.ar_length = byte_get (hdrptr, 8);
- hdrptr += 8;
- offset_size = 8;
- initial_length_size = 12;
- }
- else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- arange.ar_version = byte_get (hdrptr, 2);
- hdrptr += 2;
-
- arange.ar_info_offset = byte_get (hdrptr, offset_size);
- hdrptr += offset_size;
-
- arange.ar_pointer_size = byte_get (hdrptr, 1);
- hdrptr += 1;
-
- arange.ar_segment_size = byte_get (hdrptr, 1);
- hdrptr += 1;
-
- if (arange.ar_version != 2 && arange.ar_version != 3)
- {
- warn (_("Only DWARF 2 and 3 aranges are currently supported.\n"));
- break;
- }
-
- printf (_(" Length: %ld\n"), arange.ar_length);
- printf (_(" Version: %d\n"), arange.ar_version);
- printf (_(" Offset into .debug_info: %lx\n"), arange.ar_info_offset);
- printf (_(" Pointer Size: %d\n"), arange.ar_pointer_size);
- printf (_(" Segment Size: %d\n"), arange.ar_segment_size);
-
- printf (_("\n Address Length\n"));
-
- ranges = hdrptr;
-
- /* Must pad to an alignment boundary that is twice the pointer size. */
- excess = (hdrptr - start) % (2 * arange.ar_pointer_size);
- if (excess)
- ranges += (2 * arange.ar_pointer_size) - excess;
-
- start += arange.ar_length + initial_length_size;
-
- while (ranges + 2 * arange.ar_pointer_size <= start)
- {
- address = byte_get (ranges, arange.ar_pointer_size);
- if (address)
- value_hook(ranges, arange.ar_pointer_size, address);
-
- ranges += arange.ar_pointer_size;
-
- length = byte_get (ranges, arange.ar_pointer_size);
-
- ranges += arange.ar_pointer_size;
-
- printf (" %8.8lx %lu\n", address, length);
- }
- }
-
- printf ("\n");
-
- return 1;
-}
-
-static int
-display_debug_ranges (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- unsigned char *start = section->start;
- unsigned char *section_end;
- unsigned long bytes;
- unsigned char *section_begin = start;
- unsigned int num_range_list = 0;
- unsigned long last_offset = 0;
- unsigned int first = 0;
- unsigned int i;
- unsigned int j;
- int seen_first_offset = 0;
- int use_debug_info = 1;
- unsigned char *next;
-
- bytes = section->size;
- section_end = start + bytes;
-
- if (bytes == 0)
- {
- printf (_("\nThe %s section is empty.\n"), section->name);
- return 0;
- }
-
- load_debug_info (file);
-
- /* Check the order of range list in .debug_info section. If
- offsets of range lists are in the ascending order, we can
- use `debug_information' directly. */
- for (i = 0; i < num_debug_info_entries; i++)
- {
- unsigned int num;
-
- num = debug_information [i].num_range_lists;
- num_range_list += num;
-
- /* Check if we can use `debug_information' directly. */
- if (use_debug_info && num != 0)
- {
- if (!seen_first_offset)
- {
- /* This is the first range list. */
- last_offset = debug_information [i].range_lists [0];
- first = i;
- seen_first_offset = 1;
- j = 1;
- }
- else
- j = 0;
-
- for (; j < num; j++)
- {
- if (last_offset >
- debug_information [i].range_lists [j])
- {
- use_debug_info = 0;
- break;
- }
- last_offset = debug_information [i].range_lists [j];
- }
- }
- }
-
- if (!use_debug_info)
- /* FIXME: Should we handle this case? */
- error (_("Range lists in .debug_info section aren't in ascending order!\n"));
-
- if (!seen_first_offset)
- error (_("No range lists in .debug_info section!\n"));
-
- /* DWARF sections under Mach-O have non-zero addresses. */
- if (debug_information [first].range_lists [0] != section->address)
- warn (_("Range lists in %s section start at 0x%lx\n"),
- section->name, debug_information [first].range_lists [0]);
-
- printf (_("Contents of the %s section:\n\n"), section->name);
- printf (_(" Offset Begin End\n"));
-
- seen_first_offset = 0;
- for (i = first; i < num_debug_info_entries; i++)
- {
- unsigned long begin;
- unsigned long end;
- unsigned long offset;
- unsigned int pointer_size;
- unsigned long base_address;
-
- pointer_size = debug_information [i].pointer_size;
-
- for (j = 0; j < debug_information [i].num_range_lists; j++)
- {
- /* DWARF sections under Mach-O have non-zero addresses. */
- offset = debug_information [i].range_lists [j] - section->address;
- next = section_begin + offset;
- base_address = debug_information [i].base_address;
-
- if (!seen_first_offset)
- seen_first_offset = 1;
- else
- {
- if (start < next)
- warn (_("There is a hole [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
- else if (start > next)
- warn (_("There is an overlap [0x%lx - 0x%lx] in %s section.\n"),
- (long)(start - section_begin),
- (long)(next - section_begin), section->name);
- }
- start = next;
-
- while (1)
- {
- begin = byte_get (start, pointer_size);
- start += pointer_size;
- end = byte_get (start, pointer_size);
- start += pointer_size;
-
- if (begin == 0 && end == 0)
- {
- printf (_(" %8.8lx <End of list>\n"), offset);
- break;
- }
-
- /* Check base address specifiers. */
- if (begin == -1UL && end != -1UL)
- {
- base_address = end;
- printf (_(" %8.8lx %8.8lx %8.8lx (base address)\n"),
- offset, begin, end);
- continue;
- }
-
- base_value_pair_hook(start - 2*pointer_size, pointer_size,
- base_address, begin, end);
-
- printf (_(" %8.8lx %8.8lx %8.8lx"),
- offset, begin + base_address, end + base_address);
-
- if (begin == end)
- printf (_(" (start == end)"));
- else if (begin > end)
- printf (_(" (start > end)"));
-
- putchar ('\n');
- }
- }
- }
- putchar ('\n');
- return 1;
-}
-
-typedef struct Frame_Chunk
-{
- struct Frame_Chunk *next;
- unsigned char *chunk_start;
- int ncols;
- /* DW_CFA_{undefined,same_value,offset,register,unreferenced} */
- short int *col_type;
- int *col_offset;
- char *augmentation;
- unsigned int code_factor;
- int data_factor;
- unsigned long pc_begin;
- unsigned long pc_range;
- int cfa_reg;
- int cfa_offset;
- int ra;
- unsigned char fde_encoding;
- unsigned char cfa_exp;
-}
-Frame_Chunk;
-
-/* A marker for a col_type that means this column was never referenced
- in the frame info. */
-#define DW_CFA_unreferenced (-1)
-
-static void
-frame_need_space (Frame_Chunk *fc, int reg)
-{
- int prev = fc->ncols;
-
- if (reg < fc->ncols)
- return;
-
- fc->ncols = reg + 1;
- fc->col_type = xcrealloc (fc->col_type, fc->ncols, sizeof (short int));
- fc->col_offset = xcrealloc (fc->col_offset, fc->ncols, sizeof (int));
-
- while (prev < fc->ncols)
- {
- fc->col_type[prev] = DW_CFA_unreferenced;
- fc->col_offset[prev] = 0;
- prev++;
- }
-}
-
-static void
-frame_display_row (Frame_Chunk *fc, int *need_col_headers, int *max_regs)
-{
- int r;
- char tmp[100];
-
- if (*max_regs < fc->ncols)
- *max_regs = fc->ncols;
-
- if (*need_col_headers)
- {
- *need_col_headers = 0;
-
- printf (" LOC CFA ");
-
- for (r = 0; r < *max_regs; r++)
- if (fc->col_type[r] != DW_CFA_unreferenced)
- {
- if (r == fc->ra)
- printf ("ra ");
- else
- printf ("r%-4d", r);
- }
-
- printf ("\n");
- }
-
- printf ("%08lx ", fc->pc_begin);
- if (fc->cfa_exp)
- strcpy (tmp, "exp");
- else
- sprintf (tmp, "r%d%+d", fc->cfa_reg, fc->cfa_offset);
- printf ("%-8s ", tmp);
-
- for (r = 0; r < fc->ncols; r++)
- {
- if (fc->col_type[r] != DW_CFA_unreferenced)
- {
- switch (fc->col_type[r])
- {
- case DW_CFA_undefined:
- strcpy (tmp, "u");
- break;
- case DW_CFA_same_value:
- strcpy (tmp, "s");
- break;
- case DW_CFA_offset:
- sprintf (tmp, "c%+d", fc->col_offset[r]);
- break;
- case DW_CFA_val_offset:
- sprintf (tmp, "v%+d", fc->col_offset[r]);
- break;
- case DW_CFA_register:
- sprintf (tmp, "r%d", fc->col_offset[r]);
- break;
- case DW_CFA_expression:
- strcpy (tmp, "exp");
- break;
- case DW_CFA_val_expression:
- strcpy (tmp, "vexp");
- break;
- default:
- strcpy (tmp, "n/a");
- break;
- }
- printf ("%-5s", tmp);
- }
- }
- printf ("\n");
-}
-
-static int
-size_of_encoded_value (int encoding)
-{
- switch (encoding & 0x7)
- {
- default: /* ??? */
- case 0: return eh_addr_size;
- case 2: return 2;
- case 3: return 4;
- case 4: return 8;
- }
-}
-
-static dwarf_vma
-get_encoded_value (unsigned char *data, int encoding)
-{
- int size = size_of_encoded_value (encoding);
- if (encoding & DW_EH_PE_signed)
- return byte_get_signed (data, size);
- else
- return byte_get (data, size);
-}
-
-#define GET(N) byte_get (start, N); start += N
-#define LEB() read_leb128 (start, & length_return, 0); start += length_return
-#define SLEB() read_leb128 (start, & length_return, 1); start += length_return
-
-static int
-display_debug_frames (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- unsigned char *start = section->start;
- unsigned char *end = start + section->size;
- unsigned char *section_start = start;
- Frame_Chunk *chunks = 0;
- Frame_Chunk *remembered_state = 0;
- Frame_Chunk *rs;
- int is_eh = strcmp (section->name, ".eh_frame") == 0;
- unsigned int length_return;
- int max_regs = 0;
-
- printf (_("The section %s contains:\n"), section->name);
-
- while (start < end)
- {
- unsigned char *saved_start;
- unsigned char *block_end;
- unsigned long length;
- unsigned long cie_id;
- Frame_Chunk *fc;
- Frame_Chunk *cie;
- int need_col_headers = 1;
- unsigned char *augmentation_data = NULL;
- unsigned long augmentation_data_len = 0;
- int encoded_ptr_size = eh_addr_size;
- int offset_size;
- int initial_length_size;
-
- saved_start = start;
- length = byte_get (start, 4); start += 4;
-
- if (length == 0)
- {
- printf ("\n%08lx ZERO terminator\n\n",
- (unsigned long)(saved_start - section_start));
- return 1;
- }
-
- if (length == 0xffffffff)
- {
- length = byte_get (start, 8);
- start += 8;
- offset_size = 8;
- initial_length_size = 12;
- }
- else
- {
- offset_size = 4;
- initial_length_size = 4;
- }
-
- block_end = saved_start + length + initial_length_size;
- cie_id = byte_get (start, offset_size); start += offset_size;
-
- if (is_eh ? (cie_id == 0) : (cie_id == DW_CIE_ID))
- {
- int version;
-
- fc = xmalloc (sizeof (Frame_Chunk));
- memset (fc, 0, sizeof (Frame_Chunk));
-
- fc->next = chunks;
- chunks = fc;
- fc->chunk_start = saved_start;
- fc->ncols = 0;
- fc->col_type = xmalloc (sizeof (short int));
- fc->col_offset = xmalloc (sizeof (int));
- frame_need_space (fc, max_regs-1);
-
- version = *start++;
-
- fc->augmentation = (char *) start;
- start = (unsigned char *) strchr ((char *) start, '\0') + 1;
-
- if (fc->augmentation[0] == 'z')
- {
- fc->code_factor = LEB ();
- fc->data_factor = SLEB ();
- if (version == 1)
- {
- fc->ra = GET (1);
- }
- else
- {
- fc->ra = LEB ();
- }
- augmentation_data_len = LEB ();
- augmentation_data = start;
- start += augmentation_data_len;
- }
- else if (strcmp (fc->augmentation, "eh") == 0)
- {
- start += eh_addr_size;
- fc->code_factor = LEB ();
- fc->data_factor = SLEB ();
- if (version == 1)
- {
- fc->ra = GET (1);
- }
- else
- {
- fc->ra = LEB ();
- }
- }
- else
- {
- fc->code_factor = LEB ();
- fc->data_factor = SLEB ();
- if (version == 1)
- {
- fc->ra = GET (1);
- }
- else
- {
- fc->ra = LEB ();
- }
- }
- cie = fc;
-
- if (do_debug_frames_interp)
- printf ("\n%08lx %08lx %08lx CIE \"%s\" cf=%d df=%d ra=%d\n",
- (unsigned long)(saved_start - section_start), length, cie_id,
- fc->augmentation, fc->code_factor, fc->data_factor,
- fc->ra);
- else
- {
- printf ("\n%08lx %08lx %08lx CIE\n",
- (unsigned long)(saved_start - section_start), length, cie_id);
- printf (" Version: %d\n", version);
- printf (" Augmentation: \"%s\"\n", fc->augmentation);
- printf (" Code alignment factor: %u\n", fc->code_factor);
- printf (" Data alignment factor: %d\n", fc->data_factor);
- printf (" Return address column: %d\n", fc->ra);
-
- if (augmentation_data_len)
- {
- unsigned long i;
- printf (" Augmentation data: ");
- for (i = 0; i < augmentation_data_len; ++i)
- printf (" %02x", augmentation_data[i]);
- putchar ('\n');
- }
- putchar ('\n');
- }
-
- if (augmentation_data_len)
- {
- unsigned char *p, *q;
- p = (unsigned char *) fc->augmentation + 1;
- q = augmentation_data;
-
- while (1)
- {
- if (*p == 'L')
- q++;
- else if (*p == 'P')
- q += 1 + size_of_encoded_value (*q);
- else if (*p == 'R')
- fc->fde_encoding = *q++;
- else
- break;
- p++;
- }
-
- if (fc->fde_encoding)
- encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
- }
-
- frame_need_space (fc, fc->ra);
- }
- else
- {
- unsigned char *look_for;
- static Frame_Chunk fde_fc;
-
- fc = & fde_fc;
- memset (fc, 0, sizeof (Frame_Chunk));
-
- look_for = is_eh ? start - 4 - cie_id : section_start + cie_id;
-
- for (cie = chunks; cie ; cie = cie->next)
- if (cie->chunk_start == look_for)
- break;
-
- if (!cie)
- {
- warn ("Invalid CIE pointer %08lx in FDE at %08lx\n",
- cie_id, (unsigned long)(saved_start - section_start));
- start = block_end;
- fc->ncols = 0;
- fc->col_type = xmalloc (sizeof (short int));
- fc->col_offset = xmalloc (sizeof (int));
- frame_need_space (fc, max_regs - 1);
- cie = fc;
- fc->augmentation = "";
- fc->fde_encoding = 0;
- }
- else
- {
- fc->ncols = cie->ncols;
- fc->col_type = xcmalloc (fc->ncols, sizeof (short int));
- fc->col_offset = xcmalloc (fc->ncols, sizeof (int));
- memcpy (fc->col_type, cie->col_type, fc->ncols * sizeof (short int));
- memcpy (fc->col_offset, cie->col_offset, fc->ncols * sizeof (int));
- fc->augmentation = cie->augmentation;
- fc->code_factor = cie->code_factor;
- fc->data_factor = cie->data_factor;
- fc->cfa_reg = cie->cfa_reg;
- fc->cfa_offset = cie->cfa_offset;
- fc->ra = cie->ra;
- frame_need_space (fc, max_regs-1);
- fc->fde_encoding = cie->fde_encoding;
- }
-
- if (fc->fde_encoding)
- encoded_ptr_size = size_of_encoded_value (fc->fde_encoding);
-
- fc->pc_begin = get_encoded_value (start, fc->fde_encoding);
- if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
- /* Don't adjust for relocatable file since there's
- invariably a pcrel reloc here, which we haven't
- applied. */
- && !is_relocatable) {
- fc->pc_begin += section->address + (start - section_start);
- }
- signed_value_hook(start,
- size_of_encoded_value (fc->fde_encoding),
- fc->fde_encoding & DW_EH_PE_signed,
- fc->pc_begin);
- start += encoded_ptr_size;
- fc->pc_range = byte_get (start, encoded_ptr_size);
- start += encoded_ptr_size;
-
- if (cie->augmentation[0] == 'z')
- {
- augmentation_data_len = LEB ();
- augmentation_data = start;
- start += augmentation_data_len;
- }
-
- printf ("\n%08lx %08lx %08lx FDE cie=%08lx pc=%08lx..%08lx\n",
- (unsigned long)(saved_start - section_start), length, cie_id,
- (unsigned long)(cie->chunk_start - section_start),
- fc->pc_begin, fc->pc_begin + fc->pc_range);
- if (! do_debug_frames_interp && augmentation_data_len)
- {
- unsigned long i;
-
- printf (" Augmentation data: ");
- for (i = 0; i < augmentation_data_len; ++i)
- printf (" %02x", augmentation_data[i]);
- putchar ('\n');
- putchar ('\n');
- }
- }
-
- /* At this point, fc is the current chunk, cie (if any) is set, and
- we're about to interpret instructions for the chunk. */
- /* ??? At present we need to do this always, since this sizes the
- fc->col_type and fc->col_offset arrays, which we write into always.
- We should probably split the interpreted and non-interpreted bits
- into two different routines, since there's so much that doesn't
- really overlap between them. */
- if (1 || do_debug_frames_interp)
- {
- /* Start by making a pass over the chunk, allocating storage
- and taking note of what registers are used. */
- unsigned char *tmp = start;
-
- while (start < block_end)
- {
- unsigned op, opa;
- unsigned long reg, tmp;
-
- op = *start++;
- opa = op & 0x3f;
- if (op & 0xc0)
- op &= 0xc0;
-
- /* Warning: if you add any more cases to this switch, be
- sure to add them to the corresponding switch below. */
- switch (op)
- {
- case DW_CFA_advance_loc:
- break;
- case DW_CFA_offset:
- LEB ();
- frame_need_space (fc, opa);
- fc->col_type[opa] = DW_CFA_undefined;
- break;
- case DW_CFA_restore:
- frame_need_space (fc, opa);
- fc->col_type[opa] = DW_CFA_undefined;
- break;
- case DW_CFA_set_loc:
- start += encoded_ptr_size;
- break;
- case DW_CFA_advance_loc1:
- start += 1;
- break;
- case DW_CFA_advance_loc2:
- start += 2;
- break;
- case DW_CFA_advance_loc4:
- start += 4;
- break;
- case DW_CFA_offset_extended:
- case DW_CFA_val_offset:
- reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_restore_extended:
- reg = LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_undefined:
- reg = LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_same_value:
- reg = LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_register:
- reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_def_cfa:
- LEB (); LEB ();
- break;
- case DW_CFA_def_cfa_register:
- LEB ();
- break;
- case DW_CFA_def_cfa_offset:
- LEB ();
- break;
- case DW_CFA_def_cfa_expression:
- tmp = LEB ();
- start += tmp;
- break;
- case DW_CFA_expression:
- case DW_CFA_val_expression:
- reg = LEB ();
- tmp = LEB ();
- start += tmp;
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_offset_extended_sf:
- case DW_CFA_val_offset_sf:
- reg = LEB (); SLEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
- break;
- case DW_CFA_def_cfa_sf:
- LEB (); SLEB ();
- break;
- case DW_CFA_def_cfa_offset_sf:
- SLEB ();
- break;
- case DW_CFA_MIPS_advance_loc8:
- start += 8;
- break;
- case DW_CFA_GNU_args_size:
- LEB ();
- break;
- case DW_CFA_GNU_negative_offset_extended:
- reg = LEB (); LEB ();
- frame_need_space (fc, reg);
- fc->col_type[reg] = DW_CFA_undefined;
-
- default:
- break;
- }
- }
- start = tmp;
- }
-
- /* Now we know what registers are used, make a second pass over
- the chunk, this time actually printing out the info. */
-
- while (start < block_end)
- {
- unsigned op, opa;
- unsigned long ul, reg, roffs;
- long l, ofs;
- dwarf_vma vma;
-
- op = *start++;
- opa = op & 0x3f;
- if (op & 0xc0)
- op &= 0xc0;
-
- /* Warning: if you add any more cases to this switch, be
- sure to add them to the corresponding switch above. */
- switch (op)
- {
- case DW_CFA_advance_loc:
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_advance_loc: %d to %08lx\n",
- opa * fc->code_factor,
- fc->pc_begin + opa * fc->code_factor);
- fc->pc_begin += opa * fc->code_factor;
- break;
-
- case DW_CFA_offset:
- roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset: r%d at cfa%+ld\n",
- opa, roffs * fc->data_factor);
- fc->col_type[opa] = DW_CFA_offset;
- fc->col_offset[opa] = roffs * fc->data_factor;
- break;
-
- case DW_CFA_restore:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_restore: r%d\n", opa);
- fc->col_type[opa] = cie->col_type[opa];
- fc->col_offset[opa] = cie->col_offset[opa];
- break;
-
- case DW_CFA_set_loc:
- vma = get_encoded_value (start, fc->fde_encoding);
- if ((fc->fde_encoding & 0x70) == DW_EH_PE_pcrel
- && !is_relocatable) {
- vma += section->address + (start - section_start);
- }
- signed_value_hook(start,
- size_of_encoded_value (fc->fde_encoding),
- fc->fde_encoding & DW_EH_PE_signed,
- vma);
- start += encoded_ptr_size;
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_set_loc: %08lx\n", (unsigned long)vma);
- fc->pc_begin = vma;
- break;
-
- case DW_CFA_advance_loc1:
- ofs = byte_get (start, 1); start += 1;
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_advance_loc1: %ld to %08lx\n",
- ofs * fc->code_factor,
- fc->pc_begin + ofs * fc->code_factor);
- fc->pc_begin += ofs * fc->code_factor;
- break;
-
- case DW_CFA_advance_loc2:
- ofs = byte_get (start, 2); start += 2;
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_advance_loc2: %ld to %08lx\n",
- ofs * fc->code_factor,
- fc->pc_begin + ofs * fc->code_factor);
- fc->pc_begin += ofs * fc->code_factor;
- break;
-
- case DW_CFA_advance_loc4:
- ofs = byte_get (start, 4); start += 4;
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_advance_loc4: %ld to %08lx\n",
- ofs * fc->code_factor,
- fc->pc_begin + ofs * fc->code_factor);
- fc->pc_begin += ofs * fc->code_factor;
- break;
-
- case DW_CFA_offset_extended:
- reg = LEB ();
- roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset_extended: r%ld at cfa%+ld\n",
- reg, roffs * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
- break;
-
- case DW_CFA_val_offset:
- reg = LEB ();
- roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_val_offset: r%ld at cfa%+ld\n",
- reg, roffs * fc->data_factor);
- fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = roffs * fc->data_factor;
- break;
-
- case DW_CFA_restore_extended:
- reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_restore_extended: r%ld\n", reg);
- fc->col_type[reg] = cie->col_type[reg];
- fc->col_offset[reg] = cie->col_offset[reg];
- break;
-
- case DW_CFA_undefined:
- reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_undefined: r%ld\n", reg);
- fc->col_type[reg] = DW_CFA_undefined;
- fc->col_offset[reg] = 0;
- break;
-
- case DW_CFA_same_value:
- reg = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_same_value: r%ld\n", reg);
- fc->col_type[reg] = DW_CFA_same_value;
- fc->col_offset[reg] = 0;
- break;
-
- case DW_CFA_register:
- reg = LEB ();
- roffs = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_register: r%ld in r%ld\n", reg, roffs);
- fc->col_type[reg] = DW_CFA_register;
- fc->col_offset[reg] = roffs;
- break;
-
- case DW_CFA_remember_state:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_remember_state\n");
- rs = xmalloc (sizeof (Frame_Chunk));
- rs->ncols = fc->ncols;
- rs->col_type = xcmalloc (rs->ncols, sizeof (short int));
- rs->col_offset = xcmalloc (rs->ncols, sizeof (int));
- memcpy (rs->col_type, fc->col_type, rs->ncols);
- memcpy (rs->col_offset, fc->col_offset, rs->ncols * sizeof (int));
- rs->next = remembered_state;
- remembered_state = rs;
- break;
-
- case DW_CFA_restore_state:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_restore_state\n");
- rs = remembered_state;
- if (rs)
- {
- remembered_state = rs->next;
- frame_need_space (fc, rs->ncols-1);
- memcpy (fc->col_type, rs->col_type, rs->ncols);
- memcpy (fc->col_offset, rs->col_offset,
- rs->ncols * sizeof (int));
- free (rs->col_type);
- free (rs->col_offset);
- free (rs);
- }
- else if (do_debug_frames_interp)
- printf ("Mismatched DW_CFA_restore_state\n");
- break;
-
- case DW_CFA_def_cfa:
- fc->cfa_reg = LEB ();
- fc->cfa_offset = LEB ();
- fc->cfa_exp = 0;
- if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa: r%d ofs %d\n",
- fc->cfa_reg, fc->cfa_offset);
- break;
-
- case DW_CFA_def_cfa_register:
- fc->cfa_reg = LEB ();
- fc->cfa_exp = 0;
- if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_reg: r%d\n", fc->cfa_reg);
- break;
-
- case DW_CFA_def_cfa_offset:
- fc->cfa_offset = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_offset: %d\n", fc->cfa_offset);
- break;
-
- case DW_CFA_nop:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_nop\n");
- break;
-
- case DW_CFA_def_cfa_expression:
- ul = LEB ();
- if (! do_debug_frames_interp)
- {
- printf (" DW_CFA_def_cfa_expression (");
- decode_location_expression (start, eh_addr_size, ul, 0);
- printf (")\n");
- }
- fc->cfa_exp = 1;
- start += ul;
- break;
-
- case DW_CFA_expression:
- reg = LEB ();
- ul = LEB ();
- if (! do_debug_frames_interp)
- {
- printf (" DW_CFA_expression: r%ld (", reg);
- decode_location_expression (start, eh_addr_size, ul, 0);
- printf (")\n");
- }
- fc->col_type[reg] = DW_CFA_expression;
- start += ul;
- break;
-
- case DW_CFA_val_expression:
- reg = LEB ();
- ul = LEB ();
- if (! do_debug_frames_interp)
- {
- printf (" DW_CFA_val_expression: r%ld (", reg);
- decode_location_expression (start, eh_addr_size, ul, 0);
- printf (")\n");
- }
- fc->col_type[reg] = DW_CFA_val_expression;
- start += ul;
- break;
-
- case DW_CFA_offset_extended_sf:
- reg = LEB ();
- l = SLEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_offset_extended_sf: r%ld at cfa%+ld\n",
- reg, l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
- break;
-
- case DW_CFA_val_offset_sf:
- reg = LEB ();
- l = SLEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_val_offset_sf: r%ld at cfa%+ld\n",
- reg, l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_val_offset;
- fc->col_offset[reg] = l * fc->data_factor;
- break;
-
- case DW_CFA_def_cfa_sf:
- fc->cfa_reg = LEB ();
- fc->cfa_offset = SLEB ();
- fc->cfa_offset = fc->cfa_offset * fc->data_factor;
- fc->cfa_exp = 0;
- if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_sf: r%d ofs %d\n",
- fc->cfa_reg, fc->cfa_offset);
- break;
-
- case DW_CFA_def_cfa_offset_sf:
- fc->cfa_offset = SLEB ();
- fc->cfa_offset = fc->cfa_offset * fc->data_factor;
- if (! do_debug_frames_interp)
- printf (" DW_CFA_def_cfa_offset_sf: %d\n", fc->cfa_offset);
- break;
-
- case DW_CFA_MIPS_advance_loc8:
- ofs = byte_get (start, 8); start += 8;
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
- else
- printf (" DW_CFA_MIPS_advance_loc8: %ld to %08lx\n",
- ofs * fc->code_factor,
- fc->pc_begin + ofs * fc->code_factor);
- fc->pc_begin += ofs * fc->code_factor;
- break;
-
- case DW_CFA_GNU_window_save:
- if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_window_save\n");
- break;
-
- case DW_CFA_GNU_args_size:
- ul = LEB ();
- if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_args_size: %ld\n", ul);
- break;
-
- case DW_CFA_GNU_negative_offset_extended:
- reg = LEB ();
- l = - LEB ();
- frame_need_space (fc, reg);
- if (! do_debug_frames_interp)
- printf (" DW_CFA_GNU_negative_offset_extended: r%ld at cfa%+ld\n",
- reg, l * fc->data_factor);
- fc->col_type[reg] = DW_CFA_offset;
- fc->col_offset[reg] = l * fc->data_factor;
- break;
-
- default:
- warn (_("unsupported or unknown DW_CFA_%d\n"), op);
- start = block_end;
- }
- }
-
- if (do_debug_frames_interp)
- frame_display_row (fc, &need_col_headers, &max_regs);
-
- start = block_end;
- }
-
- printf ("\n");
-
- return 1;
-}
-
-#undef GET
-#undef LEB
-#undef SLEB
-
-static int
-display_debug_not_supported (struct dwarf_section *section,
- void *file ATTRIBUTE_UNUSED)
-{
- printf (_("Displaying the debug contents of section %s is not yet supported.\n"),
- section->name);
-
- return 1;
-}
-
-static void *
-cmalloc (size_t nmemb, size_t size)
-{
- /* Check for overflow. */
- if (nmemb >= ~(size_t) 0 / size)
- return NULL;
- else
- return malloc (nmemb * size);
-}
-
-static void *
-xmalloc(size_t size)
-{
- return malloc(size);
-}
-
-static void *
-xrealloc (p, n)
- void *p;
- size_t n;
-{
- return realloc (p, n);
-}
-
-static void *
-xcmalloc (size_t nmemb, size_t size)
-{
- /* Check for overflow. */
- if (nmemb >= ~(size_t) 0 / size)
- return NULL;
- else
- return xmalloc (nmemb * size);
-}
-
-static void *
-xcrealloc (void *ptr, size_t nmemb, size_t size)
-{
- /* Check for overflow. */
- if (nmemb >= ~(size_t) 0 / size)
- return NULL;
- else
- return xrealloc (ptr, nmemb * size);
-}
-
-static void
-error (const char *message, ...)
-{
- va_list args;
-
- va_start (args, message);
- fprintf (stderr, _("%s: Warning: "), program_name);
- vfprintf (stderr, message, args);
- va_end (args);
-}
-
-static void
-warn (const char *message, ...)
-{
- va_list args;
-
- va_start (args, message);
- fprintf (stderr, _("%s: Warning: "), program_name);
- vfprintf (stderr, message, args);
- va_end (args);
-}
-
-void
-free_debug_memory (void)
-{
- enum dwarf_section_display_enum i;
-
- free_abbrevs ();
-
- for (i = 0; i < max; i++)
- free_debug_section (i);
-
- if (debug_information)
- {
- for (i = 0; i < num_debug_info_entries; i++)
- {
- if (!debug_information [i].max_loc_offsets)
- {
- free (debug_information [i].loc_offsets);
- free (debug_information [i].have_frame_base);
- }
- if (!debug_information [i].max_range_lists)
- free (debug_information [i].range_lists);
- }
- free (debug_information);
- debug_information = NULL;
- num_debug_info_entries = 0;
- }
-
-}
-
-struct dwarf_section_display debug_displays[] =
-{
- { { ".debug_abbrev", NULL, 0, 0 },
- display_debug_abbrev, 0, 0 },
- { { ".debug_aranges", NULL, 0, 0 },
- display_debug_aranges, 0, 0 },
- { { ".debug_frame", NULL, 0, 0 },
- display_debug_frames, 1, 0 },
- { { ".debug_info", NULL, 0, 0 },
- display_debug_info, 1, 0 },
- { { ".debug_line", NULL, 0, 0 },
- display_debug_lines, 0, 0 },
- { { ".debug_pubnames", NULL, 0, 0 },
- display_debug_pubnames, 0, 0 },
- { { ".eh_frame", NULL, 0, 0 },
- display_debug_frames, 1, 1 },
- { { ".debug_macinfo", NULL, 0, 0 },
- display_debug_macinfo, 0, 0 },
- { { ".debug_str", NULL, 0, 0 },
- display_debug_str, 0, 0 },
- { { ".debug_loc", NULL, 0, 0 },
- display_debug_loc, 0, 0 },
- { { ".debug_pubtypes", NULL, 0, 0 },
- display_debug_pubnames, 0, 0 },
- { { ".debug_ranges", NULL, 0, 0 },
- display_debug_ranges, 0, 0 },
- { { ".debug_static_func", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_static_vars", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_types", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 },
- { { ".debug_weaknames", NULL, 0, 0 },
- display_debug_not_supported, 0, 0 }
-};
-
-/* Reinitializes all static and global variables owned by this module except for
- debug_display()
-*/
-void init_dwarf_variables(void)
-{
- have_frame_base = 0;
- need_base_address = 0;
- last_pointer_size = 0;
- warned_about_missing_comp_units = FALSE;
- num_debug_info_entries = 0;
- debug_information = NULL;
- eh_addr_size = 0;
- is_relocatable = 0;
-
- do_debug_info = 0;
- do_debug_abbrevs = 0;
- do_debug_lines = 0;
- do_debug_pubnames = 0;
- do_debug_aranges = 0;
- do_debug_ranges = 0;
- do_debug_frames = 0;
- do_debug_frames_interp = 0;
- do_debug_macinfo = 0;
- do_debug_str = 0;
- do_debug_loc = 0;
-
- byte_get = NULL;
-
- memset(&state_machine_regs, 0, sizeof(state_machine_regs));
-
- first_abbrev = NULL;
- last_abbrev = NULL;
-}
diff --git a/dwarf.h b/dwarf.h
deleted file mode 100644
index d362eea..0000000
--- a/dwarf.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/* dwwrf.h - DWARF support header file
- Copyright 2005
- Free Software Foundation, Inc.
-
-This file is part of GNU Binutils.
-
-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. */
-
-#include "dwarf2.h"
-
-typedef unsigned long dwarf_vma;
-typedef unsigned long dwarf_size_type;
-
-struct dwarf_section
-{
- const char *name;
- unsigned char *start;
- dwarf_vma address;
- dwarf_size_type size;
-};
-
-/* A structure containing the name of a debug section
- and a pointer to a function that can decode it. */
-struct dwarf_section_display
-{
- struct dwarf_section section;
- int (*display) (struct dwarf_section *, void *);
- unsigned int relocate : 1;
- unsigned int eh_frame : 1;
-};
-
-enum dwarf_section_display_enum {
- abbrev = 0,
- aranges,
- frame,
- info,
- line,
- pubnames,
- eh_frame,
- macinfo,
- str,
- loc,
- pubtypes,
- ranges,
- static_func,
- static_vars,
- types,
- weaknames,
- max
-};
-
-extern struct dwarf_section_display debug_displays [];
-
-/* This structure records the information that
- we extract from the.debug_info section. */
-typedef struct
-{
- unsigned int pointer_size;
- unsigned long cu_offset;
- unsigned long base_address;
- /* This is an array of offsets to the location list table. */
- unsigned long *loc_offsets;
- int *have_frame_base;
- unsigned int num_loc_offsets;
- unsigned int max_loc_offsets;
-#ifdef SORT_LOCATION_LIST_OFFSETS
- unsigned long last_loc_offset; /* used to determine whether loc offsets are sorted */
-#endif
- unsigned long *range_lists;
- unsigned int num_range_lists;
- unsigned int max_range_lists;
-}
-debug_info;
-
-extern dwarf_vma (*byte_get) (unsigned char *, int);
-extern dwarf_vma byte_get_little_endian (unsigned char *, int);
-extern dwarf_vma byte_get_big_endian (unsigned char *, int);
-
-extern dwarf_vma eh_addr_size;
-extern int is_relocatable;
-
-extern int do_debug_info;
-extern int do_debug_abbrevs;
-extern int do_debug_lines;
-extern int do_debug_pubnames;
-extern int do_debug_aranges;
-extern int do_debug_ranges;
-extern int do_debug_frames;
-extern int do_debug_frames_interp;
-extern int do_debug_macinfo;
-extern int do_debug_str;
-extern int do_debug_loc;
-
-extern int load_debug_section (enum dwarf_section_display_enum,
- void *);
-extern void free_debug_section (enum dwarf_section_display_enum);
-
-extern void free_debug_memory (void);
-
-extern void base_value_pair_hook(void *data, int size,
- int base, int begin, int end);
-
-extern void value_hook(void *data, int size, int val);
-
-extern void signed_value_hook(void *data,
- int pointer_size,
- int is_signed,
- int val);
-
-extern void init_dwarf_variables(void);
diff --git a/dwarf2.h b/dwarf2.h
deleted file mode 100644
index 264952a..0000000
--- a/dwarf2.h
+++ /dev/null
@@ -1,836 +0,0 @@
-/* Declarations and definitions of codes relating to the DWARF2 and
- DWARF3 symbolic debugging information formats.
- Copyright (C) 1992, 1993, 1995, 1996, 1997, 1999, 2000, 2001, 2002,
- 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
-
- Written by Gary Funck (gary@intrepid.com) The Ada Joint Program
- Office (AJPO), Florida State University and Silicon Graphics Inc.
- provided support for this effort -- June 21, 1995.
-
- Derived from the DWARF 1 implementation written by Ron Guilmette
- (rfg@netcom.com), November 1990.
-
- This file is part of GCC.
-
- GCC is free software; you can 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, or (at your option) any later
- version.
-
- GCC is distributed in the hope that it will be useful, but WITHOUT
- ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- License for more details.
-
- You should have received a copy of the GNU General Public License
- along with GCC; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
-
-/* This file is derived from the DWARF specification (a public document)
- Revision 2.0.0 (July 27, 1993) developed by the UNIX International
- Programming Languages Special Interest Group (UI/PLSIG) and distributed
- by UNIX International. Copies of this specification are available from
- UNIX International, 20 Waterview Boulevard, Parsippany, NJ, 07054.
-
- This file also now contains definitions from the DWARF 3 specification. */
-
-/* This file is shared between GCC and GDB, and should not contain
- prototypes. */
-
-#ifndef _ELF_DWARF2_H
-#define _ELF_DWARF2_H
-
-/* Structure found in the .debug_line section. */
-typedef struct
-{
- unsigned char li_length [4];
- unsigned char li_version [2];
- unsigned char li_prologue_length [4];
- unsigned char li_min_insn_length [1];
- unsigned char li_default_is_stmt [1];
- unsigned char li_line_base [1];
- unsigned char li_line_range [1];
- unsigned char li_opcode_base [1];
-}
-DWARF2_External_LineInfo;
-
-typedef struct
-{
- unsigned long li_length;
- unsigned short li_version;
- unsigned int li_prologue_length;
- unsigned char li_min_insn_length;
- unsigned char li_default_is_stmt;
- int li_line_base;
- unsigned char li_line_range;
- unsigned char li_opcode_base;
-}
-DWARF2_Internal_LineInfo;
-
-/* Structure found in .debug_pubnames section. */
-typedef struct
-{
- unsigned char pn_length [4];
- unsigned char pn_version [2];
- unsigned char pn_offset [4];
- unsigned char pn_size [4];
-}
-DWARF2_External_PubNames;
-
-typedef struct
-{
- unsigned long pn_length;
- unsigned short pn_version;
- unsigned long pn_offset;
- unsigned long pn_size;
-}
-DWARF2_Internal_PubNames;
-
-/* Structure found in .debug_info section. */
-typedef struct
-{
- unsigned char cu_length [4];
- unsigned char cu_version [2];
- unsigned char cu_abbrev_offset [4];
- unsigned char cu_pointer_size [1];
-}
-DWARF2_External_CompUnit;
-
-typedef struct
-{
- unsigned long cu_length;
- unsigned short cu_version;
- unsigned long cu_abbrev_offset;
- unsigned char cu_pointer_size;
-}
-DWARF2_Internal_CompUnit;
-
-typedef struct
-{
- unsigned char ar_length [4];
- unsigned char ar_version [2];
- unsigned char ar_info_offset [4];
- unsigned char ar_pointer_size [1];
- unsigned char ar_segment_size [1];
-}
-DWARF2_External_ARange;
-
-typedef struct
-{
- unsigned long ar_length;
- unsigned short ar_version;
- unsigned long ar_info_offset;
- unsigned char ar_pointer_size;
- unsigned char ar_segment_size;
-}
-DWARF2_Internal_ARange;
-
-
-/* Tag names and codes. */
-enum dwarf_tag
- {
- DW_TAG_padding = 0x00,
- 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,
- DW_TAG_imported_declaration = 0x08,
- DW_TAG_label = 0x0a,
- DW_TAG_lexical_block = 0x0b,
- DW_TAG_member = 0x0d,
- 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,
- 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_param = 0x2f,
- DW_TAG_template_value_param = 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,
- /* DWARF 3. */
- 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,
- DW_TAG_condition = 0x3f,
- DW_TAG_shared_type = 0x40,
- /* SGI/MIPS Extensions. */
- DW_TAG_MIPS_loop = 0x4081,
- /* HP extensions. See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz . */
- DW_TAG_HP_array_descriptor = 0x4090,
- /* GNU extensions. */
- DW_TAG_format_label = 0x4101, /* For FORTRAN 77 and Fortran 90. */
- DW_TAG_function_template = 0x4102, /* For C++. */
- DW_TAG_class_template = 0x4103, /* For C++. */
- DW_TAG_GNU_BINCL = 0x4104,
- DW_TAG_GNU_EINCL = 0x4105,
- /* Extensions for UPC. See: http://upc.gwu.edu/~upc. */
- DW_TAG_upc_shared_type = 0x8765,
- DW_TAG_upc_strict_type = 0x8766,
- DW_TAG_upc_relaxed_type = 0x8767,
- /* PGI (STMicroelectronics) extensions. No documentation available. */
- DW_TAG_PGI_kanji_type = 0xA000,
- DW_TAG_PGI_interface_block = 0xA020
- };
-
-#define DW_TAG_lo_user 0x4080
-#define DW_TAG_hi_user 0xffff
-
-/* Flag that tells whether entry has a child or not. */
-#define DW_children_no 0
-#define DW_children_yes 1
-
-/* Form names and codes. */
-enum dwarf_form
- {
- 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
- };
-
-/* Attribute names and codes. */
-enum dwarf_attribute
- {
- DW_AT_sibling = 0x01,
- DW_AT_location = 0x02,
- DW_AT_name = 0x03,
- DW_AT_ordering = 0x09,
- DW_AT_subscr_data = 0x0a,
- DW_AT_byte_size = 0x0b,
- DW_AT_bit_offset = 0x0c,
- DW_AT_bit_size = 0x0d,
- DW_AT_element_list = 0x0f,
- DW_AT_stmt_list = 0x10,
- DW_AT_low_pc = 0x11,
- DW_AT_high_pc = 0x12,
- DW_AT_language = 0x13,
- DW_AT_member = 0x14,
- 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,
- DW_AT_inline = 0x20,
- DW_AT_is_optional = 0x21,
- DW_AT_lower_bound = 0x22,
- DW_AT_producer = 0x25,
- DW_AT_prototyped = 0x27,
- DW_AT_return_addr = 0x2a,
- DW_AT_start_scope = 0x2c,
- DW_AT_stride_size = 0x2e,
- DW_AT_upper_bound = 0x2f,
- 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,
- DW_AT_namelist_items = 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,
- /* DWARF 3 values. */
- DW_AT_allocated = 0x4e,
- DW_AT_associated = 0x4f,
- DW_AT_data_location = 0x50,
- DW_AT_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,
- /* SGI/MIPS extensions. */
- 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,
- /* HP extensions. */
- DW_AT_HP_block_index = 0x2000,
- DW_AT_HP_unmodifiable = 0x2001, /* Same as DW_AT_MIPS_fde. */
- DW_AT_HP_actuals_stmt_list = 0x2010,
- DW_AT_HP_proc_per_section = 0x2011,
- DW_AT_HP_raw_data_ptr = 0x2012,
- DW_AT_HP_pass_by_reference = 0x2013,
- DW_AT_HP_opt_level = 0x2014,
- DW_AT_HP_prof_version_id = 0x2015,
- DW_AT_HP_opt_flags = 0x2016,
- DW_AT_HP_cold_region_low_pc = 0x2017,
- DW_AT_HP_cold_region_high_pc = 0x2018,
- DW_AT_HP_all_variables_modifiable = 0x2019,
- DW_AT_HP_linkage_name = 0x201a,
- DW_AT_HP_prof_flags = 0x201b, /* In comp unit of procs_info for -g. */
- /* 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,
- /* VMS extensions. */
- DW_AT_VMS_rtnbeg_pd_address = 0x2201,
- /* UPC extension. */
- DW_AT_upc_threads_scaled = 0x3210,
- /* PGI (STMicroelectronics) extensions. */
- DW_AT_PGI_lbase = 0x3a00,
- DW_AT_PGI_soffset = 0x3a01,
- DW_AT_PGI_lstride = 0x3a02
- };
-
-#define DW_AT_lo_user 0x2000 /* Implementation-defined range start. */
-#define DW_AT_hi_user 0x3ff0 /* Implementation-defined range end. */
-
-/* Location atom names and codes. */
-enum dwarf_location_atom
- {
- DW_OP_addr = 0x03,
- DW_OP_deref = 0x06,
- DW_OP_const1u = 0x08,
- DW_OP_const1s = 0x09,
- DW_OP_const2u = 0x0a,
- DW_OP_const2s = 0x0b,
- DW_OP_const4u = 0x0c,
- DW_OP_const4s = 0x0d,
- DW_OP_const8u = 0x0e,
- DW_OP_const8s = 0x0f,
- DW_OP_constu = 0x10,
- DW_OP_consts = 0x11,
- DW_OP_dup = 0x12,
- DW_OP_drop = 0x13,
- DW_OP_over = 0x14,
- DW_OP_pick = 0x15,
- 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,
- DW_OP_shl = 0x24,
- DW_OP_shr = 0x25,
- DW_OP_shra = 0x26,
- DW_OP_xor = 0x27,
- DW_OP_bra = 0x28,
- 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,
- DW_OP_lit0 = 0x30,
- DW_OP_lit1 = 0x31,
- DW_OP_lit2 = 0x32,
- DW_OP_lit3 = 0x33,
- DW_OP_lit4 = 0x34,
- DW_OP_lit5 = 0x35,
- DW_OP_lit6 = 0x36,
- DW_OP_lit7 = 0x37,
- DW_OP_lit8 = 0x38,
- DW_OP_lit9 = 0x39,
- DW_OP_lit10 = 0x3a,
- DW_OP_lit11 = 0x3b,
- DW_OP_lit12 = 0x3c,
- DW_OP_lit13 = 0x3d,
- DW_OP_lit14 = 0x3e,
- DW_OP_lit15 = 0x3f,
- DW_OP_lit16 = 0x40,
- DW_OP_lit17 = 0x41,
- DW_OP_lit18 = 0x42,
- DW_OP_lit19 = 0x43,
- DW_OP_lit20 = 0x44,
- DW_OP_lit21 = 0x45,
- DW_OP_lit22 = 0x46,
- DW_OP_lit23 = 0x47,
- DW_OP_lit24 = 0x48,
- DW_OP_lit25 = 0x49,
- DW_OP_lit26 = 0x4a,
- DW_OP_lit27 = 0x4b,
- DW_OP_lit28 = 0x4c,
- DW_OP_lit29 = 0x4d,
- DW_OP_lit30 = 0x4e,
- DW_OP_lit31 = 0x4f,
- DW_OP_reg0 = 0x50,
- DW_OP_reg1 = 0x51,
- DW_OP_reg2 = 0x52,
- DW_OP_reg3 = 0x53,
- DW_OP_reg4 = 0x54,
- DW_OP_reg5 = 0x55,
- DW_OP_reg6 = 0x56,
- DW_OP_reg7 = 0x57,
- DW_OP_reg8 = 0x58,
- DW_OP_reg9 = 0x59,
- DW_OP_reg10 = 0x5a,
- DW_OP_reg11 = 0x5b,
- DW_OP_reg12 = 0x5c,
- DW_OP_reg13 = 0x5d,
- DW_OP_reg14 = 0x5e,
- DW_OP_reg15 = 0x5f,
- DW_OP_reg16 = 0x60,
- DW_OP_reg17 = 0x61,
- DW_OP_reg18 = 0x62,
- DW_OP_reg19 = 0x63,
- DW_OP_reg20 = 0x64,
- DW_OP_reg21 = 0x65,
- DW_OP_reg22 = 0x66,
- DW_OP_reg23 = 0x67,
- DW_OP_reg24 = 0x68,
- DW_OP_reg25 = 0x69,
- DW_OP_reg26 = 0x6a,
- DW_OP_reg27 = 0x6b,
- DW_OP_reg28 = 0x6c,
- DW_OP_reg29 = 0x6d,
- DW_OP_reg30 = 0x6e,
- DW_OP_reg31 = 0x6f,
- DW_OP_breg0 = 0x70,
- DW_OP_breg1 = 0x71,
- DW_OP_breg2 = 0x72,
- DW_OP_breg3 = 0x73,
- DW_OP_breg4 = 0x74,
- DW_OP_breg5 = 0x75,
- DW_OP_breg6 = 0x76,
- DW_OP_breg7 = 0x77,
- DW_OP_breg8 = 0x78,
- DW_OP_breg9 = 0x79,
- DW_OP_breg10 = 0x7a,
- DW_OP_breg11 = 0x7b,
- DW_OP_breg12 = 0x7c,
- DW_OP_breg13 = 0x7d,
- DW_OP_breg14 = 0x7e,
- DW_OP_breg15 = 0x7f,
- DW_OP_breg16 = 0x80,
- DW_OP_breg17 = 0x81,
- DW_OP_breg18 = 0x82,
- DW_OP_breg19 = 0x83,
- DW_OP_breg20 = 0x84,
- DW_OP_breg21 = 0x85,
- DW_OP_breg22 = 0x86,
- DW_OP_breg23 = 0x87,
- DW_OP_breg24 = 0x88,
- DW_OP_breg25 = 0x89,
- DW_OP_breg26 = 0x8a,
- DW_OP_breg27 = 0x8b,
- DW_OP_breg28 = 0x8c,
- DW_OP_breg29 = 0x8d,
- DW_OP_breg30 = 0x8e,
- DW_OP_breg31 = 0x8f,
- DW_OP_regx = 0x90,
- DW_OP_fbreg = 0x91,
- DW_OP_bregx = 0x92,
- DW_OP_piece = 0x93,
- DW_OP_deref_size = 0x94,
- DW_OP_xderef_size = 0x95,
- DW_OP_nop = 0x96,
- /* DWARF 3 extensions. */
- 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,
- DW_OP_call_frame_cfa = 0x9c,
- DW_OP_bit_piece = 0x9d,
- /* GNU extensions. */
- DW_OP_GNU_push_tls_address = 0xe0,
- /* HP extensions. */
- DW_OP_HP_unknown = 0xe0, /* Ouch, the same as GNU_push_tls_address. */
- DW_OP_HP_is_value = 0xe1,
- DW_OP_HP_fltconst4 = 0xe2,
- DW_OP_HP_fltconst8 = 0xe3,
- DW_OP_HP_mod_range = 0xe4,
- DW_OP_HP_unmod_range = 0xe5,
- DW_OP_HP_tls = 0xe6
- };
-
-#define DW_OP_lo_user 0xe0 /* Implementation-defined range start. */
-#define DW_OP_hi_user 0xff /* Implementation-defined range end. */
-
-/* Type encodings. */
-enum dwarf_type
- {
- 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,
- /* DWARF 3. */
- 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,
- /* HP extensions. */
- DW_ATE_HP_float80 = 0x80, /* Floating-point (80 bit). */
- DW_ATE_HP_complex_float80 = 0x81, /* Complex floating-point (80 bit). */
- DW_ATE_HP_float128 = 0x82, /* Floating-point (128 bit). */
- DW_ATE_HP_complex_float128 = 0x83, /* Complex floating-point (128 bit). */
- DW_ATE_HP_floathpintel = 0x84, /* Floating-point (82 bit IA64). */
- DW_ATE_HP_imaginary_float80 = 0x85,
- DW_ATE_HP_imaginary_float128 = 0x86
- };
-
-#define DW_ATE_lo_user 0x80
-#define DW_ATE_hi_user 0xff
-
-/* Decimal sign encodings. */
-enum dwarf_decimal_sign_encoding
- {
- /* DWARF 3. */
- DW_DS_unsigned = 0x01,
- DW_DS_leading_overpunch = 0x02,
- DW_DS_trailing_overpunch = 0x03,
- DW_DS_leading_separate = 0x04,
- DW_DS_trailing_separate = 0x05
- };
-
-/* Endianity encodings. */
-enum dwarf_endianity_encoding
- {
- /* DWARF 3. */
- DW_END_default = 0x00,
- DW_END_big = 0x01,
- DW_END_little = 0x02
- };
-
-#define DW_END_lo_user 0x40
-#define DW_END_hi_user 0xff
-
-/* Array ordering names and codes. */
-enum dwarf_array_dim_ordering
- {
- DW_ORD_row_major = 0,
- DW_ORD_col_major = 1
- };
-
-/* Access attribute. */
-enum dwarf_access_attribute
- {
- DW_ACCESS_public = 1,
- DW_ACCESS_protected = 2,
- DW_ACCESS_private = 3
- };
-
-/* Visibility. */
-enum dwarf_visibility_attribute
- {
- DW_VIS_local = 1,
- DW_VIS_exported = 2,
- DW_VIS_qualified = 3
- };
-
-/* Virtuality. */
-enum dwarf_virtuality_attribute
- {
- DW_VIRTUALITY_none = 0,
- DW_VIRTUALITY_virtual = 1,
- DW_VIRTUALITY_pure_virtual = 2
- };
-
-/* Case sensitivity. */
-enum dwarf_id_case
- {
- DW_ID_case_sensitive = 0,
- DW_ID_up_case = 1,
- DW_ID_down_case = 2,
- DW_ID_case_insensitive = 3
- };
-
-/* Calling convention. */
-enum dwarf_calling_convention
- {
- DW_CC_normal = 0x1,
- DW_CC_program = 0x2,
- DW_CC_nocall = 0x3,
- DW_CC_GNU_renesas_sh = 0x40
- };
-
-#define DW_CC_lo_user 0x40
-#define DW_CC_hi_user 0xff
-
-/* Inline attribute. */
-enum dwarf_inline_attribute
- {
- DW_INL_not_inlined = 0,
- DW_INL_inlined = 1,
- DW_INL_declared_not_inlined = 2,
- DW_INL_declared_inlined = 3
- };
-
-/* Discriminant lists. */
-enum dwarf_discrim_list
- {
- DW_DSC_label = 0,
- DW_DSC_range = 1
- };
-
-/* Line number opcodes. */
-enum dwarf_line_number_ops
- {
- DW_LNS_extended_op = 0,
- 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,
- /* DWARF 3. */
- DW_LNS_set_prologue_end = 10,
- DW_LNS_set_epilogue_begin = 11,
- DW_LNS_set_isa = 12
- };
-
-/* Line number extended opcodes. */
-enum dwarf_line_number_x_ops
- {
- DW_LNE_end_sequence = 1,
- DW_LNE_set_address = 2,
- DW_LNE_define_file = 3,
- /* HP extensions. */
- DW_LNE_HP_negate_is_UV_update = 0x11,
- DW_LNE_HP_push_context = 0x12,
- DW_LNE_HP_pop_context = 0x13,
- DW_LNE_HP_set_file_line_column = 0x14,
- DW_LNE_HP_set_routine_name = 0x15,
- DW_LNE_HP_set_sequence = 0x16,
- DW_LNE_HP_negate_post_semantics = 0x17,
- DW_LNE_HP_negate_function_exit = 0x18,
- DW_LNE_HP_negate_front_end_logical = 0x19,
- DW_LNE_HP_define_proc = 0x20
- };
-
-#define DW_LNE_lo_user 0x80
-#define DW_LNE_hi_user 0xff
-
-/* Call frame information. */
-enum dwarf_call_frame_info
- {
- DW_CFA_advance_loc = 0x40,
- DW_CFA_offset = 0x80,
- DW_CFA_restore = 0xc0,
- 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,
- /* DWARF 3. */
- 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,
- /* SGI/MIPS specific. */
- DW_CFA_MIPS_advance_loc8 = 0x1d,
- /* GNU extensions. */
- DW_CFA_GNU_window_save = 0x2d,
- DW_CFA_GNU_args_size = 0x2e,
- DW_CFA_GNU_negative_offset_extended = 0x2f
- };
-
-#define DW_CIE_ID 0xffffffff
-#define DW_CIE_VERSION 1
-
-#define DW_CFA_extended 0
-#define DW_CFA_lo_user 0x1c
-#define DW_CFA_hi_user 0x3f
-
-#define DW_CHILDREN_no 0x00
-#define DW_CHILDREN_yes 0x01
-
-#define DW_ADDR_none 0
-
-/* Source language names and codes. */
-enum dwarf_source_language
- {
- DW_LANG_C89 = 0x0001,
- DW_LANG_C = 0x0002,
- DW_LANG_Ada83 = 0x0003,
- DW_LANG_C_plus_plus = 0x0004,
- DW_LANG_Cobol74 = 0x0005,
- DW_LANG_Cobol85 = 0x0006,
- DW_LANG_Fortran77 = 0x0007,
- DW_LANG_Fortran90 = 0x0008,
- DW_LANG_Pascal83 = 0x0009,
- DW_LANG_Modula2 = 0x000a,
- /* DWARF 3. */
- DW_LANG_Java = 0x000b,
- DW_LANG_C99 = 0x000c,
- DW_LANG_Ada95 = 0x000d,
- DW_LANG_Fortran95 = 0x000e,
- DW_LANG_PLI = 0x000f,
- DW_LANG_ObjC = 0x0010,
- DW_LANG_ObjC_plus_plus = 0x0011,
- DW_LANG_UPC = 0x0012,
- DW_LANG_D = 0x0013,
- /* MIPS. */
- DW_LANG_Mips_Assembler = 0x8001,
- /* UPC. */
- DW_LANG_Upc = 0x8765
- };
-
-#define DW_LANG_lo_user 0x8000 /* Implementation-defined range start. */
-#define DW_LANG_hi_user 0xffff /* Implementation-defined range start. */
-
-/* Names and codes for macro information. */
-enum dwarf_macinfo_record_type
- {
- DW_MACINFO_define = 1,
- DW_MACINFO_undef = 2,
- DW_MACINFO_start_file = 3,
- DW_MACINFO_end_file = 4,
- DW_MACINFO_vendor_ext = 255
- };
-
-/* @@@ For use with GNU frame unwind information. */
-
-#define DW_EH_PE_absptr 0x00
-#define DW_EH_PE_omit 0xff
-
-#define DW_EH_PE_uleb128 0x01
-#define DW_EH_PE_udata2 0x02
-#define DW_EH_PE_udata4 0x03
-#define DW_EH_PE_udata8 0x04
-#define DW_EH_PE_sleb128 0x09
-#define DW_EH_PE_sdata2 0x0A
-#define DW_EH_PE_sdata4 0x0B
-#define DW_EH_PE_sdata8 0x0C
-#define DW_EH_PE_signed 0x08
-
-#define DW_EH_PE_pcrel 0x10
-#define DW_EH_PE_textrel 0x20
-#define DW_EH_PE_datarel 0x30
-#define DW_EH_PE_funcrel 0x40
-#define DW_EH_PE_aligned 0x50
-
-#define DW_EH_PE_indirect 0x80
-
-#endif /* _ELF_DWARF2_H */
diff --git a/elfcopy.c b/elfcopy.c
deleted file mode 100644
index ec8d0f3..0000000
--- a/elfcopy.c
+++ /dev/null
@@ -1,2992 +0,0 @@
-
-#include <stdio.h>
-#include <common.h>
-#include <debug.h>
-#include <hash.h>
-#include <libelf.h>
-#include <libebl.h>
-#include <libebl_arm.h>
-#include <elf.h>
-#include <gelf.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-#ifdef DEBUG
- #include <rangesort.h>
-#endif
-
-/* static void print_shdr_array(shdr_info_t *, int); */
-
-#include <elfcopy.h>
-
-#define COPY_SECTION_DATA_BUFFER (0)
-
-/* When this macro is set to a nonzero value, we replace calls to elf_strptr()
- on the target ELF handle with code that extracts the strings directly from
- the data buffers of that ELF handle. In this case, elf_strptr() does not
- work as expected, as it tries to read the data buffer of the associated
- string section directly from the file, and that buffer does not exist yet
- in the file, since we haven't committed our changes yet.
-*/
-#define ELF_STRPTR_IS_BROKEN (1)
-
-static void update_relocations_section_symbol_references(Elf *newelf, Elf *elf,
- shdr_info_t *info, int info_len,
- shdr_info_t *relsect_info,
- Elf32_Word *newsymidx);
-
-static void update_relocations_section_offsets(Elf *newelf, Elf *elf, Ebl *ebl,
- shdr_info_t *info,
- int info_len,
- shdr_info_t *relsect_info,
- Elf_Data *data,
- range_list_t *old_section_ranges);
-
-static void update_hash_table(Elf *newelf, Elf *elf,
- Elf32_Word hash_scn_idx,
- shdr_info_t *symtab_info);
-
-static inline
-Elf_Data *create_section_data(shdr_info_t *, Elf_Scn *);
-
-static Elf64_Off section_to_header_mapping(Elf *elf,
- int phdr_idx,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- Elf64_Off *file_end,
- Elf64_Off *mem_end);
-
-static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
- int dynidx, /* index of .dynamic section */
- int symtabidx, /* index of symbol table section */
- shdr_info_t *shdr_info,
- int shdr_info_len);
-
-#ifdef DEBUG
-static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
- int dynidx, /* index of .dynamic section */
- int symtabidx, /* index of symbol table section */
- shdr_info_t *shdr_info,
- int shdr_info_len);
-#endif
-
-static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl,
- Elf *newelf,
- int idx, /* index of .dynamic section */
- shdr_info_t *shdr_info,
- int shdr_info_len);
-
-static void update_symbol_values(Elf *elf, GElf_Ehdr *ehdr,
- Elf *newelf,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- int shady,
- int dynamic_idx);
-
-static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr);
-
-static range_list_t *
-update_section_offsets(Elf *elf,
- Elf *newelf,
- GElf_Phdr *phdr_info,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- range_list_t *section_ranges,
- bool adjust_alloc_section_offsets);
-
-void handle_range_error(range_error_t err, range_t *left, range_t *right);
-
-#ifdef DEBUG
-static void
-verify_elf(GElf_Ehdr *ehdr, struct shdr_info_t *shdr_info, int shdr_info_len,
- GElf_Phdr *phdr_info);
-#endif
-
-void adjust_elf(Elf *elf, const char *elf_name,
- Elf *newelf, const char *newelf_name,
- Ebl *ebl,
- GElf_Ehdr *ehdr, /* store ELF header of original library */
- bool *sym_filter, int num_symbols,
- struct shdr_info_t *shdr_info, int shdr_info_len,
- GElf_Phdr *phdr_info,
- size_t highest_scn_num,
- size_t shnum,
- size_t shstrndx,
- struct Ebl_Strtab *shst,
- bool sections_dropped_or_rearranged,
- int dynamic_idx, /* index in shdr_info[] of .dynamic section */
- int dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
- int shady,
- Elf_Data **shstrtab_data,
- bool adjust_alloc_section_offsets,
- bool rebuild_shstrtab)
-{
- int cnt; /* general-purpose counter */
- Elf_Scn *scn; /* general-purpose section */
-
- *shstrtab_data = NULL;
-
- /* When this flag is true, we have dropped some symbols, which caused
- a change in the order of symbols in the symbol table (all symbols after
- the removed symbol have shifted forward), and a change in its size as
- well. When the symbol table changes this way, we need to modify the
- relocation entries that relocate symbols in this symbol table, and we
- also need to rebuild the hash table (the hash is outdated).
-
- Note that it is possible to change the symbols in the symbol table
- without changing their position (that is, without cutting any symbols
- out). If a section that a symbol refers to changes (i.e., moves), we
- need to update that section's index in the symbol entry in the symbol
- table. Therefore, there are symbol-table changes that can be made and
- still have symtab_size_changed == false!
- */
- bool symtab_size_changed = false;
-
- /* We allow adjusting of offsets only for files that are shared libraries.
- We cannot mess with the relative positions of sections for executable
- files, because we do not have enough information to adjust them. The
- text section is already linked to fixed addresses.
- */
- ASSERT(!adjust_alloc_section_offsets || ehdr->e_type == ET_DYN);
-
- if (!sections_dropped_or_rearranged)
- INFO("Note: we aren't dropping or rearranging any sections.\n");
-
- /* Index of the section header table in the shdr_info array. This is
- an important variable because it denotes the last section of the old
- file, as well as the location of the section-strings section of the
- new one.
-
- Note: we use this variable only when we are re-creating the section-
- header-strings table. Otherwise, we keep it as zero.
- */
-
- size_t shdridx = shstrndx;
- if (rebuild_shstrtab) {
- INFO("Creating new section-strings section...\n");
-
- shdridx = shnum;
-
- /* Create the new section-name-strings section */
- {
- INFO("\tNew index will be %d (was %d).\n", highest_scn_num, shstrndx);
-
- /* Add the section header string table section name. */
- shdr_info[shdridx] = shdr_info[shstrndx];
- ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab"));
- shdr_info[shdridx].se = ebl_strtabadd (shst, ".shstrtab", 10);
- ASSERT(shdr_info[shdridx].se != NULL);
- shdr_info[shdridx].idx = highest_scn_num;
-
- /* Create the section header. */
- shdr_info[shdridx].shdr.sh_type = SHT_STRTAB;
- shdr_info[shdridx].shdr.sh_flags = 0;
- shdr_info[shdridx].shdr.sh_addr = 0;
- shdr_info[shdridx].shdr.sh_link = SHN_UNDEF;
- shdr_info[shdridx].shdr.sh_info = SHN_UNDEF;
- shdr_info[shdridx].shdr.sh_entsize = 0;
-
- shdr_info[shdridx].shdr.sh_offset = shdr_info[shdridx].old_shdr.sh_offset;
- shdr_info[shdridx].shdr.sh_addralign = 1;
-
- /* Create the section. */
- FAILIF_LIBELF((shdr_info[shdridx].newscn = elf_newscn(newelf)) == NULL,
- elf_newscn);
- ASSERT(elf_ndxscn (shdr_info[shdridx].newscn) == highest_scn_num);
-
- {
- /* Finalize the string table and fill in the correct indices in
- the section headers. */
- FAILIF_LIBELF((*shstrtab_data =
- elf_newdata (shdr_info[shdridx].newscn)) == NULL,
- elf_newdata);
- ebl_strtabfinalize (shst, *shstrtab_data);
- /* We have to set the section size. */
- INFO("\tNew size will be %d.\n", (*shstrtab_data)->d_size);
- shdr_info[shdridx].shdr.sh_size = (*shstrtab_data)->d_size;
- /* Setting the data pointer tells the update loop below not to
- copy the information from the original section. */
-
- shdr_info[shdridx].data = *shstrtab_data;
-#if COPY_SECTION_DATA_BUFFER
- shdr_info[shdridx].data->d_buf = MALLOC(shdr_info[shdridx].data->d_size);
- ASSERT((*shstrtab_data)->d_buf);
- memcpy(shdr_info[shdridx].data->d_buf, (*shstrtab_data)->d_buf, (*shstrtab_data)->d_size);
-#endif
- }
- }
- } /* if (rebuild_shstrtab) */
- else {
- /* When we are not rebuilding shstrtab, we expect the input parameter
- shstrndx to be the index of .shstrtab BOTH in shdr_info[] and in
- as a section index in the ELF file.
- */
- ASSERT(!strcmp(shdr_info[shdridx].name, ".shstrtab"));
- }
-
- INFO("Updating section information...\n");
- /* Update the section information. */
-
-#ifdef DEBUG
- /* We use this flag to ASSERT that the symbol tables comes
- before the .dynamic section in the file. See comments
- further below.
- */
- bool visited_dynsym = false;
-#endif
-
- for (cnt = 1; cnt < shdr_info_len; ++cnt) {
- if (shdr_info[cnt].idx > 0) {
- Elf_Data *newdata;
-
- INFO("\t%03d: Updating section %s (index %d, address %lld offset %lld, size %lld, alignment %d)...\n",
- cnt,
- (shdr_info[cnt].name ?: "(no name)"),
- shdr_info[cnt].idx,
- shdr_info[cnt].shdr.sh_addr,
- shdr_info[cnt].shdr.sh_offset,
- shdr_info[cnt].shdr.sh_size,
- shdr_info[cnt].shdr.sh_addralign);
-
- scn = shdr_info[cnt].newscn;
- ASSERT(scn != NULL);
- ASSERT(scn == elf_getscn(newelf, shdr_info[cnt].idx));
-
- /* Update the name. */
- if (rebuild_shstrtab) {
- Elf64_Word new_sh_name = ebl_strtaboffset(shdr_info[cnt].se);
- INFO("\t\tname offset %d (was %d).\n",
- new_sh_name,
- shdr_info[cnt].shdr.sh_name);
- shdr_info[cnt].shdr.sh_name = new_sh_name;
- }
-
- /* Update the section header from the input file. Some fields
- might be section indices which now have to be adjusted. */
- if (shdr_info[cnt].shdr.sh_link != 0) {
- INFO("\t\tsh_link %d (was %d).\n",
- shdr_info[shdr_info[cnt].shdr.sh_link].idx,
- shdr_info[cnt].shdr.sh_link);
-
- shdr_info[cnt].shdr.sh_link =
- shdr_info[shdr_info[cnt].shdr.sh_link].idx;
- }
-
- /* Handle the SHT_REL, SHT_RELA, and SHF_INFO_LINK flag. */
- if (SH_INFO_LINK_P (&shdr_info[cnt].shdr)) {
- INFO("\t\tsh_info %d (was %d).\n",
- shdr_info[shdr_info[cnt].shdr.sh_info].idx,
- shdr_info[cnt].shdr.sh_info);
-
- 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, which
- has a section number equal to shnum--hence the ASSERT().
- */
- ASSERT(!rebuild_shstrtab || shdr_info[cnt].data || cnt < shnum);
- newdata = create_section_data(shdr_info + cnt, scn);
-
- /* We know the size. */
- shdr_info[cnt].shdr.sh_size = shdr_info[cnt].data->d_size;
-
- /* We have to adjust symbol tables. Each symbol contains
- a reference to the section it belongs to. Since we have
- renumbered the sections (and dropped some), we need to adjust
- the symbols' section indices as well. Also, if we do not want
- to keep a symbol, we drop it from the symbol table in this loop.
-
- When we drop symbols from the dynamic-symbol table, we need to
- remove the names of the sybmols from the dynamic-symbol-strings
- table. Changing the dynamic-symbol-strings table means that we
- also have to rebuild the strings that go into the .dynamic
- section (such as the DT_NEEDED strings, which lists the libraries
- that the file depends on), since those strings are kept in the
- same dynamic-symbol-strings table. That latter statement
- is an assumption (which we ASSERT against, read on below).
-
- Note: we process the symbol-table sections only when the user
- specifies a symbol filter AND that leads to a change in the
- symbol table, or when section indices change.
- */
-
- /* The .dynamic section's strings need not be contained in the
- same section as the strings of the dynamic symbol table,
- but we assume that they are (I haven't seen it be otherwise).
- We assert the validity of our assumption here.
-
- If this assertion fails, then we *may* need to reorganize
- this code as follows: we will need to call function
- build_dynamic_segment_strings() even when sections numbers
- don't change and there is no filter. Also, if string section
- containing the .dynamic section strings changes, then we'd
- need to update the sh_link of the .dynamic section to point
- to the new section.
- */
-
- ASSERT(shdr_info[dynamic_idx].shdr.sh_link ==
- shdr_info[dynsym_idx].shdr.sh_link);
-
- if (sections_dropped_or_rearranged || (sym_filter != NULL))
- {
- if(shdr_info[cnt].shdr.sh_type == SHT_DYNSYM)
- {
- INFO("\t\tupdating a symbol table.\n");
-
- /* Calculate the size of the external representation of a
- symbol. */
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
-
- /* Check the length of the dynamic-symbol filter. (This is the
- second of two identical checks, the first one being in
- the loop that checks for exceptions.)
-
- NOTE: We narrow this assertion down to the dynamic-symbol
- table only. Since we expect the symbol filter to
- be parallel to .dynsym, and .dynsym in general
- contains fewer symbols than .strtab, we cannot
- make this assertion for .strtab.
- */
- FAILIF(sym_filter != NULL &&
- num_symbols != shdr_info[cnt].data->d_size / elsize,
- "Length of dynsym filter (%d) must equal the number"
- " of dynamic symbols (%d) in section [%s]!\n",
- num_symbols,
- shdr_info[cnt].data->d_size / elsize,
- shdr_info[cnt].name);
-
- shdr_info[cnt].symse =
- (struct Ebl_Strent **)MALLOC(
- (shdr_info[cnt].data->d_size/elsize) *
- sizeof(struct Ebl_Strent *));
- shdr_info[cnt].dynsymst = ebl_strtabinit(1);
- FAILIF_LIBELF(NULL == shdr_info[cnt].dynsymst, ebl_strtabinit);
-
- /* Allocate an array of Elf32_Word, one for each symbol. This
- array will hold the new symbol indices.
- */
- shdr_info[cnt].newsymidx =
- (Elf32_Word *)CALLOC(shdr_info[cnt].data->d_size / elsize,
- sizeof (Elf32_Word));
-
- bool last_was_local = true;
- size_t destidx, // index of the symbol in the new symbol table
- inner, // index of the symbol in the old table
- last_local_idx = 0;
- int num_kept_undefined_and_special = 0;
- int num_kept_global_or_weak = 0;
- int num_thrown_away = 0;
-
- unsigned long num_symbols = shdr_info[cnt].data->d_size / elsize;
- INFO("\t\tsymbol table has %ld symbols.\n", num_symbols);
-
- /* In the loop below, determine whether to remove or not each
- symbol.
- */
- for (destidx = inner = 1; inner < num_symbols; ++inner)
- {
- Elf32_Word sec; /* index of section a symbol refers to */
- Elf32_Word xshndx; /* extended-section index of symbol */
- /* Retrieve symbol information and separate section index
- from the symbol table at the given index. */
- GElf_Sym sym_mem; /* holds the symbol */
-
- /* Retrieve symbol information and separate section index
- from the symbol table at the given index. */
- GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
- NULL, inner,
- &sym_mem, &xshndx);
- ASSERT(sym != NULL);
-
- FAILIF(sym->st_shndx == SHN_XINDEX,
- "Can't handle symbol's st_shndx == SHN_XINDEX!\n");
-
- /* Do not automatically strip the symbol if:
- -- the symbol filter is NULL or
- -- the symbol is marked to keep or
- -- the symbol is neither of:
- -- imported or refers to a nonstandard section
- -- global
- -- weak
-
- We do not want to strip imported symbols, because then
- we won't be able to link against them. We do not want
- to strip global or weak symbols, because then someone
- else will fail to link against them. Finally, we do
- not want to strip nonstandard symbols, because we're
- not sure what they are doing there.
- */
-
- char *symname = elf_strptr(elf,
- shdr_info[cnt].old_shdr.sh_link,
- sym->st_name);
-
- if (NULL == sym_filter || /* no symfilter */
- sym_filter[inner] || /* keep the symbol! */
- /* don't keep the symbol, but the symbol is undefined
- or refers to a specific section */
- sym->st_shndx == SHN_UNDEF || sym->st_shndx >= shnum ||
- /* don't keep the symbol, which defined and refers to
- a normal section, but the symbol is neither global
- nor weak. */
- (ELF32_ST_BIND(sym->st_info) != STB_GLOBAL &&
- ELF32_ST_BIND(sym->st_info) != STB_WEAK))
- {
- /* Do not remove the symbol. */
- if (sym->st_shndx == SHN_UNDEF ||
- sym->st_shndx >= shnum)
- {
- /* This symbol has no section index (it is
- absolute). Leave the symbol alone unless it is
- moved. */
- FAILIF_LIBELF(!(destidx == inner ||
- gelf_update_symshndx(
- shdr_info[cnt].data,
- NULL,
- destidx,
- sym,
- xshndx)),
- gelf_update_symshndx);
-
- shdr_info[cnt].newsymidx[inner] = destidx;
- INFO("\t\t\tkeeping %s symbol %d (new index %d), name [%s]\n",
- (sym->st_shndx == SHN_UNDEF ? "undefined" : "special"),
- inner,
- destidx,
- symname);
- /* mark the symbol as kept */
- if (sym_filter) sym_filter[inner] = 1;
- shdr_info[cnt].symse[destidx] =
- ebl_strtabadd (shdr_info[cnt].dynsymst,
- symname, 0);
- ASSERT(shdr_info[cnt].symse[destidx] != NULL);
- num_kept_undefined_and_special++;
- if (GELF_ST_BIND(sym->st_info) == STB_LOCAL)
- last_local_idx = destidx;
- destidx++;
- } else {
- /* Get the full section index. */
- sec = shdr_info[sym->st_shndx].idx;
-
- if (sec) {
- Elf32_Word nxshndx;
-
- ASSERT (sec < SHN_LORESERVE);
- nxshndx = 0;
-
- /* Update the symbol only if something changed,
- that is, if either the symbol's position in
- the symbol table changed (because we deleted
- some symbols), or because its section moved!
-
- NOTE: We don't update the symbol's section
- index, sym->st_shndx here, but in function
- update_symbol_values() instead. The reason
- is that if we update the symbol-section index,
- now, it won't refer anymore to the shdr_info[]
- entry, which we will need in
- update_symbol_values().
- */
- if (inner != destidx)
- {
- FAILIF_LIBELF(0 ==
- gelf_update_symshndx(
- shdr_info[cnt].data,
- NULL,
- destidx, sym,
- nxshndx),
- gelf_update_symshndx);
- }
-
- shdr_info[cnt].newsymidx[inner] = destidx;
-
- /* If we are not filtering out some symbols,
- there's no point to printing this message
- for every single symbol. */
- if (sym_filter) {
- INFO("\t\t\tkeeping symbol %d (new index %d), name (index %d) [%s]\n",
- inner,
- destidx,
- sym->st_name,
- symname);
- /* mark the symbol as kept */
- sym_filter[inner] = 1;
- }
- shdr_info[cnt].symse[destidx] =
- ebl_strtabadd(shdr_info[cnt].dynsymst,
- symname, 0);
- ASSERT(shdr_info[cnt].symse[destidx] != NULL);
- num_kept_global_or_weak++;
- if (GELF_ST_BIND(sym->st_info) == STB_LOCAL)
- last_local_idx = destidx;
- destidx++;
- } else {
- /* I am not sure, there might be other types of
- symbols that do not refer to any section, but
- I will handle them case by case when this
- assertion fails--I want to know if each of them
- is safe to remove!
- */
- ASSERT(GELF_ST_TYPE (sym->st_info) == STT_SECTION ||
- GELF_ST_TYPE (sym->st_info) == STT_NOTYPE);
- INFO("\t\t\tignoring %s symbol [%s]"
- " at index %d refering to section %d\n",
- (GELF_ST_TYPE(sym->st_info) == STT_SECTION
- ? "STT_SECTION" : "STT_NOTYPE"),
- symname,
- inner,
- sym->st_shndx);
- num_thrown_away++;
- /* mark the symbol as thrown away */
- if (sym_filter) sym_filter[inner] = 0;
- }
- }
- } /* to strip or not to strip? */
- else {
- INFO("\t\t\tremoving symbol [%s]\n", symname);
- shdr_info[cnt].newsymidx[inner] = (Elf32_Word)-1;
- num_thrown_away++;
- /* mark the symbol as thrown away */
- if (sym_filter) sym_filter[inner] = 0;
- }
-
- /* For symbol-table sections, sh_info is one greater than the
- symbol table index of the last local symbol. This is why,
- when we find the last local symbol, we update the sh_info
- field.
- */
-
- if (last_was_local) {
- if (GELF_ST_BIND (sym->st_info) != STB_LOCAL) {
- last_was_local = false;
- if (last_local_idx) {
- INFO("\t\t\tMARKING ONE PAST LAST LOCAL INDEX %d\n",
- last_local_idx + 1);
- shdr_info[cnt].shdr.sh_info =
- last_local_idx + 1;
- }
- else shdr_info[cnt].shdr.sh_info = 0;
-
- }
- } else FAILIF(0 && GELF_ST_BIND (sym->st_info) == STB_LOCAL,
- "Internal error in ELF file: symbol table has"
- " local symbols after first global"
- " symbol!\n");
- } /* for each symbol */
-
- INFO("\t\t%d undefined or special symbols were kept.\n",
- num_kept_undefined_and_special);
- INFO("\t\t%d global or weak symbols were kept.\n",
- num_kept_global_or_weak);
- INFO("\t\t%d symbols were thrown away.\n",
- num_thrown_away);
-
- if (destidx != inner) {
- /* The symbol table changed. */
- INFO("\t\t\tthe symbol table has changed.\n");
- INFO("\t\t\tdestidx = %d, inner = %d.\n", destidx, inner);
- INFO("\t\t\tnew size %d (was %lld).\n",
- destidx * elsize,
- shdr_info[cnt].shdr.sh_size);
- shdr_info[cnt].shdr.sh_size = newdata->d_size = destidx * elsize;
- symtab_size_changed = true;
- } else {
- /* The symbol table didn't really change. */
- INFO("\t\t\tthe symbol table did not change.\n");
- FREE (shdr_info[cnt].newsymidx);
- shdr_info[cnt].newsymidx = NULL;
- }
-#ifdef DEBUG
- visited_dynsym = shdr_info[cnt].shdr.sh_type == SHT_DYNSYM;
-#endif
- } /* if it's a symbol table... */
- else if (shdr_info[cnt].shdr.sh_type == SHT_DYNAMIC) {
- /* We get here either when we drop some sections, or
- when we are dropping symbols. If we are not dropping
- symbols, then the dynamic-symbol-table and its strings
- section won't change, so we won't need to rebuild the
- symbols for the SHT_DYNAMIC section either.
-
- NOTE: If ever in the future we add the ability in
- adjust_elf() to change the strings in the SHT_DYNAMIC
- section, then we would need to find a way to rebuild
- the dynamic-symbol-table-strings section.
- */
-
- /* symtab_size_changed has a meaningful value only after
- we've processed the symbol table. If this assertion
- is ever violated, it will be because the .dynamic section
- came before the symbol table in the list of section in
- a file. If that happens, then we have to break up the
- loop into two: one that finds and processes the symbol
- tables, and another, after the first one, that finds
- and handles the .dynamic sectio.
- */
- ASSERT(visited_dynsym == true);
- if (sym_filter != NULL && symtab_size_changed) {
- /* Walk the old dynamic segment. For each tag that represents
- a string, build an entry into the dynamic-symbol-table's
- strings table. */
- INFO("\t\tbuilding strings for the dynamic section.\n");
- ASSERT(cnt == dynamic_idx);
-
- /* NOTE: By passing the the index (in shdr_info[]) of the
- dynamic-symbol table to build_dynamic_segment_strings(),
- we are making the assumption that those strings will be
- kept in that table. While this does not seem to be
- mandated by the ELF spec, it seems to be always the case.
- Where else would you put these strings? You already have
- the dynamic-symbol table and its strings table, and that's
- guaranteed to be in the file, so why not put it there?
- */
- build_dynamic_segment_strings(elf, ebl,
- dynamic_idx,
- dynsym_idx,
- shdr_info,
- shdr_info_len);
- }
- else {
- INFO("\t\tThe dynamic-symbol table is not changing, so no "
- "need to rebuild strings for the dynamic section.\n");
-#ifdef DEBUG
- print_dynamic_segment_strings(elf, ebl,
- dynamic_idx,
- dynsym_idx,
- shdr_info,
- shdr_info_len);
-#endif
- }
- }
- }
-
- /* Set the section header in the new file. There cannot be any
- overflows. */
- INFO("\t\tupdating section header (size %lld)\n",
- shdr_info[cnt].shdr.sh_size);
-
- FAILIF(!gelf_update_shdr (scn, &shdr_info[cnt].shdr),
- "Could not update section header for section %s!\n",
- shdr_info[cnt].name);
- } /* if (shdr_info[cnt].idx > 0) */
- else INFO("\t%03d: not updating section %s, it will be discarded.\n",
- cnt,
- shdr_info[cnt].name);
- } /* for (cnt = 1; cnt < shdr_info_len; ++cnt) */
-
- /* Now, if we removed some symbols and thus modified the symbol table,
- we need to update the hash table, the relocation sections that use these
- symbols, and the symbol-strings table to cut out the unused symbols.
- */
- if (symtab_size_changed) {
- for (cnt = 1; cnt < shnum; ++cnt) {
- if (shdr_info[cnt].idx == 0) {
- /* Ignore sections which are discarded, unless these sections
- are relocation sections. This case is for use by the
- prelinker. */
- if (shdr_info[cnt].shdr.sh_type != SHT_REL &&
- shdr_info[cnt].shdr.sh_type != SHT_RELA) {
- continue;
- }
- }
-
- if (shdr_info[cnt].shdr.sh_type == SHT_REL ||
- shdr_info[cnt].shdr.sh_type == SHT_RELA) {
- /* shdr_info[cnt].old_shdr.sh_link is index of old symbol-table
- section that this relocation-table section was relative to.
- We can access shdr_info[] at that index to get to the
- symbol-table section.
- */
- Elf32_Word *newsymidx =
- shdr_info[shdr_info[cnt].old_shdr.sh_link].newsymidx;
-
- /* The referred-to-section must be a symbol table! Note that
- alrhough shdr_info[cnt].shdr refers to the updated section
- header, this assertion is still valid, since when updating
- the section header we never modify the sh_type field.
- */
- {
- Elf64_Word sh_type =
- shdr_info[shdr_info[cnt].shdr.sh_link].shdr.sh_type;
- FAILIF(sh_type != SHT_DYNSYM,
- "Section refered to from relocation section is not"
- " a dynamic symbol table (sh_type=%d)!\n",
- sh_type);
- }
-
- /* If that symbol table hasn't changed, then its newsymidx
- field is NULL (see comments to shdr_info_t), so we
- don't have to update this relocation-table section
- */
- if (newsymidx == NULL) continue;
-
- update_relocations_section_symbol_references(newelf, elf,
- shdr_info, shnum,
- shdr_info + cnt,
- newsymidx);
-
- } else if (shdr_info[cnt].shdr.sh_type == SHT_HASH) {
- /* We have to recompute the hash table. A hash table's
- sh_link field refers to the symbol table for which the hash
- table is generated.
- */
- Elf32_Word symtabidx = shdr_info[cnt].old_shdr.sh_link;
-
- /* We do not have to recompute the hash table if the symbol
- table was not changed. */
- if (shdr_info[symtabidx].newsymidx == NULL)
- continue;
-
- FAILIF(shdr_info[cnt].shdr.sh_entsize != sizeof (Elf32_Word),
- "Can't handle 64-bit ELF files!\n");
-
- update_hash_table(newelf, /* new ELF */
- elf, /* old ELF */
- shdr_info[cnt].idx, /* hash table index */
- shdr_info + symtabidx);
- } /* if SHT_REL else if SHT_HASH ... */
- else if (shdr_info[cnt].shdr.sh_type == SHT_DYNSYM)
- {
- /* The symbol table's sh_link field contains the index of the
- strings table for this symbol table. We want to find the
- index of the section in the shdr_info[] array. That index
- corresponds to the index of the section in the original ELF file,
- which is why we look at shdr_info[cnt].old_shdr and not
- shdr_info[cnt].shdr.
- */
-
- int symstrndx = shdr_info[cnt].old_shdr.sh_link;
- INFO("Updating [%s] (symbol-strings-section data for [%s]).\n",
- shdr_info[symstrndx].name,
- shdr_info[cnt].name);
- ASSERT(shdr_info[symstrndx].newscn);
- size_t new_symstrndx = elf_ndxscn(shdr_info[symstrndx].newscn);
- Elf_Data *newdata = elf_getdata(shdr_info[symstrndx].newscn, NULL);
- ASSERT(NULL != newdata);
- INFO("\tbefore update:\n"
- "\t\tbuffer: %p\n"
- "\t\tsize: %d\n",
- newdata->d_buf,
- newdata->d_size);
- ASSERT(shdr_info[cnt].dynsymst);
- ebl_strtabfinalize (shdr_info[cnt].dynsymst, newdata);
- INFO("\tafter update:\n"
- "\t\tbuffer: %p\n"
- "\t\tsize: %d\n",
- newdata->d_buf,
- newdata->d_size);
- FAILIF(new_symstrndx != shdr_info[cnt].shdr.sh_link,
- "The index of the symbol-strings table according to elf_ndxscn() is %d, "
- "according to shdr_info[] is %d!\n",
- new_symstrndx,
- shdr_info[cnt].shdr.sh_link);
-
- INFO("%d nonprintable\n",
- dump_hex_buffer(stdout, newdata->d_buf, newdata->d_size, 0));
-
- shdr_info[symstrndx].shdr.sh_size = newdata->d_size;
- FAILIF(!gelf_update_shdr(shdr_info[symstrndx].newscn,
- &shdr_info[symstrndx].shdr),
- "Could not update section header for section %s!\n",
- shdr_info[symstrndx].name);
-
- /* Now, update the symbol-name offsets. */
- {
- size_t i;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
- for (i = 1; i < shdr_info[cnt].shdr.sh_size / elsize; ++i) {
- Elf32_Word xshndx;
- GElf_Sym sym_mem;
- /* retrieve the symbol information; */
- GElf_Sym *sym = gelf_getsymshndx (shdr_info[cnt].data,
- NULL, i,
- &sym_mem, &xshndx);
- ASSERT(sym != NULL);
- ASSERT(NULL != shdr_info[cnt].symse[i]);
- /* calculate the new name offset; */
- size_t new_st_name =
- ebl_strtaboffset(shdr_info[cnt].symse[i]);
-#if 1
- ASSERT(!strcmp(newdata->d_buf + new_st_name,
- elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link,
- sym->st_name)));
-#endif
- if (sym_filter && (sym->st_name != new_st_name)) {
- /* FIXME: For some reason, elf_strptr() does not return the updated
- string value here. It looks like ebl_strtabfinalize() doesn't
- update libelf's internal structures well enough for elf_strptr()
- to work on an ELF file that's being compose.
- */
- INFO("Symbol [%s]'s name (index %d, old value %llx) changes offset: %d -> %d\n",
-#if 0
- newdata->d_buf + new_st_name,
-#else
- elf_strptr(elf, shdr_info[cnt].old_shdr.sh_link,
- sym->st_name),
-#endif
- i,
- sym->st_value,
- sym->st_name,
- new_st_name);
- }
- sym->st_name = new_st_name;
- /* update the symbol info; */
- FAILIF_LIBELF(0 ==
- gelf_update_symshndx(
- shdr_info[cnt].data,
- NULL,
- i, sym,
- xshndx),
- gelf_update_symshndx);
- } /* for each symbol... */
- }
- }
-
- FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GNU_versym,
- "Can't handle SHT_GNU_versym!\n");
- FAILIF(shdr_info[cnt].shdr.sh_type == SHT_GROUP,
- "Can't handle section groups!\n");
- } /* for (cnt = 1; cnt < shnum; ++cnt) */
- } /* if (symtab_size_changed) */
-
-
- range_list_t *old_section_ranges = init_range_list();
- range_list_t *section_ranges = NULL;
- /* Analyze gaps in the ranges before we compact the sections. */
- INFO("Analyzing gaps in ranges before compacting sections...\n");
- {
- size_t scnidx;
- /* Gather the ranges */
- for (scnidx = 1; scnidx < shdr_info_len; scnidx++) {
- if (shdr_info[scnidx].idx > 0) {
- if (/*shdr_info[scnidx].old_shdr.sh_type != SHT_NOBITS &&*/
- shdr_info[scnidx].old_shdr.sh_flags & SHF_ALLOC) {
- add_unique_range_nosort(
- old_section_ranges,
- shdr_info[scnidx].old_shdr.sh_addr,
- shdr_info[scnidx].old_shdr.sh_size,
- shdr_info + scnidx,
- handle_range_error,
- NULL);
- }
- }
- }
- sort_ranges(old_section_ranges);
-#ifdef DEBUG
- int num_ranges;
- /* Analyze gaps in the ranges before we compact the sections. */
- range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges);
- if (ranges) {
- GElf_Off last_end = ranges->start;
- int i;
- for (i = 0; i < num_ranges; i++) {
- shdr_info_t *curr = (shdr_info_t *)ranges[i].user;
- ASSERT(ranges[i].start >= last_end);
- int col_before, col_after;
- INFO("[%016lld, %016lld] %n[%s]%n",
- ranges[i].start,
- ranges[i].start + ranges[i].length,
- &col_before,
- curr->name,
- &col_after);
- if (ranges[i].start > last_end) {
- shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user;
- ASSERT(prev && curr);
- while (col_after++ - col_before < 20) INFO(" ");
- INFO(" [GAP: %lld bytes with %s]\n",
- (ranges[i].start - last_end),
- prev->name);
- }
- else INFO("\n");
- last_end = ranges[i].start + ranges[i].length;
- }
- }
-#endif/*DEBUG*/
- }
-
- /* Calculate the final section offsets */
- INFO("Calculating new section offsets...\n");
- section_ranges = update_section_offsets(elf,
- newelf,
- phdr_info,
- shdr_info,
- shdr_info_len,
- init_range_list(),
- adjust_alloc_section_offsets);
-
-#ifdef DEBUG
- {
- /* Analyze gaps in the ranges after we've compacted the sections. */
- int num_ranges;
- range_t *ranges = get_sorted_ranges(section_ranges, &num_ranges);
- if (ranges) {
- int last_end = ranges->start;
- int i;
- for (i = 0; i < num_ranges; i++) {
- shdr_info_t *curr = (shdr_info_t *)ranges[i].user;
- ASSERT(ranges[i].start >= last_end);
- int col_before, col_after;
- INFO("[%016lld, %016lld] %n[%s]%n",
- ranges[i].start,
- ranges[i].start + ranges[i].length,
- &col_before,
- curr->name,
- &col_after);
- if (ranges[i].start > last_end) {
- shdr_info_t *prev = (shdr_info_t *)ranges[i-1].user;
- ASSERT(prev && curr);
- while (col_after++ - col_before < 20) INFO(" ");
- INFO(" [GAP: %lld bytes with %s]\n",
- (ranges[i].start - last_end),
- prev->name);
- }
- else INFO("\n");
- last_end = ranges[i].start + ranges[i].length;
- }
- }
- }
-#endif
-
- {
- /* Now that we have modified the section offsets, we need to scan the
- symbol tables once again and update their st_value fields. A symbol's
- st_value field (in a shared library) contains the virtual address of the
- symbol. For each symbol we encounter, we look up the section it was in.
- If that section's virtual address has changed, then we calculate the
- delta and update the symbol.
- */
-
-#if 0
- {
- /* for debugging: Print out all sections and their data pointers and
- sizes. */
- int i = 1;
- for (; i < shdr_info_len; i++) {
- PRINT("%8d: %-15s: %2lld %8lld %08lx (%08lx:%8d) %08lx (%08lx:%8d)\n",
- i,
- shdr_info[i].name,
- shdr_info[i].shdr.sh_entsize,
- shdr_info[i].shdr.sh_addralign,
- (long)shdr_info[i].data,
- (long)(shdr_info[i].data ? shdr_info[i].data->d_buf : 0),
- (shdr_info[i].data ? shdr_info[i].data->d_size : 0),
- (long)shdr_info[i].newdata,
- (long)(shdr_info[i].newdata ? shdr_info[i].newdata->d_buf : 0),
- (shdr_info[i].newdata ? shdr_info[i].newdata->d_size : 0));
- if (!strcmp(shdr_info[i].name, ".got") /* ||
- !strcmp(shdr_info[i].name, ".plt") */) {
- dump_hex_buffer(stdout,
- shdr_info[i].newdata->d_buf,
- shdr_info[i].newdata->d_size,
- shdr_info[i].shdr.sh_entsize);
- }
- }
- }
-#endif
-
- INFO("Updating symbol values...\n");
- update_symbol_values(elf, ehdr, newelf, shdr_info, shdr_info_len,
- shady,
- dynamic_idx);
-
- /* If we are not stripping the debug sections, then we need to adjust
- * them accordingly, so that the new ELF file is actually debuggable.
- * For that glorios reason, we call update_dwarf(). Note that
- * update_dwarf() won't do anything if there, in fact, no debug
- * sections to speak of.
- */
-
- INFO("Updating DWARF records...\n");
- int num_total_dwarf_patches = 0, num_failed_dwarf_patches = 0;
- update_dwarf_if_necessary(
- elf, ehdr, newelf,
- shdr_info, shdr_info_len,
- &num_total_dwarf_patches, &num_failed_dwarf_patches);
- INFO("DWARF: %-15s: total %8d failed %8d.\n", elf_name, num_total_dwarf_patches, num_failed_dwarf_patches);
-
- /* Adjust the program-header table. Since the file offsets of the various
- sections may have changed, the file offsets of their containing segments
- must change as well. We update those offsets in the loop below.
- */
- {
- INFO("Adjusting program-header table...\n");
- int pi; /* program-header index */
- for (pi = 0; pi < ehdr->e_phnum; ++pi) {
- /* Print the segment number. */
- INFO("\t%2.2zu\t", pi);
- INFO("PT_ header type: %d", phdr_info[pi].p_type);
- if (phdr_info[pi].p_type == PT_NULL) {
- INFO(" PT_NULL (skip)\n");
- }
- else if (phdr_info[pi].p_type == PT_PHDR) {
- INFO(" PT_PHDR\n");
- ASSERT(phdr_info[pi].p_memsz == phdr_info[pi].p_filesz);
- /* Although adjust_elf() does not remove program-header entries,
- we perform this update here because I've seen object files
- whose PHDR table is bigger by one element than it should be.
- Here we check and correct the size, if necessary.
- */
- if (phdr_info[pi].p_memsz != ehdr->e_phentsize * ehdr->e_phnum) {
- ASSERT(phdr_info[pi].p_memsz > ehdr->e_phentsize * ehdr->e_phnum);
- INFO("WARNING: PT_PHDR file and memory sizes are incorrect (%ld instead of %ld). Correcting.\n",
- (long)phdr_info[pi].p_memsz,
- (long)(ehdr->e_phentsize * ehdr->e_phnum));
- phdr_info[pi].p_memsz = ehdr->e_phentsize * ehdr->e_phnum;
- phdr_info[pi].p_filesz = phdr_info[pi].p_memsz;
- }
- }
- else {
-
- /* Go over the section array and find which section's offset
- field matches this program header's, and update the program
- header's offset to refelect the new value.
- */
- Elf64_Off file_end, mem_end;
- Elf64_Off new_phdr_offset =
- section_to_header_mapping(elf, pi,
- shdr_info, shdr_info_len,
- &file_end,
- &mem_end);
-
- /* Alignments of 0 and 1 mean nothing. Higher alignments are
- interpreted as powers of 2. */
- if (phdr_info[pi].p_align > 1) {
- INFO("\t\tapplying alignment of 0x%llx to new offset %lld\n",
- phdr_info[pi].p_align,
- new_phdr_offset);
- new_phdr_offset &= ~(phdr_info[pi].p_align - 1);
- }
-
- Elf32_Sxword delta = new_phdr_offset - phdr_info[pi].p_offset;
-
- INFO("\t\tnew offset %lld (was %lld)\n",
- new_phdr_offset,
- phdr_info[pi].p_offset);
-
- phdr_info[pi].p_offset = new_phdr_offset;
-
- INFO("\t\tnew vaddr 0x%llx (was 0x%llx)\n",
- phdr_info[pi].p_vaddr + delta,
- phdr_info[pi].p_vaddr);
- phdr_info[pi].p_vaddr += delta;
-
- INFO("\t\tnew paddr 0x%llx (was 0x%llx)\n",
- phdr_info[pi].p_paddr + delta,
- phdr_info[pi].p_paddr);
- phdr_info[pi].p_paddr += delta;
-
- INFO("\t\tnew mem size %lld (was %lld)\n",
- mem_end - new_phdr_offset,
- phdr_info[pi].p_memsz);
- //phdr_info[pi].p_memsz = mem_end - new_phdr_offset;
- phdr_info[pi].p_memsz = mem_end - phdr_info[pi].p_vaddr;
-
- INFO("\t\tnew file size %lld (was %lld)\n",
- file_end - new_phdr_offset,
- phdr_info[pi].p_filesz);
- //phdr_info[pi].p_filesz = file_end - new_phdr_offset;
- phdr_info[pi].p_filesz = file_end - phdr_info[pi].p_offset;
- }
-
- FAILIF_LIBELF(gelf_update_phdr (newelf, pi, &phdr_info[pi]) == 0,
- gelf_update_phdr);
- }
- }
-
- if (dynamic_idx >= 0) {
- /* NOTE: dynamic_idx is the index of .dynamic section in the shdr_info[] array, NOT the
- index of the section in the ELF file!
- */
- adjust_dynamic_segment_offsets(elf, ebl,
- newelf,
- dynamic_idx,
- shdr_info,
- shdr_info_len);
- }
- else INFO("There is no dynamic section in this file.\n");
-
- /* Walk the relocation sections (again). This time, update offsets of the
- relocation entries. Note that there is an implication here that the
- offsets are virual addresses, because we are handling a shared library!
- */
- for (cnt = 1; cnt < shdr_info_len; cnt++) {
- /* Note here that we process even those relocation sections that are
- * marked for removal. Normally, we wouldn't need to do this, but
- * in the case where we run adjust_elf() after a dry run of
- * prelink() (see apriori), we still want to update the relocation
- * offsets because those will be picked up by the second run of
- * prelink(). If this all seems too cryptic, go yell at Iliyan
- * Malchev.
- */
- if (/* shdr_info[cnt].idx > 0 && */
- (shdr_info[cnt].shdr.sh_type == SHT_REL ||
- shdr_info[cnt].shdr.sh_type == SHT_RELA))
- {
- int hacked = shdr_info[cnt].idx == 0;
- Elf_Data *data;
- if (hacked) {
- /* This doesn't work! elf_ndxscn(shdr_info[cnt].scn) will return the section number
- of the new sectin that has moved into this slot. */
- shdr_info[cnt].idx = elf_ndxscn(shdr_info[cnt].scn);
- data = elf_getdata (elf_getscn (elf, shdr_info[cnt].idx), NULL);
- INFO("PRELINKER HACK: Temporarily restoring index of to-be-removed section [%s] to %d.\n",
- shdr_info[cnt].name,
- shdr_info[cnt].idx);
- }
- else
- data = elf_getdata (elf_getscn (newelf, shdr_info[cnt].idx), NULL);
-
- update_relocations_section_offsets(newelf, elf, ebl,
- shdr_info, shdr_info_len,
- shdr_info + cnt,
- data,
- old_section_ranges);
- if (hacked) {
- INFO("PRELINKER HACK: Done with hack, marking section [%s] for removal again.\n",
- shdr_info[cnt].name);
- shdr_info[cnt].idx = 0;
- }
- }
- }
- }
-
- /* Finally finish the ELF header. Fill in the fields not handled by
- libelf from the old file. */
- {
- GElf_Ehdr *newehdr, newehdr_mem;
- newehdr = gelf_getehdr (newelf, &newehdr_mem);
- FAILIF_LIBELF(newehdr == NULL, gelf_getehdr);
-
- INFO("Updating ELF header.\n");
-
- 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 = get_last_address(section_ranges);
- newehdr->e_shoff += offsize - 1;
- newehdr->e_shoff &= ~((GElf_Off) (offsize - 1));
- newehdr->e_shentsize = gelf_fsize (elf, ELF_T_SHDR, 1, EV_CURRENT);
- INFO("\tsetting section-header-table offset to %lld\n",
- newehdr->e_shoff);
- }
-
- if (rebuild_shstrtab) {
- /* If we are rebuilding the section-headers string table, then
- the new index must not be zero. This is to guard against
- code breakage resulting from rebuild_shstrtab and shdridx
- somehow getting out of sync. */
- ASSERT(shdridx);
- /* The new section header string table index. */
- FAILIF(!(shdr_info[shdridx].idx < SHN_HIRESERVE) &&
- likely (shdr_info[shdridx].idx != SHN_XINDEX),
- "Can't handle extended section indices!\n");
- }
-
- INFO("Index of shstrtab is now %d (was %d).\n",
- shdr_info[shdridx].idx,
- ehdr->e_shstrndx);
- newehdr->e_shstrndx = shdr_info[shdridx].idx;
-
- FAILIF_LIBELF(gelf_update_ehdr(newelf, newehdr) == 0, gelf_update_ehdr);
- }
- if (section_ranges != NULL) destroy_range_list(section_ranges);
- destroy_range_list(old_section_ranges);
-
-#ifdef DEBUG
- verify_elf (ehdr, shdr_info, shdr_info_len, phdr_info);
-#endif
-
-}
-
-static void update_hash_table(Elf *newelf, Elf *elf,
- Elf32_Word hash_scn_idx,
- shdr_info_t *symtab_info) {
- GElf_Shdr shdr_mem, *shdr = NULL;
- Elf32_Word *chain;
- Elf32_Word nbucket;
-
- /* The hash table section and data in the new file. */
- Elf_Scn *hashscn = elf_getscn (newelf, hash_scn_idx);
- ASSERT(hashscn != NULL);
- Elf_Data *hashd = elf_getdata (hashscn, NULL);
- ASSERT (hashd != NULL);
- Elf32_Word *bucket = (Elf32_Word *) hashd->d_buf; /* Sane arches first. */
-
- /* The symbol table data. */
- Elf_Data *symd = elf_getdata (elf_getscn (newelf, symtab_info->idx), NULL);
- ASSERT (symd != NULL);
-
- GElf_Ehdr ehdr_mem;
- GElf_Ehdr *ehdr = gelf_getehdr (elf, &ehdr_mem);
- FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
- size_t strshndx = symtab_info->old_shdr.sh_link;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1,
- ehdr->e_version);
-
- /* Convert to the correct byte order. */
- FAILIF_LIBELF(gelf_xlatetom (newelf, hashd, hashd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL,
- gelf_xlatetom);
-
- /* Adjust the nchain value. The symbol table size changed. We keep the
- same size for the bucket array. */
- INFO("hash table: buckets: %d (no change).\n", bucket[0]);
- INFO("hash table: chains: %d (was %d).\n",
- symd->d_size / elsize,
- bucket[1]);
- bucket[1] = symd->d_size / elsize;
- nbucket = bucket[0];
- bucket += 2;
- chain = bucket + nbucket;
-
- /* New size of the section. */
- shdr = gelf_getshdr (hashscn, &shdr_mem);
- ASSERT(shdr->sh_type == SHT_HASH);
- shdr->sh_size = (2 + symd->d_size / elsize + nbucket) * sizeof (Elf32_Word);
- INFO("hash table: size %lld (was %d) bytes.\n",
- shdr->sh_size,
- hashd->d_size);
- hashd->d_size = shdr->sh_size;
- (void)gelf_update_shdr (hashscn, shdr);
-
- /* Clear the arrays. */
- memset (bucket, '\0',
- (symd->d_size / elsize + nbucket)
- * sizeof (Elf32_Word));
-
- size_t inner;
- for (inner = symtab_info->shdr.sh_info;
- inner < symd->d_size / elsize;
- ++inner) {
- const char *name;
- GElf_Sym sym_mem;
- GElf_Sym *sym = gelf_getsym (symd, inner, &sym_mem);
- ASSERT (sym != NULL);
-
- name = elf_strptr (elf, strshndx, sym->st_name);
- ASSERT (name != NULL);
- size_t hidx = elf_hash (name) % nbucket;
-
- if (bucket[hidx] == 0)
- bucket[hidx] = inner;
- else {
- hidx = bucket[hidx];
- while (chain[hidx] != 0)
- hidx = chain[hidx];
- chain[hidx] = inner;
- }
- }
-
- /* Convert back to the file byte order. */
- FAILIF_LIBELF(gelf_xlatetof (newelf, hashd, hashd,
- BYTE_ORDER == LITTLE_ENDIAN
- ? ELFDATA2LSB : ELFDATA2MSB) == NULL,
- gelf_xlatetof);
-}
-
-/* This function updates the symbol indices of relocation entries. It does not
- update the section offsets of those entries.
-*/
-static void update_relocations_section_symbol_references(
- Elf *newelf, Elf *elf __attribute__((unused)),
- shdr_info_t *info,
- int info_len __attribute__((unused)),
- shdr_info_t *relsect_info,
- Elf32_Word *newsymidx)
-{
- /* Get this relocation section's data */
- Elf_Data *d = elf_getdata (elf_getscn (newelf, relsect_info->idx), NULL);
- ASSERT (d != NULL);
- ASSERT (d->d_size == relsect_info->shdr.sh_size);
-
- size_t old_nrels =
- relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize;
- size_t new_nrels =
- relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize;
-
- size_t nrels = new_nrels;
- if (relsect_info->use_old_shdr_for_relocation_calculations) {
- nrels = old_nrels;
- /* Now, we update d->d_size to point to the old size in order to
- prevent gelf_update_rel() and gelf_update_rela() from returning
- an error. We restore the value at the end of the function.
- */
- d->d_size = old_nrels * relsect_info->shdr.sh_entsize;
- }
-
- /* Now, walk the relocations one by one. For each relocation,
- check to see whether the symbol it refers to has a new
- index in the symbol table, and if so--update it. We know
- if a symbol's index has changed when we look up that
- the newsymidx[] array at the old index. If the value at that
- location is different from the array index, then the
- symbol's index has changed; otherwise, it remained the same.
- */
- INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n",
- nrels,
- relsect_info->name,
- (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"),
- old_nrels, new_nrels);
-
- size_t relidx, newidx;
- if (relsect_info->shdr.sh_type == SHT_REL) {
- for (newidx = relidx = 0; relidx < nrels; ++relidx) {
- GElf_Rel rel_mem;
- FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL,
- gelf_getrel);
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != (Elf32_Word)-1)
- {
- rel_mem.r_info = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
- FAILIF_LIBELF(gelf_update_rel (d, newidx, &rel_mem) == 0,
- gelf_update_rel);
- newidx++;
- }
- else {
- INFO("Discarding REL entry for symbol [%d], section [%d]\n",
- symidx,
- relsect_info->shdr.sh_info);
- }
- } /* for each rel entry... */
- } else {
- for (newidx = relidx = 0; relidx < nrels; ++relidx) {
- GElf_Rela rel_mem;
- FAILIF_LIBELF(gelf_getrela (d, relidx, &rel_mem) == NULL,
- gelf_getrela);
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- if (newsymidx[symidx] != (Elf32_Word)-1)
- {
- rel_mem.r_info
- = GELF_R_INFO (newsymidx[symidx],
- GELF_R_TYPE (rel_mem.r_info));
-
- FAILIF_LIBELF(gelf_update_rela (d, newidx, &rel_mem) == 0,
- gelf_update_rela);
- newidx++;
- }
- else {
- INFO("Discarding RELA entry for symbol [%d], section [%d]\n",
- symidx,
- relsect_info->shdr.sh_info);
- }
- } /* for each rela entry... */
- } /* if rel else rela */
-
- if (newidx != relidx)
- {
- INFO("Shrinking relocation section from %lld to %lld bytes (%d -> %d "
- "entries).\n",
- relsect_info->shdr.sh_size,
- relsect_info->shdr.sh_entsize * newidx,
- relidx,
- newidx);
-
- d->d_size = relsect_info->shdr.sh_size =
- relsect_info->shdr.sh_entsize * newidx;
- } else INFO("Relocation section [%s]'s size (relocates: %s(%d), "
- "symab: %s(%d)) does not change.\n",
- relsect_info->name,
- info[relsect_info->shdr.sh_info].name,
- relsect_info->shdr.sh_info,
- info[relsect_info->shdr.sh_link].name,
- relsect_info->shdr.sh_link);
-
- /* Restore d->d_size if necessary. */
- if (relsect_info->use_old_shdr_for_relocation_calculations)
- d->d_size = new_nrels * relsect_info->shdr.sh_entsize;
-}
-
-static void update_relocations_section_offsets(Elf *newelf, Elf *elf __attribute((unused)),
- Ebl *ebl __attribute__((unused)),
- shdr_info_t *info,
- int info_len __attribute__((unused)),
- shdr_info_t *relsect_info,
- Elf_Data *d,
- range_list_t *old_section_ranges)
-{
- /* Get this relocation section's data */
- ASSERT (d != NULL);
- if (d->d_size != relsect_info->shdr.sh_size) {
- /* This is not necessarily a fatal error. In the case where we call adjust_elf() from apriori
- (the prelinker), we may call this function for a relocation section that is marked for
- removal. We still want to process this relocation section because, even though it is marked
- for removal, its relocatin entries will be used by the prelinker to know what to prelink.
- Once the prelinker is done, it will call adjust_elf() one more time to actually eliminate the
- relocation section. */
- PRINT("WARNING: section size according to section [%s]'s header is %lld, but according to data buffer is %ld.\n",
- relsect_info->name,
- relsect_info->shdr.sh_size,
- d->d_size);
- ASSERT((relsect_info->shdr.sh_type == SHT_REL || relsect_info->shdr.sh_type == SHT_RELA) &&
- relsect_info->use_old_shdr_for_relocation_calculations);
- }
-
- size_t old_nrels =
- relsect_info->old_shdr.sh_size / relsect_info->old_shdr.sh_entsize;
- size_t new_nrels =
- relsect_info->shdr.sh_size / relsect_info->shdr.sh_entsize;
-
- size_t nrels = new_nrels;
- if (relsect_info->use_old_shdr_for_relocation_calculations) {
- nrels = old_nrels;
- /* Now, we update d->d_size to point to the old size in order to
- prevent gelf_update_rel() and gelf_update_rela() from returning
- an error. We restore the value at the end of the function.
- */
- d->d_size = old_nrels * relsect_info->shdr.sh_entsize;
- }
-
- /* Now, walk the relocations one by one. For each relocation,
- check to see whether the symbol it refers to has a new
- index in the symbol table, and if so--update it. We know
- if a symbol's index has changed when we look up that
- the newsymidx[] array at the old index. If the value at that
- location is different from the array index, then the
- symbol's index has changed; otherwise, it remained the same.
- */
- INFO("Scanning %d relocation entries in section [%s] (taken from %s section header (old %d, new %d))...\n",
- nrels,
- relsect_info->name,
- (relsect_info->use_old_shdr_for_relocation_calculations ? "old" : "new"),
- old_nrels, new_nrels);
-
- if (relsect_info->old_shdr.sh_info == 0) {
- PRINT("WARNING: Relocation section [%s] relocates the NULL section.\n",
- relsect_info->name);
- }
- else {
- FAILIF(info[relsect_info->old_shdr.sh_info].idx == 0,
- "Section [%s] relocates section [%s] (index %d), which is being "
- "removed!\n",
- relsect_info->name,
- info[relsect_info->old_shdr.sh_info].name,
- relsect_info->old_shdr.sh_info);
- }
-
- size_t relidx;
- FAILIF(relsect_info->shdr.sh_type == SHT_RELA,
- "Can't handle SHT_RELA relocation entries.\n");
-
- if (relsect_info->shdr.sh_type == SHT_REL) {
- for (relidx = 0; relidx < nrels; ++relidx) {
- GElf_Rel rel_mem;
- FAILIF_LIBELF(gelf_getrel (d, relidx, &rel_mem) == NULL,
- gelf_getrel);
-
- if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_NONE)
- continue;
-
- range_t *old_range = find_range(old_section_ranges,
- rel_mem.r_offset);
-#if 1
- if (NULL == old_range) {
- GElf_Sym *sym, sym_mem;
- unsigned sym_idx = GELF_R_SYM(rel_mem.r_info);
- /* relsect_info->shdr.sh_link is the index of the associated
- symbol table. */
- sym = gelf_getsymshndx(info[relsect_info->shdr.sh_link].data,
- NULL,
- sym_idx,
- &sym_mem,
- NULL);
- /* info[relsect_info->shdr.sh_link].shdr.sh_link is the index
- of the string table associated with the symbol table
- associated with the relocation section rel_sect. */
- const char *symname = elf_strptr(elf,
- info[relsect_info->shdr.sh_link].shdr.sh_link,
- sym->st_name);
-
- {
- int i = 0;
- INFO("ABOUT TO FAIL for symbol [%s]: old section ranges:\n", symname);
-
- int num_ranges;
- range_t *ranges = get_sorted_ranges(old_section_ranges, &num_ranges);
-
- for (; i < num_ranges; i++) {
- shdr_info_t *inf = (shdr_info_t *)ranges[i].user;
- INFO("\t[%8lld, %8lld] (%8lld bytes) [%8lld, %8lld] (%8lld bytes) [%-15s]\n",
- ranges[i].start,
- ranges[i].start + ranges[i].length,
- ranges[i].length,
- inf->old_shdr.sh_addr,
- inf->old_shdr.sh_addr + inf->old_shdr.sh_size,
- inf->old_shdr.sh_size,
- inf->name);
- }
- INFO("\n");
- }
-
- FAILIF(1,
- "No range matches relocation entry value 0x%llx (%d) [%s]!\n",
- rel_mem.r_offset,
- rel_mem.r_offset,
- symname);
- }
-#else
- FAILIF(NULL == old_range,
- "No range matches relocation entry value 0x%llx!\n",
- rel_mem.r_offset);
-#endif
- ASSERT(old_range->start <= rel_mem.r_offset &&
- rel_mem.r_offset < old_range->start + old_range->length);
- ASSERT(old_range->user);
- shdr_info_t *old_range_info = (shdr_info_t *)old_range->user;
- ASSERT(old_range_info->idx > 0);
- if (relsect_info->old_shdr.sh_info &&
- old_range_info->idx != relsect_info->old_shdr.sh_info) {
- PRINT("Relocation offset 0x%llx does not match section [%s] "
- "but section [%s]!\n",
- rel_mem.r_offset,
- info[relsect_info->old_shdr.sh_info].name,
- old_range_info->name);
- }
-
-#if 0 /* This is true only for shared libraries, but not for executables */
- ASSERT(old_range_info->shdr.sh_addr == old_range_info->shdr.sh_offset);
- ASSERT(old_range_info->old_shdr.sh_addr == old_range_info->old_shdr.sh_offset);
-#endif
- Elf64_Sxword delta =
- old_range_info->shdr.sh_addr - old_range_info->old_shdr.sh_addr;
-
- if (delta) {
- extern int verbose_flag;
- /* Print out some info about the relocation entry we are
- modifying. */
- if (unlikely(verbose_flag)) {
- /* Get associated (new) symbol table. */
- Elf64_Word symtab = relsect_info->shdr.sh_link;
- /* Get the symbol that is being relocated. */
- size_t symidx = GELF_R_SYM (rel_mem.r_info);
- GElf_Sym sym_mem, *sym;
- /* Since by now we've already updated the symbol index,
- we need to retrieve the symbol from the new symbol table.
- */
- sym = gelf_getsymshndx (elf_getdata(info[symtab].newscn, NULL),
- NULL,
- symidx, &sym_mem, NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- char buf[64];
- INFO("\t%02d (%-15s) off 0x%llx -> 0x%llx (%lld) (relocates [%s:(%d)%s])\n",
- (unsigned)GELF_R_TYPE(rel_mem.r_info),
- ebl_reloc_type_name(ebl,
- GELF_R_TYPE(rel_mem.r_info),
- buf,
- sizeof(buf)),
- rel_mem.r_offset, rel_mem.r_offset + delta, delta,
- old_range_info->name,
- symidx,
-#if ELF_STRPTR_IS_BROKEN
- /* libelf does not keep track of changes very well.
- Looks like, if you use elf_strptr() on a file that
- has not been updated yet, you get bogus results. */
- ((char *)info[info[symtab].old_shdr.sh_link].
- newdata->d_buf) + sym->st_name
-#else
- elf_strptr(newelf,
- info[symtab].shdr.sh_link,
- sym->st_name)
-#endif
- );
- } /* if (verbose_flag) */
-
- rel_mem.r_offset += delta;
- FAILIF_LIBELF(gelf_update_rel (d, relidx, &rel_mem) == 0,
- gelf_update_rel);
-
-#ifdef ARM_SPECIFIC_HACKS
- if (GELF_R_TYPE(rel_mem.r_info) == R_ARM_RELATIVE) {
- FAILIF(GELF_R_SYM(rel_mem.r_info) != 0,
- "Can't handle relocation!\n");
- /* From the ARM documentation: "when the symbol is zero,
- the R_ARM_RELATIVE entry resolves to the difference
- between the address at which the segment being
- relocated was loaded and the address at which it
- was linked."
- */
-
- int *ptr =
- (int *)(((char *)old_range_info->newdata->d_buf) +
- (rel_mem.r_offset -
- old_range_info->shdr.sh_addr));
- *ptr += (int)delta;
-
- }
-#endif
- } /* if (delta) */
- } /* for each rel entry... */
- }
-
- /* Restore d->d_size if necessary. */
- if (relsect_info->use_old_shdr_for_relocation_calculations)
- d->d_size = new_nrels * relsect_info->shdr.sh_entsize;
-}
-
-static inline
-Elf_Data *create_section_data(shdr_info_t *info, Elf_Scn *scn)
-{
- Elf_Data *newdata = NULL;
-
- if (info->data == NULL) {
- info->data = elf_getdata (info->scn, NULL);
- FAILIF_LIBELF(NULL == info->data, elf_getdata);
- INFO("\t\tcopying data from original section (%d bytes).\n",
- info->data->d_size);
- /* Set the data. This is done by copying from the old file. */
- newdata = elf_newdata (scn);
- FAILIF_LIBELF(newdata == NULL, elf_newdata);
- /* Copy the structure. Note that the data buffer pointer gets
- copied, but the buffer itself does not. */
- *newdata = *info->data;
-#if COPY_SECTION_DATA_BUFFER
- if (info->data->d_buf != NULL) {
- newdata->d_buf = MALLOC(newdata->d_size);
- memcpy(newdata->d_buf, info->data->d_buf, newdata->d_size);
- }
-#endif
- } else {
- INFO("\t\tassigning new data to section (%d bytes).\n",
- info->data->d_size);
- newdata = info->data;
- }
-
- info->newdata = newdata;
- return newdata;
-}
-
-#if 0
-static void print_shdr_array(shdr_info_t *info, int num_entries) {
- extern int verbose_flag;
- if (verbose_flag) {
- int i;
- for (i = 0; i < num_entries; i++) {
- INFO("%03d:"
- "\tname [%s]\n"
- "\tidx [%d]\n",
- i, info[i].name, info[i].idx);
- }
- } /* if (verbose_flag) */
-}
-#endif
-
-static size_t do_update_dyn_entry_address(Elf *elf,
- GElf_Dyn *dyn,
- shdr_info_t *shdr_info,
- int shdr_info_len,
- int newline)
-{
- size_t scnidx = 0;
- INFO("%#0*llx",
- gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
- dyn->d_un.d_val);
- for (scnidx = 1; scnidx < shdr_info_len; scnidx++) {
- if (shdr_info[scnidx].old_shdr.sh_addr == dyn->d_un.d_ptr) {
- if (shdr_info[scnidx].idx > 0) {
- INFO(" (updating to 0x%08llx per section %d (shdr_info[] index %d): [%s])",
- shdr_info[scnidx].shdr.sh_addr,
- shdr_info[scnidx].idx,
- scnidx,
- shdr_info[scnidx].name);
- dyn->d_un.d_ptr = shdr_info[scnidx].shdr.sh_addr;
- break;
- }
- else {
- /* FIXME: This should be more intelligent. What if there is more than one section that fits the
- dynamic entry, and just the first such is being removed? We should keep on searching here.
- */
- INFO(" (Setting to ZERO per section (shdr_info[] index %d) [%s], which is being removed)",
- scnidx,
- shdr_info[scnidx].name);
- dyn->d_un.d_ptr = 0;
- break;
- }
- }
- }
- if (newline) INFO("\n");
- return scnidx == shdr_info_len ? 0 : scnidx;
-}
-
-static inline size_t update_dyn_entry_address(Elf *elf,
- GElf_Dyn *dyn,
- shdr_info_t *shdr_info,
- int shdr_info_len)
-{
- return do_update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len, 1);
-}
-
-static void update_dyn_entry_address_and_size(Elf *elf, Ebl *oldebl,
- GElf_Dyn *dyn,
- shdr_info_t *shdr_info,
- int shdr_info_len,
- Elf_Data *dyn_data,
- size_t *dyn_size_entries,
- int dyn_entry_idx)
-{
- size_t scnidx = do_update_dyn_entry_address(elf, dyn,
- shdr_info, shdr_info_len,
- 0);
- if (scnidx) {
- char buf[64];
- INFO(" (affects tag %s)",
- ebl_dynamic_tag_name(oldebl, dyn_entry_idx,
- buf, sizeof (buf)));
- if (dyn_size_entries[dyn_entry_idx]) {
- /* We previously encountered this size entry, and because
- we did not know which section would affect it, we saved its
- index in the dyn_size_entries[] array so that we can update
- the entry when we do know. Now we know that the field
- shdr_info[scnidx].shdr.sh_size contains that new value.
- */
- GElf_Dyn *szdyn, szdyn_mem;
-
- szdyn = gelf_getdyn (dyn_data,
- dyn_size_entries[dyn_entry_idx],
- &szdyn_mem);
- FAILIF_LIBELF(NULL == szdyn, gelf_getdyn);
- ASSERT(szdyn->d_tag == dyn_entry_idx);
-
- INFO("\n (!)\t%-17s completing deferred update (%lld -> %lld bytes)"
- " per section %d [%s]",
- ebl_dynamic_tag_name (oldebl, szdyn->d_tag,
- buf, sizeof (buf)),
- szdyn->d_un.d_val,
- shdr_info[scnidx].shdr.sh_size,
- shdr_info[scnidx].idx,
- shdr_info[scnidx].name);
-
- szdyn->d_un.d_val = shdr_info[scnidx].shdr.sh_size;
- FAILIF_LIBELF(0 == gelf_update_dyn(dyn_data,
- dyn_size_entries[dyn_entry_idx],
- szdyn),
- gelf_update_dyn);
-#ifdef DEBUG
- dyn_size_entries[dyn_entry_idx] = -1;
-#endif
- }
- else dyn_size_entries[dyn_entry_idx] = scnidx;
- } /* if (scnidx) */
-
- INFO("\n");
-}
-
-static void do_build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
- int dynidx, /* index of .dynamic section */
- int symtabidx, /* index of symbol table section */
- shdr_info_t *shdr_info,
- int shdr_info_len __attribute__((unused)),
- bool print_strings_only)
-{
- Elf_Scn *dynscn = elf_getscn(elf, dynidx);
- FAILIF_LIBELF(NULL == dynscn, elf_getscn);
- Elf_Data *data = elf_getdata (dynscn, NULL);
- ASSERT(data != NULL);
-
- size_t cnt;
-
- if (!print_strings_only) {
- /* Allocate an array of string-offset structures. */
- shdr_info[dynidx].symse =
- (struct Ebl_Strent **)CALLOC(
- shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize,
- sizeof(struct Ebl_Strent *));
- }
-
- for (cnt = 0;
- cnt < shdr_info[dynidx].shdr.sh_size/shdr_info[dynidx].shdr.sh_entsize;
- ++cnt)
- {
- char buf[64];
- GElf_Dyn dynmem;
- GElf_Dyn *dyn;
-
- dyn = gelf_getdyn (data, cnt, &dynmem);
- FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
-
- switch (dyn->d_tag) {
- case DT_NEEDED:
- case DT_SONAME:
- case DT_RPATH:
- case DT_RUNPATH:
- {
- const char *str =
- elf_strptr (elf,
- shdr_info[dynidx].shdr.sh_link,
- dyn->d_un.d_val);
- ASSERT(str != NULL);
- INFO("\t\t\t%-17s: ",
- ebl_dynamic_tag_name (oldebl,
- dyn->d_tag,
- buf, sizeof (buf)));
- INFO("[%s] (offset %ld)\n", str, dyn->d_un.d_val);
- if (!print_strings_only) {
- /* We append the strings to the string table belonging to the
- dynamic-symbol-table section. We keep the dynsymst handle
- for the strings section in the shdr_info[] entry for the
- dynamic-sybmol table. Confusing, I know.
- */
- ASSERT(shdr_info[symtabidx].dynsymst);
- /* The string tables for the symbol table and the .dynamic
- section must be the same.
- */
- ASSERT(shdr_info[symtabidx].shdr.sh_link ==
- shdr_info[dynidx].shdr.sh_link);
- shdr_info[dynidx].symse[cnt] =
- ebl_strtabadd(shdr_info[symtabidx].dynsymst, str?:"", 0);
- ASSERT(shdr_info[dynidx].symse[cnt] != NULL);
- }
- }
- break;
- default:
- break;
- }
- } /* for (...) */
-} /* build_dynamic_segment_strings() */
-
-static void build_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
- int dynidx, /* index of .dynamic section */
- int symtabidx, /* index of symbol table section */
- shdr_info_t *shdr_info,
- int shdr_info_len __attribute__((unused)))
-{
- INFO("\t\tbuilding string offsets for dynamic section [%s], index %d\n",
- shdr_info[dynidx].name,
- dynidx);
- do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx,
- shdr_info, shdr_info_len, false);
-}
-
-#ifdef DEBUG
-static void print_dynamic_segment_strings(Elf *elf, Ebl *oldebl,
- int dynidx, /* index of .dynamic section */
- int symtabidx, /* index of symbol table section */
- shdr_info_t *shdr_info,
- int shdr_info_len __attribute__((unused)))
-{
- INFO("\t\tprinting string offsets for dynamic section [%s], index %d\n",
- shdr_info[dynidx].name,
- dynidx);
- do_build_dynamic_segment_strings(elf, oldebl, dynidx, symtabidx,
- shdr_info, shdr_info_len, true);
-}
-#endif
-
-static void adjust_dynamic_segment_offsets(Elf *elf, Ebl *oldebl,
- Elf *newelf,
- int dynidx, /* index of .dynamic section in shdr_info[] */
- shdr_info_t *shdr_info,
- int shdr_info_len)
-{
- Elf_Scn *scn = shdr_info[dynidx].newscn;
- FAILIF_LIBELF(NULL == scn, elf_getscn);
- Elf_Data *data = elf_getdata (scn, NULL);
- ASSERT(data != NULL);
-
- size_t cnt;
- INFO("Updating dynamic section [%s], index %d\n",
- shdr_info[dynidx].name,
- dynidx);
-
- size_t *dyn_size_entries = (size_t *)CALLOC(DT_NUM, sizeof(size_t));
-
- ASSERT(data->d_type == ELF_T_DYN);
-
- for (cnt = 0; cnt < shdr_info[dynidx].shdr.sh_size / shdr_info[dynidx].shdr.sh_entsize; ++cnt) {
- char buf[64];
- GElf_Dyn dynmem;
- GElf_Dyn *dyn;
-
- dyn = gelf_getdyn (data, cnt, &dynmem);
- FAILIF_LIBELF(NULL == dyn, gelf_getdyn);
-
- INFO("\t%-17s ",
- ebl_dynamic_tag_name (oldebl, dyn->d_tag, buf, sizeof (buf)));
-
- switch (dyn->d_tag) {
- /* Updates to addresses */
-
- /* We assume that the address entries come before the size entries.
- */
-
- case DT_PLTGOT:
- case DT_HASH:
- case DT_SYMTAB:
- (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len);
- break;
- case DT_STRTAB:
- /* Defer-update DT_STRSZ as well, if not already updated. */
- update_dyn_entry_address_and_size(elf, oldebl, dyn,
- shdr_info, shdr_info_len,
- data,
- dyn_size_entries,
- DT_STRSZ);
- break;
- case DT_RELA:
- /* Defer-update DT_RELASZ as well, if not already updated. */
- update_dyn_entry_address_and_size(elf, oldebl, dyn,
- shdr_info, shdr_info_len,
- data,
- dyn_size_entries,
- DT_RELASZ);
- break;
- case DT_REL:
- /* Defer-update DT_RELSZ as well, if not already updated. */
- update_dyn_entry_address_and_size(elf, oldebl, dyn,
- shdr_info, shdr_info_len,
- data,
- dyn_size_entries,
- DT_RELSZ);
- break;
- case DT_JMPREL:
- /* Defer-update DT_PLTRELSZ as well, if not already updated. */
- update_dyn_entry_address_and_size(elf, oldebl, dyn,
- shdr_info, shdr_info_len,
- data,
- dyn_size_entries,
- DT_PLTRELSZ);
- break;
- case DT_INIT_ARRAY:
- case DT_FINI_ARRAY:
- case DT_PREINIT_ARRAY:
- case DT_INIT:
- case DT_FINI:
- (void)update_dyn_entry_address(elf, dyn, shdr_info, shdr_info_len);
- break;
-
- /* Updates to sizes */
- case DT_PLTRELSZ: /* DT_JMPREL or DT_PLTGOT */
- case DT_STRSZ: /* DT_STRTAB */
- case DT_RELSZ: /* DT_REL */
- case DT_RELASZ: /* DR_RELA */
- if (dyn_size_entries[dyn->d_tag] == 0) {
- /* We have not yet found the new size for this entry, so we
- save the index of the dynamic entry in the dyn_size_entries[]
- array. When we find the section affecting this field (in
- code above), we will update the entry.
- */
- INFO("(!) (deferring update: new value not known yet)\n");
- dyn_size_entries[dyn->d_tag] = cnt;
- }
- else {
- ASSERT(dyn_size_entries[dyn->d_tag] < shdr_info_len);
- INFO("%lld (bytes) (updating to %lld bytes "
- "per section %d [%s])\n",
- dyn->d_un.d_val,
- shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size,
- shdr_info[dyn_size_entries[dyn->d_tag]].idx,
- shdr_info[dyn_size_entries[dyn->d_tag]].name);
- dyn->d_un.d_val =
- shdr_info[dyn_size_entries[dyn->d_tag]].shdr.sh_size;
-#ifdef DEBUG
- /* Clear the array so that we know we are done with it. */
- dyn_size_entries[dyn->d_tag] = (size_t)-1;
-#endif
- }
- break;
- /* End of updates. */
-
- case DT_NULL:
- case DT_DEBUG:
- case DT_BIND_NOW:
- case DT_TEXTREL:
- /* No further output. */
- INFO("\n");
- break;
-
- /* String-entry updates. */
- case DT_NEEDED:
- case DT_SONAME:
- case DT_RPATH:
- case DT_RUNPATH:
- if (shdr_info[dynidx].symse != NULL)
- {
- Elf64_Xword new_offset =
- ebl_strtaboffset(shdr_info[dynidx].symse[cnt]);
- INFO("string [%s] offset changes: %lld -> %lld\n",
- elf_strptr (elf,
- shdr_info[dynidx].shdr.sh_link,
- dyn->d_un.d_val),
- dyn->d_un.d_val,
- new_offset);
- dyn->d_un.d_val = new_offset;
- FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn),
- gelf_update_dyn);
- }
- else
- INFO("string [%s] offset has not changed from %lld, not updating\n",
- elf_strptr (elf,
- shdr_info[dynidx].shdr.sh_link,
- dyn->d_un.d_val),
- dyn->d_un.d_val);
- break;
-
- case DT_RELAENT:
- case DT_SYMENT:
- case DT_RELENT:
- 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:
- INFO("%lld (bytes)\n", dyn->d_un.d_val);
- break;
-
- case DT_VERDEFNUM:
- case DT_VERNEEDNUM:
- case DT_RELACOUNT:
- case DT_RELCOUNT:
- INFO("%lld\n", dyn->d_un.d_val);
- break;
-
- case DT_PLTREL: /* Specifies whether PLTREL (same as JMPREL) has REL or RELA entries */
- INFO("%s (%d)\n", ebl_dynamic_tag_name (oldebl, dyn->d_un.d_val, NULL, 0), dyn->d_un.d_val);
- break;
-
- default:
- INFO("%#0*llx\n",
- gelf_getclass (elf) == ELFCLASS32 ? 10 : 18,
- dyn->d_un.d_val);
- break;
- }
-
- FAILIF_LIBELF(0 == gelf_update_dyn(data, cnt, dyn),
- gelf_update_dyn);
- } /* for (...) */
-
-#ifdef DEBUG
- if (1) {
- int i;
- for (i = 0; i < DT_NUM; i++)
- ASSERT((ssize_t)dyn_size_entries[i] <= 0);
- }
-#endif
-
- FREE(dyn_size_entries);
-} /* adjust_dynamic_segment_offsets() */
-
-static bool section_belongs_to_header(GElf_Shdr *shdr, GElf_Phdr *phdr)
-{
- if (shdr->sh_size) {
- /* Compare allocated sections by VMA, unallocated
- sections by file offset. */
- if(shdr->sh_flags & SHF_ALLOC) {
- if(shdr->sh_addr >= phdr->p_vaddr
- && (shdr->sh_addr + shdr->sh_size
- <= phdr->p_vaddr + phdr->p_memsz))
- {
- return true;
- }
- }
- else {
- if (shdr->sh_offset >= phdr->p_offset
- && (shdr->sh_offset + shdr->sh_size
- <= phdr->p_offset + phdr->p_filesz))
- {
- return true;
- }
- }
- }
-
- return false;
-}
-
-static Elf64_Off section_to_header_mapping(Elf *elf,
- int phdr_idx,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- Elf64_Off *file_end,
- Elf64_Off *mem_end)
-{
- Elf64_Off start;
- GElf_Phdr phdr_mem;
- GElf_Phdr *phdr = gelf_getphdr (elf, phdr_idx, &phdr_mem);
- FAILIF_LIBELF(NULL == phdr, gelf_getphdr);
- size_t inner;
-
- FAILIF(phdr->p_type == PT_GNU_RELRO,
- "Can't handle segments of type PT_GNU_RELRO!\n");
-
- /* Iterate over the sections. */
- start = (Elf64_Off)-1;
- *file_end = *mem_end = 0;
- INFO("\n\t\t");
- for (inner = 1; inner < num_shdr_info; ++inner)
- {
- if (shdr_info[inner].idx > 0) {
- /* Check to see the section is in the segment. We use the old
- header because that header contains the old offset and length
- information about a section.
- */
- if (section_belongs_to_header(&shdr_info[inner].old_shdr, phdr))
- {
- INFO("%-17s", shdr_info[inner].name);
-#define SECT_MEM_END(s) ((s).sh_addr + (s).sh_size)
- if ((shdr_info[inner].shdr.sh_flags & SHF_ALLOC)) {
- if (SECT_MEM_END(shdr_info[inner].shdr) > *mem_end) {
- INFO("(mem_end 0x%llx --> 0x%llx) ", *mem_end, SECT_MEM_END(shdr_info[inner].shdr));
- *mem_end = SECT_MEM_END(shdr_info[inner].shdr);
- }
-#undef SECT_MEM_END
-#define SECT_FILE_END(s) ((s).sh_offset + (s).sh_size)
- if (shdr_info[inner].shdr.sh_type != SHT_NOBITS) {
- if (SECT_FILE_END(shdr_info[inner].shdr) > *file_end) {
- INFO("(file_end 0x%llx --> 0x%llx) ", *file_end, SECT_FILE_END(shdr_info[inner].shdr));
- *file_end = SECT_FILE_END(shdr_info[inner].shdr);
- }
- }
-#undef SECT_FILE_END
- if (shdr_info[inner].shdr.sh_offset < start) {
- start = shdr_info[inner].shdr.sh_offset;
- }
- } /* if section takes space */
- INFO("\n\t\t");
- }
- else
- INFO("(!) %-17s does not match\n\t\t", shdr_info[inner].name);
- }
- else
- INFO("(!) %-17s is not considered, it is being removed\n\t\t", shdr_info[inner].name);
- }
-
- /* Finish the line. */
- INFO("start: %lld\n", start);
- INFO("\t\tends: %lld file, %lld mem\n", *file_end, *mem_end);
-
- return start;
-}
-
-static void
-update_symbol_values(Elf *elf, GElf_Ehdr *ehdr,
- Elf *newelf __attribute__((unused)),
- shdr_info_t *shdr_info,
- int num_shdr_info,
- int shady,
- int dynamic_idx)
-{
- /* Scan the sections, looking for the symbol table. */
- size_t i;
- for (i = 1; i < num_shdr_info; i++) {
- if (shdr_info[i].idx > 0 &&
- (shdr_info[i].shdr.sh_type == SHT_SYMTAB ||
- shdr_info[i].shdr.sh_type == SHT_DYNSYM))
- {
- size_t inner;
- size_t elsize = gelf_fsize (elf, ELF_T_SYM, 1, ehdr->e_version);
- Elf_Data *symdata = shdr_info[i].newdata;
- /* shdr_info[i].old_shdr.sh_link is the index of the strings table
- in the old ELF file. This index still points to the same section
- in the shdr_info[] array. The idx field of that entry is that
- section's new index. That index must, therefore, be equal to
- the new value of sh_link. */
- ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].idx ==
- shdr_info[i].shdr.sh_link);
- ASSERT(shdr_info[shdr_info[i].old_shdr.sh_link].data);
-
- INFO("\tupdating symbol values for section [%s]...\n",
- shdr_info[i].name);
-
-#if 1 /* DEBUG */
- {
- Elf_Scn *symstrscn = elf_getscn(newelf, shdr_info[i].shdr.sh_link);
- ASSERT(symstrscn);
- Elf_Data *symstrdata = elf_getdata(symstrscn, NULL);
- ASSERT(symstrdata);
- INFO("%d nonprintable\n",
- dump_hex_buffer(stdout, symstrdata->d_buf, symstrdata->d_size, 0));
- }
-#endif
-
- INFO("\tnumber of symbols to update: %d (%d bytes)\n",
- symdata->d_size / elsize, symdata->d_size);
- for (inner = 0; inner < symdata->d_size / elsize; ++inner)
- {
- GElf_Sym sym_mem;
- GElf_Sym *sym;
- size_t shnum;
- FAILIF_LIBELF(elf_getshnum (elf, &shnum) < 0, elf_getshnum);
-
- sym = gelf_getsymshndx (symdata, NULL,
- inner, &sym_mem, NULL);
- FAILIF_LIBELF(sym == NULL, gelf_getsymshndx);
-
-#if 0 /* DEBUG */
- if (shdr_info[i].shdr.sh_type == SHT_SYMTAB) {
- PRINT("%8d: name %d info %02x other %02x shndx %d size %lld value %lld\n",
- inner,
- sym->st_info,
- sym->st_name,
- sym->st_other,
- sym->st_shndx,
- sym->st_size,
- sym->st_value);
- }
-#endif
-
- size_t scnidx = sym->st_shndx;
- FAILIF(scnidx == SHN_XINDEX,
- "Can't handle SHN_XINDEX!\n");
-
- char *symname = NULL;
- {
-#if ELF_STRPTR_IS_BROKEN
- Elf_Scn *symstrscn = elf_getscn(newelf, shdr_info[i].shdr.sh_link);
- ASSERT(symstrscn);
- Elf_Data *symstrdata = elf_getdata(symstrscn, NULL);
- ASSERT(symstrdata);
- symname = symstrdata->d_buf + sym->st_name;
-#else
- symname = elf_strptr(newelf,
- shdr_info[i].shdr.sh_link,
- sym->st_name);
-#endif
- }
-
- extern int verbose_flag;
- if (unlikely(verbose_flag))
- {
- int c, max = 40;
- INFO("%-8d [", inner);
- for (c=0; c<max-1; c++) {
- if (symname[c]) {
- INFO("%c", symname[c]);
- }
- else break;
- }
- if (c < max-1) {
- while (c++ < max) INFO(" ");
- }
- else INFO("<");
- INFO("]");
- } /* if (unlikely(verbose_flag)) */
-
- /* Notice that shdr_info[] is an array whose indices correspond
- to the section indices in the original ELF file. Of those
- sections, some have been discarded, and one is moved to the
- end of the file--this is section .shstrtab. Of course, no
- symbol refers to this section, so it is safe for us to
- address sections by their original indices in the
- shdr_info[] array directly.
- */
-
- /* Note that we do not skip over the STT_SECTION symbols. Since
- they contain the addresses of sections, we update their
- values as well.
- */
- if (scnidx == SHN_UNDEF) {
- INFO(" undefined\n");
- continue;
- }
- if (scnidx >= shnum ||
- (scnidx >= SHN_LORESERVE &&
- scnidx <= SHN_HIRESERVE))
- {
- INFO(" special (scn %d, value 0x%llx, size %lld)\n",
- scnidx,
- sym->st_value,
- sym->st_size);
-
- /* We shouldn't be messing with these symbols, but they are
- often absolute symbols that encode the starting address
- or the ending address of some section. As a heuristic,
- we will check to see if the value of the symbol matches
- the start or the end of any section, and if so, we will
- update it, but only if --shady is enabled.
- */
-
- if (shady && sym->st_value) {
- size_t scnidx;
- /* Is it the special symbol _DYNAMIC? */
- if (!strcmp(symname, "_DYNAMIC")) {
- /* The _DYNAMIC symbol points to the DYNAMIC
- segment. It is used by linker to bootstrap
- itself. */
- ASSERT(dynamic_idx >= 0);
- PRINT("*** SHADY *** symbol %s: "
- "new st_value = %lld (was %lld), "
- "st_size = %lld (was %lld)\n",
- symname,
- shdr_info[dynamic_idx].shdr.sh_addr,
- sym->st_value,
- shdr_info[dynamic_idx].shdr.sh_size,
- sym->st_size);
- sym->st_value =
- shdr_info[dynamic_idx].shdr.sh_addr;
- sym->st_size =
- shdr_info[dynamic_idx].shdr.sh_size;
- /* NOTE: We don't update st_shndx, because this is a special
- symbol. I am not sure if it's necessary though.
- */
- FAILIF_LIBELF(gelf_update_symshndx(symdata,
- NULL,
- inner,
- sym,
- 0) == 0,
- gelf_update_symshndx);
- }
- else {
- for (scnidx = 1; scnidx < num_shdr_info; scnidx++) {
- if (sym->st_value ==
- shdr_info[scnidx].old_shdr.sh_addr) {
- if (shdr_info[scnidx].shdr.sh_addr !=
- sym->st_value) {
- PRINT("*** SHADY *** symbol %s matches old "
- "start %lld of section %s, updating "
- "to %lld.\n",
- symname,
- shdr_info[scnidx].old_shdr.sh_addr,
- shdr_info[scnidx].name,
- shdr_info[scnidx].shdr.sh_addr);
- sym->st_value = shdr_info[scnidx].shdr.sh_addr;
- }
- break;
- }
- else {
- Elf64_Addr oldaddr =
- shdr_info[scnidx].old_shdr.sh_addr +
- shdr_info[scnidx].old_shdr.sh_size;
- if (sym->st_value == oldaddr) {
- Elf64_Addr newaddr =
- shdr_info[scnidx].shdr.sh_addr +
- shdr_info[scnidx].shdr.sh_size;
- if (newaddr != sym->st_value) {
- PRINT("*** SHADY *** symbol %s matches old "
- "end %lld of section %s, updating "
- "to %lld.\n",
- symname,
- oldaddr,
- shdr_info[scnidx].name,
- newaddr);
- sym->st_value = newaddr;
- }
- break;
- }
- }
- } /* for each section... */
- /* NOTE: We don't update st_shndx, because this is a special
- symbol. I am not sure if it's necessary though.
- */
- if (scnidx < num_shdr_info) {
- FAILIF_LIBELF(gelf_update_symshndx(symdata,
- NULL,
- inner,
- sym,
- 0) == 0,
- gelf_update_symshndx);
- }
- } /* if symbol is _DYNAMIC else */
- }
-
- continue;
- } /* handle special-section symbols */
-
- /* The symbol must refer to a section which is not being
- removed. */
- if(shdr_info[scnidx].idx == 0)
- {
- FAILIF(GELF_ST_TYPE (sym->st_info) != STT_SECTION,
- "Non-STT_SECTION symbol [%s] refers to section [%s],"
- " which is being removed.\n",
- symname,
- shdr_info[scnidx].name);
- INFO("STT_SECTION symbol [%s] refers to section [%s], "
- "which is being removed. Skipping...\n",
- symname,
- shdr_info[scnidx].name);
- continue;
- }
-
- INFO(" %8d %-17s ",
- sym->st_shndx,
- shdr_info[sym->st_shndx].name);
-
- /* Has the section's offset (hence its virtual address,
- because we set that to the same value as the offset) changed?
- If so, calculate the delta and update the symbol entry.
- */
- Elf64_Sxword delta;
- delta =
- shdr_info[scnidx].shdr.sh_offset -
- shdr_info[scnidx].old_shdr.sh_offset;
-
- Elf64_Sxword vaddr_delta;
- vaddr_delta =
- shdr_info[scnidx].shdr.sh_addr -
- shdr_info[scnidx].old_shdr.sh_addr;
-
- if (delta || shdr_info[scnidx].idx != scnidx) {
-
- if (sym->st_value)
- INFO("0x%llx -> 0x%llx (delta %lld)",
- sym->st_value,
- sym->st_value + delta,
- delta);
- else {
- INFO("(value is zero, not adjusting it)",
- sym->st_value,
- sym->st_value + delta,
- delta);
- /* This might be a bit too paranoid, but symbols with values of
- zero for which we are not adjusting the value must be in the
- static-symbol section and refer to a section which is
- not loaded at run time. If this assertion ever fails, figure
- out why and also figure out whether the zero value should have
- been adjusted, after all.
- */
- ASSERT(!(shdr_info[sym->st_shndx].shdr.sh_flags & SHF_ALLOC));
- ASSERT(shdr_info[i].shdr.sh_type == SHT_SYMTAB);
- }
-
- /* The section index of the symbol must coincide with
- the shdr_info[] index of the section that the
- symbol refers to. Since that section may have been
- moved, its new setion index, which is stored in
- the idx field, may have changed. However the index
- of the original section must match.
- */
- ASSERT(scnidx == elf_ndxscn(shdr_info[scnidx].scn));
-
- if(unlikely(verbose_flag)) {
- if (shdr_info[scnidx].idx != scnidx) {
- INFO(" (updating sym->st_shndx = %lld --> %lld)\n",
- sym->st_shndx,
- shdr_info[scnidx].idx);
- }
- else INFO("(sym->st_shndx remains %lld)\n", sym->st_shndx);
- }
-
- sym->st_shndx = shdr_info[scnidx].idx;
- if (sym->st_value)
- sym->st_value += delta;
- FAILIF_LIBELF(gelf_update_symshndx(symdata,
- NULL,
- inner,
- sym,
- 0) == 0,
- gelf_update_symshndx);
- }
- else {
- INFO(" (no change)\n");
- }
- } /* for each symbol */
- } /* if it's a symbol table... */
- } /* for each section... */
-}
-
-static void adjust_section_offset(Elf *newelf,
- shdr_info_t *shdr_info,
- Elf64_Sxword delta)
-{
- Elf_Scn *scn = elf_getscn (newelf, shdr_info->idx);
- ASSERT(scn != NULL);
-
- ASSERT(((Elf64_Sxword)shdr_info->shdr.sh_offset) + delta >= 0);
- shdr_info->shdr.sh_offset += delta;
- ASSERT(shdr_info->shdr.sh_addralign);
-#ifdef DEBUG
- /* The assumption is that the delta is calculated so that it will preserve
- the alignment. Of course, we don't trust ourselves so we verify.
-
- NOTE: The assertion below need not hold about NOBITS sections (such as
- the .bss section), for which the offset in the file and the address at
- which the section is to be loaded may differ.
- */
- if (shdr_info->shdr.sh_type != SHT_NOBITS)
- {
- Elf64_Off new_offset = shdr_info->shdr.sh_offset;
- new_offset += shdr_info->shdr.sh_addralign - 1;
- new_offset &= ~((GElf_Off)(shdr_info->shdr.sh_addralign - 1));
-
- ASSERT(shdr_info->shdr.sh_offset == new_offset);
- }
-#endif
- INFO("\t\t\t\tsection offset %lld -> %lld%s\n",
- shdr_info->old_shdr.sh_offset,
- shdr_info->shdr.sh_offset,
- (shdr_info->old_shdr.sh_offset ==
- shdr_info->shdr.sh_offset ? " (SAME)" : ""));
-
- /* If there is a delta for an ALLOC section, then the sections address must match the sections's offset in
- the file, if that section is not marked SHT_NOBITS. For SHT_NOBITS sections, the two may differ.
- Note that we compare against the old_shdr.sh_offset because we just modified shdr.sh_offset!
- */
-
- ASSERT(!delta ||
- !(shdr_info->shdr.sh_flags & SHF_ALLOC) ||
- shdr_info->shdr.sh_type == SHT_NOBITS ||
- shdr_info->shdr.sh_addr == shdr_info->old_shdr.sh_offset);
-
- if ((shdr_info->shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC)
- {
- ASSERT(shdr_info->shdr.sh_addr);
- shdr_info->shdr.sh_addr += delta;
- INFO("\t\t\t\tsection address %lld -> %lld%s\n",
- shdr_info->old_shdr.sh_addr,
- shdr_info->shdr.sh_addr,
- (shdr_info->old_shdr.sh_addr ==
- shdr_info->shdr.sh_addr ? " (SAME)" : ""));
- }
-
- /* Set the section header in the new file. There cannot be any
- overflows. */
- INFO("\t\t\t\tupdating section header (size %lld)\n",
- shdr_info->shdr.sh_size);
- FAILIF(!gelf_update_shdr (scn, &shdr_info->shdr),
- "Could not update section header for section %s!\n",
- shdr_info->name);
-}
-
-#ifdef MOVE_SECTIONS_IN_RANGES
-static int get_end_of_range(shdr_info_t *shdr_info,
- int num_shdr_info,
- int start,
- Elf64_Xword *alignment,
- Elf32_Word *real_align)
-{
- int end = start;
- ASSERT(start < num_shdr_info);
-
- /* Note that in the loop below we do not check to see if a section is
- being thrown away. If a section in the middle of a range is thrown
- away, that will cause the section to be removed, but it will not cause
- the relative offsets of the sections in the block to be modified.
- */
-
- *alignment = real_align[start];
- while (end < num_shdr_info &&
- ((shdr_info[end].shdr.sh_flags & SHF_ALLOC) == SHF_ALLOC) &&
- ((shdr_info[end].shdr.sh_type == SHT_PROGBITS) ||
- (shdr_info[end].shdr.sh_type == SHT_INIT_ARRAY) ||
- (shdr_info[end].shdr.sh_type == SHT_FINI_ARRAY) ||
- (shdr_info[end].shdr.sh_type == SHT_PREINIT_ARRAY) ||
- /* (shdr_info[end].shdr.sh_type == SHT_NOBITS) || */
-#ifdef ARM_SPECIFIC_HACKS
- /* SHF_ALLOC sections with with names starting with ".ARM." are
- part of the ARM EABI extensions to ELF.
- */
- !strncmp(shdr_info[end].name, ".ARM.", 5) ||
-#endif
- (shdr_info[end].shdr.sh_type == SHT_DYNAMIC)))
- {
- if (real_align[end] > *alignment) {
- *alignment = real_align[end];
- }
- end++;
- }
-
- return end == start ? end + 1 : end;
-}
-#endif/*MOVE_SECTIONS_IN_RANGES*/
-
-static GElf_Off update_last_offset(shdr_info_t *shdr_info,
- range_list_t *section_ranges,
- GElf_Off offset)
-{
- GElf_Off filesz = 0;
- if (shdr_info->shdr.sh_type != SHT_NOBITS) {
- /* This function is used as an assertion: if the range we are
- adding conflicts with another range already in the list,
- then add_unique_range() will call FAILIF().
- */
- add_unique_range_nosort(section_ranges,
- shdr_info->shdr.sh_offset,
- shdr_info->shdr.sh_size,
- shdr_info,
- handle_range_error,
- NULL);
-
- filesz = shdr_info->shdr.sh_size;
- }
-
- /* Remember the last section written so far. */
- if (offset < shdr_info->shdr.sh_offset + filesz) {
- offset = shdr_info->shdr.sh_offset + filesz;
- INFO("\t\t\t\tupdated lastoffset to %lld\n", offset);
- }
-
- return offset;
-}
-
-static GElf_Off move_sections(Elf *newelf,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- int start,
- int end,
- GElf_Off offset,
- Elf64_Xword alignment,
- range_list_t *section_ranges,
- bool adjust_alloc_section_offsets)
-{
- /* The alignment parameter is expected to contain the largest alignment of
- all sections in the block. Thus, when we iterate over all sections in
- the block and apply the same offset to them, we are guaranteed to
- preserve (a) the relative offsets between the sections in the block and
- (b) the alignment requirements of each individual section.
- */
-
- ASSERT(start < num_shdr_info);
- ASSERT(end <= num_shdr_info);
-
- Elf64_Sxword delta = offset - shdr_info[start].shdr.sh_offset;
- delta += (alignment - 1);
- delta &= ~(alignment - 1);
- while (start < end) {
- if (shdr_info[start].idx > 0) {
- if (adjust_alloc_section_offsets || (shdr_info[start].shdr.sh_flags & SHF_ALLOC) != SHF_ALLOC) {
- INFO("\t\t\t%03d:\tAdjusting offset of section %s "
- "(index %d) from 0x%llx (%lld) to 0x%llx (%lld) (DELTA %lld)...\n",
- start,
- (shdr_info[start].name ?: "(no name)"),
- shdr_info[start].idx,
- shdr_info[start].old_shdr.sh_offset, shdr_info[start].old_shdr.sh_offset,
- offset, offset,
- delta);
-
- /* Compute the new offset of the section. */
- adjust_section_offset(newelf, shdr_info + start, delta);
- }
- else {
- INFO("\t\t\t%03d: NOT adjusting offset of section %s (index %d)"
- ": (not moving SHF_ALLOC sections)...\n",
- start,
- (shdr_info[start].name ?: "(no name)"),
- shdr_info[start].idx);
- }
- offset = update_last_offset(shdr_info + start,
- section_ranges,
- offset);
- } /* if (shdr_info[start].idx > 0) */
- else {
- INFO("\t\t\t%03d: NOT adjusting offset of section %s (index %d)"
- " (ignored)...\n",
- start,
- (shdr_info[start].name ?: "(no name)"),
- shdr_info[start].idx);
- }
- start++;
- }
-
- sort_ranges(section_ranges);
- return offset;
-}
-
-/* Compute the alignments of sections with consideration of segment
- alignments. Returns an array of Elf32_Word containing the alignment
- of sections. Callee is responsible to deallocate the array after use. */
-Elf32_Word *
-get_section_real_align (GElf_Ehdr *ehdr, GElf_Phdr *phdr_info,
- struct shdr_info_t *shdr_info, int shdr_info_len)
-{
- size_t max_align_array_size;
- Elf32_Word *max_align;
- size_t first_section;
- bool propagate_p;
- int si, pi;
-
- max_align_array_size = sizeof(Elf32_Word) * shdr_info_len;
- max_align = (Elf32_Word*) malloc (max_align_array_size);
- FAILIF(!max_align, "malloc(%zu) failed.\n", max_align_array_size);
-
- /* Initialize alignment array. */
- max_align[0] = 0;
- for (si = 1; si < shdr_info_len; si++)
- max_align[si] = shdr_info[si].shdr.sh_addralign;
-
- /* Determine which sections need to be aligned with the alignment of
- containing segments. Becasue the first section in a segment may
- be deleted, we need to look at all sections and compare their offsets.
- */
- for (pi = 0; pi < ehdr->e_phnum; ++pi) {
- /* Skip null segment. */
- if (phdr_info[pi].p_type == PT_NULL)
- continue;
-
- /* Look for the first non-deleted section of a segment in output.
- We assume asections are sorted by offsets. Also check to see if
- a segment starts with a section. We only want to propagate
- alignment if the segment starts with a section. */
- propagate_p = false;
- first_section = 0;
- for (si = 1; si < shdr_info_len && first_section == 0; si++) {
- if (shdr_info[si].old_shdr.sh_offset == phdr_info[pi].p_offset)
- propagate_p = true;
-
- if (shdr_info[si].idx > 0
- && section_belongs_to_header(&shdr_info[si].old_shdr,
- &phdr_info[pi]))
- first_section = si;
- }
-
- if (!propagate_p || first_section == 0)
- continue;
-
- /* Adjust alignment of first section. Note that a section can appear
- in multiple segments. We only need the extra alignment if the
- section's alignment is smaller than that of the segment. */
- if (first_section != 0 &&
- max_align[first_section] < phdr_info[pi].p_align) {
- max_align[first_section] = phdr_info[pi].p_align;
- }
- }
-
- return max_align;
-}
-
-static range_list_t *
-update_section_offsets(Elf *elf,
- Elf *newelf,
- GElf_Phdr *phdr_info,
- shdr_info_t *shdr_info,
- int num_shdr_info,
- range_list_t *section_ranges,
- bool adjust_alloc_section_offsets)
-{
- Elf32_Word *real_align;
-
- ASSERT(section_ranges);
- INFO("Updating section addresses and offsets...\n");
- /* The initial value of lastoffset is set to the size of the ELF header
- plus the size of the program-header table. libelf seems to always
- place the program-header table for a new file immediately after the
- ELF header itself... or I could not find any other way to change it
- otherwise.
- */
- GElf_Ehdr ehdr_mem, *ehdr;
- ehdr = gelf_getehdr (elf, &ehdr_mem);
- FAILIF_LIBELF(NULL == ehdr, gelf_getehdr);
- const size_t ehdr_size = gelf_fsize (elf, ELF_T_EHDR, 1, EV_CURRENT);
- FAILIF(ehdr->e_phoff != ehdr_size,
- "Expecting the program-header table to follow the ELF header"
- " immediately!\n");
-
- GElf_Off lastoffset = 0;
- lastoffset += ehdr_size;
- lastoffset += (ehdr->e_phnum + 1) * ehdr->e_phentsize;
- INFO("Section offsets will start from %lld.\n", lastoffset);
-
- int start = 1, end = 1;
- ASSERT(num_shdr_info > 0);
- real_align = get_section_real_align (ehdr, phdr_info, shdr_info,
- num_shdr_info);
- while (end < num_shdr_info) {
- Elf64_Xword alignment;
- /* end is the index one past the last section of the block. */
-#ifdef MOVE_SECTIONS_IN_RANGES
- end = get_end_of_range(shdr_info, num_shdr_info,
- start, &alignment, real_align);
-#else
- end = start + 1;
- alignment = real_align[start];
-#endif
-
- INFO("\tAdjusting sections [%d - %d) as a group (start offset %lld, alignment %lld)\n",
- start, end, lastoffset, alignment);
- lastoffset = move_sections(newelf,
- shdr_info,
- num_shdr_info,
- start, end,
- lastoffset,
- alignment,
- section_ranges,
- adjust_alloc_section_offsets);
-
- start = end;
- }
-
- ASSERT(lastoffset == get_last_address(section_ranges));
- free (real_align);
- return section_ranges;
-}
-
-void handle_range_error(range_error_t err, range_t *left, range_t *right)
-{
- shdr_info_t *info_l = (shdr_info_t *)left->user;
- shdr_info_t *info_r = (shdr_info_t *)right->user;
- ASSERT(info_l);
- ASSERT(info_r);
-
- switch (err) {
- case ERROR_CONTAINS:
- ERROR("ERROR: section [%s] (%lld, %lld bytes) contains "
- "section [%s] (%lld, %lld bytes)\n",
- info_l->name,
- left->start, left->length,
- info_r->name,
- right->start, right->length);
- break;
- case ERROR_OVERLAPS:
- ERROR("ERROR: Section [%s] (%lld, %lld bytes) intersects "
- "section [%s] (%lld, %lld bytes)\n",
- info_l->name,
- left->start, left->length,
- info_r->name,
- right->start, right->length);
- break;
- default:
- ASSERT(!"Unknown range error code!");
- }
-
- FAILIF(1, "Range error.\n");
-}
-
-#ifdef DEBUG
-
-/* Functions to ELF file is still sane after adjustment. */
-
-static bool
-sections_overlap_p (GElf_Shdr *s1, GElf_Shdr *s2)
-{
- GElf_Addr a1, a2;
- GElf_Off o1, o2;
-
- if ((s1->sh_flags & s2->sh_flags & SHF_ALLOC) != 0) {
- a1 = (s1->sh_addr > s2->sh_addr)? s1->sh_addr : s2->sh_addr;
- a2 = ((s1->sh_addr + s1->sh_size < s2->sh_addr + s2->sh_size)?
- (s1->sh_addr + s1->sh_size) : (s2->sh_addr + s2->sh_size));
- if (a1 < a2)
- return true;
- }
-
- if (s1->sh_type != SHT_NOBITS && s2->sh_type != SHT_NOBITS) {
- o1 = (s1->sh_offset > s2->sh_offset)? s1->sh_offset : s2->sh_offset;
- o2 = ((s1->sh_offset + s1->sh_size < s2->sh_offset + s2->sh_size)?
- (s1->sh_offset + s1->sh_size) : (s2->sh_offset + s2->sh_size));
- if (o1 < o2)
- return true;
- }
-
- return false;
-}
-
-/* Return size of the overlapping portion of section S and segment P
- in memory. */
-
-static GElf_Word
-mem_overlap_size (GElf_Shdr *s, GElf_Phdr *p)
-{
- GElf_Addr a1, a2;
-
- if (s->sh_flags & SHF_ALLOC) {
- a1 = p->p_vaddr > s->sh_addr ? p->p_vaddr : s->sh_addr;
- a2 = ((p->p_vaddr + p->p_memsz < s->sh_addr + s->sh_size) ?
- (p->p_vaddr + p->p_memsz) : (s->sh_addr + s->sh_size));
- if (a1 < a2) {
- return a2 - a1;
- }
- }
- return 0;
-}
-
-/* Return size of the overlapping portion of section S and segment P
- in file. */
-
-static GElf_Word
-file_overlap_size (GElf_Shdr *s, GElf_Phdr *p)
-{
- GElf_Off o1, o2;
-
- if (s->sh_type != SHT_NOBITS) {
- o1 = p->p_offset > s->sh_offset ? p->p_offset : s->sh_offset;
- o2 = ((p->p_offset + p->p_filesz < s->sh_offset + s->sh_size) ?
- (p->p_offset + p->p_filesz) : (s->sh_offset + s->sh_size));
- if (o1 < o2) {
- return o2 - o1;
- }
- }
- return 0;
-}
-
-/* Verify the ELF file is sane. */
-static void
-verify_elf(GElf_Ehdr *ehdr, struct shdr_info_t *shdr_info, int shdr_info_len,
- GElf_Phdr *phdr_info)
-{
- int si, sj, pi;
- GElf_Word addralign;
- GElf_Word m_size, f_size;
-
- /* Check all sections */
- for (si = 1; si < shdr_info_len; si++) {
- if (shdr_info[si].idx <= 0)
- continue;
-
- /* Check alignment */
- addralign = shdr_info[si].shdr.sh_addralign;
- if (addralign != 0) {
- if (shdr_info[si].shdr.sh_flags & SHF_ALLOC) {
- FAILIF ((addralign - 1) & shdr_info[si].shdr.sh_addr,
- "Load address %llx of section %s is not "
- "aligned to multiples of %u\n",
- (long long unsigned) shdr_info[si].shdr.sh_addr,
- shdr_info[si].name,
- addralign);
- }
-
- if (shdr_info[si].shdr.sh_type != SHT_NOBITS) {
- FAILIF ((addralign - 1) & shdr_info[si].shdr.sh_offset,
- "Offset %lx of section %s is not "
- "aligned to multiples of %u\n",
- shdr_info[si].shdr.sh_offset,
- shdr_info[si].name,
- addralign);
- }
- }
-
- /* Verify that sections do not overlap. */
- for (sj = si + 1; sj < shdr_info_len; sj++) {
- if (shdr_info[sj].idx <= 0)
- continue;
-
- FAILIF (sections_overlap_p (&shdr_info[si].shdr,
- &shdr_info[sj].shdr),
- "sections %s and %s overlap.\n", shdr_info[si].name,
- shdr_info[sj].name);
- }
-
- /* Verify that section is properly contained in segments. */
- for (pi = 0; pi < ehdr->e_phnum; pi++) {
- if (phdr_info[pi].p_type == PT_NULL)
- continue;
-
- f_size = file_overlap_size (&shdr_info[si].shdr, &phdr_info[pi]);
- m_size = mem_overlap_size (&shdr_info[si].shdr, &phdr_info[pi]);
-
- if (f_size) {
- FAILIF (shdr_info[si].shdr.sh_size > phdr_info[pi].p_filesz,
- "Section %s is larger than segment %d\n",
- shdr_info[si].name, pi);
- FAILIF (f_size != shdr_info[si].shdr.sh_size,
- "Section %s partially overlaps segment %d in file.\n",
- shdr_info[si].name, pi);
- }
-
- if (m_size) {
- FAILIF (shdr_info[si].shdr.sh_size > phdr_info[pi].p_memsz,
- "Section %s is larger than segment %d\n",
- shdr_info[si].name, pi);
- FAILIF (m_size != shdr_info[si].shdr.sh_size,
- "Section %s partially overlaps segment %d in memory.\n",
- shdr_info[si].name, pi);
- }
-
- }
- }
-}
-#endif /* DEBUG */
diff --git a/elfcopy.h b/elfcopy.h
deleted file mode 100644
index df448a5..0000000
--- a/elfcopy.h
+++ /dev/null
@@ -1,94 +0,0 @@
-#ifndef ELFCOPY_H
-#define ELFCOPY_H
-
-#include <libelf.h>
-#include <libebl.h>
-#include <elf.h>
-#include <gelf.h>
-
-typedef struct shdr_info_t {
- /* data from original file: */
- Elf_Scn *scn; /* original section */
- /* Original-section header. */
- GElf_Shdr old_shdr;
- /* Starts out as the original header, but we modify this variable when we
- compose the new section information. */
- GElf_Shdr shdr;
- /* This oddly-named flag causes adjust_elf() to look at the size of the
- relocation sections before the modification, as opposed to the new
- size, in order to determine the number of relocation entries. */
- bool use_old_shdr_for_relocation_calculations;
- const char *name; /* name of the original section */
- /* If we do not want to modify a section's data, we set this field to NULL.
- This will cause clone_elf() to extract the original section's data and
- copy it over to the new section. If, on the other hand, we do want to
- change the data, we call elf_newdata() by ourselves and set *data to
- the return value.
- */
- Elf_Data *data;
- Elf_Data *newdata;
-
- /* data for new file */
-
- /* Index in new file. Before we assign numbers to the sections in the
- new file, the idx field has the following meaning:
- 0 -- will strip
- 1 -- present but not yet investigated
- 2 -- handled (stripped or decided not to stip).
- */
- Elf32_Word idx;
- Elf_Scn *newscn; /* new section handle */
- struct Ebl_Strent *se; /* contribution to shstr section */
- /* The following three variables are for symbol-table-sections (SHT_DYNSYM
- and SHT_SYMTAB).
-
- newsymidx: contains a mapping between the indices of old symbols and new
- symbols. If a symbol table has changed, then newsymidx !=
- NULL; otherwise, it is NULL. Thus newsymidx can be used also
- as a flag.
-
- dynsymst: handle to the new symbol-strings section.
- */
- Elf32_Word *newsymidx;
- struct Ebl_Strtab *dynsymst;
- /* The following variable is used by SHT_DYNSYM, SHT_SYMTAB and SHT_DYNAMIC
- sections only. For the symbol tables, this is a parallel array to the
- symbol table that stores the symbol name's index into the symbol-strings
- table.
-
- For the dynamic section, this is an array parallel to the array of
- structures that the dynamic section is; for each structure that
- represents a string field, the element at the same index into symse
- contains the offset of that string into the new dynamic-symbol table.
- */
- struct Ebl_Strent **symse;
-} shdr_info_t;
-
-/*
-Symbol_filter:
- On input: symbol_filter[i] indicates whether to keep a symbol (1) or to
- remove it from the symbol table.
- On output: symbol_filter[i] indicates whether a symbol was removed (0) or
- kept (1) in the symbol table.
-*/
-
-void adjust_elf(Elf *elf, const char *elf_name,
- Elf *newelf, const char *newelf_name,
- Ebl *ebl,
- GElf_Ehdr *ehdr, /* store ELF header of original library */
- bool *sym_filter, int num_symbols,
- struct shdr_info_t *shdr_info, int shdr_info_len,
- GElf_Phdr *phdr_info,
- size_t highest_scn_num,
- size_t shnum,
- size_t shstrndx,
- struct Ebl_Strtab *shst,
- bool sections_dropped_or_rearranged,
- int dynamic_idx, /* index in shdr_info[] of .dynamic section */
- int dynsym_idx, /* index in shdr_info[] of dynamic symbol table */
- int shady,
- Elf_Data **shstrtab_data,
- bool adjust_section_offsets,
- bool rebuild_shstrtab);
-
-#endif/*ELFCOPY_H*/
diff --git a/fixdwarf.c b/fixdwarf.c
deleted file mode 100644
index 5707d5e..0000000
--- a/fixdwarf.c
+++ /dev/null
@@ -1,577 +0,0 @@
-#include <fixdwarf.h>
-#include <common.h>
-#include <debug.h>
-#include <hash.h>
-
-#include <libelf.h>
-#include <libebl.h>
-#include <libebl_arm.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-/* When this macro is set to a nonzero value, we maintain a BST where we store each address once
- we update the value at that address, and check to make sure that the address has not been
- visited before we udpate it. This way we make sure that we do not do multiple updates at any
- any given address. The feature is disabled by default because it is very expensive. It should
- be enabled as a first step in debugging problems with the DWARF patches that this code makes.
-*/
-
-#define PARANOIA (0)
-
-#define _str(name) #name
-#define _id(a,b) a ## b
-
-#if PARANOIA
-#define COLLECT_BACKTRACES (0)
-
-#if COLLECT_BACKTRACES
-#include <execinfo.h>
-#endif
-#endif/*PARANOIA*/
-
-#include <dwarf.h>
-
-int load_debug_section (enum dwarf_section_display_enum debug, void *file);
-void free_debug_section (enum dwarf_section_display_enum debug);
-
-static shdr_info_t *s_shdr_info;
-static int s_shdr_info_len;
-static int dwarf_to_shdr[max];
-static shdr_info_t *s_cached_find_section_result = NULL;
-static int s_num_total_patches = 0;
-static int s_num_failed_patches = 0;
-
-static void init_value_free_lists();
-
-#if PARANOIA
-typedef struct value_struct {
- unsigned long key;
- struct value_struct *left;
- struct value_struct *right;
-#if COLLECT_BACKTRACES
-#define BACKTRACE_DEPTH (10)
- void *backtrace[BACKTRACE_DEPTH];
- int backtrace_depth;
-#endif/*COLLECT_BACKTRACES*/
-} value_t;
-
-static value_t *s_visited_values; /* BST of visited values */
-#endif/*PARANOIA*/
-
-static void dump_dwarf_section (enum dwarf_section_display_enum dwarf_idx);
-static void byte_set_little_endian (
- unsigned char *field, int size, dwarf_vma val);
-static void byte_set_big_endian (
- unsigned char *field, int size, dwarf_vma val);
-static void (*byte_set) (unsigned char *, int, dwarf_vma);
-
-void update_dwarf_if_necessary(Elf *elf __attribute__((unused)),
- GElf_Ehdr *ehdr,
- Elf *newelf __attribute__((unused)),
- shdr_info_t *shdr_info, int num_shdr_info,
- int *num_total_patches, int *num_failed_patches)
-{
- /* Find the debug sections */
-
- int cnt;
-
- /* Initialize the static variables, which might have been left in
- nondefault states from a previous call to this function.
- */
- s_shdr_info = NULL;
- s_cached_find_section_result = NULL;
- s_shdr_info_len = 0;
- s_num_total_patches = 0;
- s_num_failed_patches = 0;
- memset(dwarf_to_shdr, 0, sizeof(dwarf_to_shdr));
- for(cnt = 0; cnt < max; cnt++)
- free_debug_section(cnt);
-#if PARANOIA
- s_visited_values = NULL;
- init_value_free_lists();
-#endif/*PARANOIA*/
- init_dwarf_variables();
-
- cnt = 0;
-
- /* Locate the .debug_<xxx> sections, and save
- their indices (in shdr_info) in the respective
- idx_debug_<xxx> variable. If a section is not
- prwesent in the file, the variable will have
- a negative value after this loop.
- */
-
-#define CHECK_DEBUG_SECTION(sname) \
- ASSERT(shdr_info[cnt].name != NULL); \
- if (!strcmp(shdr_info[cnt].name, \
- ".debug_" _str(sname))) { \
- FAILIF(dwarf_to_shdr[sname] > 0, \
- ".debug_" _str(sname) " is already found at index %d!\n", \
- dwarf_to_shdr[sname]); \
- INFO("Index of \".debug_" _str(name) " is %d", cnt); \
- if (shdr_info[cnt].idx > 0) \
- dwarf_to_shdr[sname] = cnt; \
- else INFO(", but the section is being removed."); \
- INFO("\n"); \
- }
-
- for(cnt = 1; cnt < num_shdr_info; cnt++) {
- CHECK_DEBUG_SECTION(aranges);
- CHECK_DEBUG_SECTION(info);
- CHECK_DEBUG_SECTION(abbrev);
- CHECK_DEBUG_SECTION(line);
- CHECK_DEBUG_SECTION(frame);
- CHECK_DEBUG_SECTION(loc);
- CHECK_DEBUG_SECTION(ranges);
- CHECK_DEBUG_SECTION(pubnames);
- CHECK_DEBUG_SECTION(str);
- }
-#undef CHECK_DEBUG_SECTION
-
- {
- is_relocatable = (ehdr->e_type == ET_REL);
- eh_addr_size = 4;
-
- if (ehdr->e_ident[EI_DATA] == ELFDATA2LSB) {
- byte_get = byte_get_little_endian;
- byte_set = byte_set_little_endian;
- }
- else {
- ASSERT(ehdr->e_ident[EI_DATA] == ELFDATA2MSB);
- byte_get = byte_get_big_endian;
- byte_set = byte_set_big_endian;
- }
- }
-
-#define ADJUST_IF_NECESSARY(sname) \
- do { \
- if (dwarf_to_shdr[sname] > 0) { \
- INFO("\nAdjusting for %s.\n", shdr_info[dwarf_to_shdr[sname]].name); \
- dump_dwarf_section(sname); \
- } \
- else { \
- INFO("\nNot adjusting for %s.\n", shdr_info[dwarf_to_shdr[sname]].name); \
- } \
- } while(0)
-
- s_shdr_info = shdr_info;
- s_shdr_info_len = num_shdr_info;
-
- ADJUST_IF_NECESSARY(info);
- ADJUST_IF_NECESSARY(loc);
- ADJUST_IF_NECESSARY(aranges);
- ADJUST_IF_NECESSARY(frame);
- ADJUST_IF_NECESSARY(ranges);
- ADJUST_IF_NECESSARY(line);
- ADJUST_IF_NECESSARY(str);
- ADJUST_IF_NECESSARY(pubnames);
- ADJUST_IF_NECESSARY(abbrev);
-
-#undef ADJUST_IF_NECESSRY
-
- *num_total_patches = s_num_total_patches;
- *num_failed_patches = s_num_failed_patches;
-}
-
-int
-load_debug_section (enum dwarf_section_display_enum debug,
- void *file __attribute__((unused)))
-{
- struct dwarf_section *section = &debug_displays [debug].section;
- int shdr_idx = dwarf_to_shdr[debug];
- if (!shdr_idx) {
- INFO("Could not load section %s: it is not in the file.\n",
- debug_displays[debug].section.name);
- return 0;
- }
- ASSERT(s_shdr_info);
-
- INFO("Loading DWARF section type %s index %d (type %d)\n",
- s_shdr_info[shdr_idx].name,
- s_shdr_info[shdr_idx].idx,
- debug);
-
- /* If it is already loaded, do nothing. */
- if (section->start != NULL) {
- INFO("\tAlready loaded DWARF section type %s (type %d)\n", s_shdr_info[shdr_idx].name, debug);
- return 1;
- }
-
- ASSERT(s_shdr_info[shdr_idx].newdata);
-
- section->address = s_shdr_info[shdr_idx].shdr.sh_addr;
- section->start = s_shdr_info[shdr_idx].newdata->d_buf;
- section->size = s_shdr_info[shdr_idx].newdata->d_size;
- ASSERT(s_shdr_info[shdr_idx].newdata->d_off == 0);
-
- ASSERT(section->size != 0);
- ASSERT(s_shdr_info[shdr_idx].shdr.sh_size == s_shdr_info[shdr_idx].newdata->d_size);
- ASSERT(section->start != NULL);
-
- return 1;
-}
-
-void
-free_debug_section (enum dwarf_section_display_enum debug)
-{
- struct dwarf_section *section = &debug_displays [debug].section;
-
- INFO("Unloading DWARF section type %d\n", debug);
-
- if (section->start == NULL)
- return;
-
- section->start = NULL;
- section->address = 0;
- section->size = 0;
-}
-
-static void
-dump_dwarf_section (enum dwarf_section_display_enum dwarf_idx)
-{
- int shdr_idx = dwarf_to_shdr[dwarf_idx];
- ASSERT(shdr_idx);
- ASSERT(s_shdr_info);
- ASSERT(s_shdr_info[shdr_idx].idx);
- ASSERT(s_shdr_info[shdr_idx].name);
-
- ASSERT(!strcmp (debug_displays[dwarf_idx].section.name, s_shdr_info[shdr_idx].name));
-
- if (!debug_displays[dwarf_idx].eh_frame) {
- struct dwarf_section *sec = &debug_displays [dwarf_idx].section;
-
- if (load_debug_section (dwarf_idx, NULL)) {
- INFO("Dumping DWARF section [%s] (type %d).\n",
- s_shdr_info[shdr_idx].name,
- dwarf_idx);
- debug_displays[dwarf_idx].display (sec, NULL);
- if (dwarf_idx != info && dwarf_idx != abbrev)
- free_debug_section (dwarf_idx);
- }
- }
-}
-
-static shdr_info_t *find_section(int value)
-{
- ASSERT(s_shdr_info != NULL);
- ASSERT(s_shdr_info_len > 0);
-
-#define IN_RANGE(v,s,l) ((s)<=(v) && (v)<((s)+(l)))
- if (s_cached_find_section_result != NULL &&
- IN_RANGE((unsigned)value,
- s_cached_find_section_result->old_shdr.sh_addr,
- s_cached_find_section_result->old_shdr.sh_size)) {
- return s_cached_find_section_result;
- }
-
- /* Find the section to which the address belongs. */
- int cnt;
- for (cnt = 0; cnt < s_shdr_info_len; cnt++) {
- if (s_shdr_info[cnt].idx > 0 &&
- (s_shdr_info[cnt].old_shdr.sh_flags & SHF_ALLOC) &&
- IN_RANGE((unsigned) value,
- s_shdr_info[cnt].old_shdr.sh_addr,
- s_shdr_info[cnt].old_shdr.sh_size)) {
-
- s_cached_find_section_result = s_shdr_info + cnt;
- return s_cached_find_section_result;
- }
- }
-#undef IN_RANGE
-
- return NULL;
-}
-
-#if PARANOIA
-static value_t **s_value_free_lists;
-static int s_num_free_lists;
-static int s_cur_free_list;
-static int s_alloc_values; /* number of allocated values in the list */
-#define LISTS_INCREMENT (10)
-#define NUM_VALUES_PER_LIST (10000)
-
-static void init_value_free_lists()
-{
- if (s_value_free_lists) {
- value_t **trav = s_value_free_lists;
- while(s_cur_free_list) {
- FREE(*trav++);
- s_cur_free_list--;
- }
- FREE(s_value_free_lists);
- s_value_free_lists = NULL;
- }
- s_num_free_lists = 0;
- s_alloc_values = 0;
-}
-
-static value_t *alloc_value()
-{
- if (s_alloc_values == NUM_VALUES_PER_LIST) {
- s_cur_free_list++;
- s_alloc_values = 0;
- }
-
- if (s_cur_free_list == s_num_free_lists) {
- s_num_free_lists += LISTS_INCREMENT;
- s_value_free_lists = REALLOC(s_value_free_lists,
- s_num_free_lists * sizeof(value_t *));
- memset(s_value_free_lists + s_cur_free_list,
- 0,
- (s_num_free_lists - s_cur_free_list) * sizeof(value_t *));
- }
-
- if (s_value_free_lists[s_cur_free_list] == NULL) {
- s_value_free_lists[s_cur_free_list] = MALLOC(NUM_VALUES_PER_LIST*sizeof(value_t));
- }
-
- return s_value_free_lists[s_cur_free_list] + s_alloc_values++;
-}
-
-static value_t *would_be_parent = NULL;
-static value_t *find_value(unsigned long val)
-{
- would_be_parent = NULL;
- value_t *trav = s_visited_values;
- while(trav) {
- would_be_parent = trav;
- if (val < trav->key)
- trav = trav->left;
- else if (val > trav->key)
- trav = trav->right;
- else if (val == trav->key) {
- return trav;
- }
- }
- return NULL;
-}
-
-static int value_visited(unsigned long val)
-{
- value_t *found = find_value(val);
- if (found != NULL) {
-#if COLLECT_BACKTRACES
- void *new_bt[BACKTRACE_DEPTH];
- int new_bt_depth = backtrace(new_bt, BACKTRACE_DEPTH);
- char **symbols = backtrace_symbols(new_bt, new_bt_depth);
- PRINT("NEW VISIT AT %x\n", val);
- if (symbols != NULL) {
- int cnt = 0;
- while(cnt < new_bt_depth) {
- PRINT("\t%s\n", symbols[cnt]);
- cnt++;
- }
- }
- FREE(symbols);
- PRINT("OLD VISIT AT %x\n", val);
- symbols = backtrace_symbols(found->backtrace, found->backtrace_depth);
- if (symbols != NULL) {
- int cnt = 0;
- while(cnt < new_bt_depth) {
- PRINT("\t%s\n", symbols[cnt]);
- cnt++;
- }
- }
- FREE(symbols);
-#else
- ERROR("DWARF: Double update at address 0x%lx!\n", val);
-#endif/*COLLECT_BACKTRACES*/
- return 1;
- }
- found = alloc_value();
- found->left = found->right = NULL;
- found->key = val;
-#if COLLECT_BACKTRACES
- found->backtrace_depth = backtrace(found->backtrace, BACKTRACE_DEPTH);
-#endif/*COLLECT_BACKTRACES*/
- if (would_be_parent == NULL) {
- s_visited_values = found;
- } else {
- if (val < would_be_parent->key)
- would_be_parent->left = found;
- else
- would_be_parent->right = found;
- }
- return 0;
-}
-#else
-static int value_visited(unsigned long val __attribute__((unused)))
-{
- return 0;
-}
-#endif /*PARANOIA*/
-
-void value_hook(void *data, int size, int val)
-{
- shdr_info_t *shdr = find_section(val);
- s_num_total_patches++;
- if(shdr == NULL) {
- PRINT("DWARF: cannot map address 0x%x to any section!\n", val);
- s_num_failed_patches++;
- return;
- }
- long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr;
- if(delta) {
- if (!value_visited((unsigned long)data)) {
- INFO("DWARF: adjusting %d-byte value at %p: 0x%x -> 0x%x (delta %d per section %s)\n",
- size, data,
- val, (int)(val + delta), (int)delta,
- shdr->name);
- byte_set(data, size, val + delta);
- }
- }
-}
-
-void base_value_pair_hook(void *data, int size,
- int base, int begin, int end)
-{
- shdr_info_t *shdr = find_section(base + begin);
- s_num_total_patches++;
-
- if (begin > end) {
- PRINT("DWARF: start > end in range 0x%x:[0x%x, 0x%x)!\n",
- base,
- begin,
- end);
- s_num_failed_patches++;
- return;
- }
-
- if(shdr == NULL) {
- PRINT("DWARF: cannot map range 0x%x:[0x%x, 0x%x) to any section!\n",
- base,
- begin,
- end);
- s_num_failed_patches++;
- return;
- }
-
- if (unlikely(begin != end)) {
- shdr_info_t *end_shdr = find_section(base + end - 1);
- if (shdr != end_shdr) {
- printf("DWARF: range 0x%x:[%x, %x) maps to different sections: %s and %s!\n",
- base,
- begin, end,
- shdr->name,
- (end_shdr ? end_shdr->name : "(none)"));
- s_num_failed_patches++;
- return;
- }
- }
-
- long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr;
- if(delta) {
- if (!value_visited((unsigned long)data)) {
- INFO("DWARF: adjusting %d-byte value at %p: 0x%x -> 0x%x (delta %d per section %s)\n",
- size, data,
- begin, (int)(begin + delta), (int)delta,
- shdr->name);
- byte_set(data, size, begin + delta);
- byte_set(data + size, size, end + delta);
- }
- }
-}
-
-void signed_value_hook(
- void *data,
- int pointer_size,
- int is_signed,
- int value)
-{
- INFO("DWARF frame info: initial PC value: %8x (width %d), %ssigned\n",
- value, pointer_size,
- (!is_signed ? "un" : ""));
-
- ASSERT(s_shdr_info != NULL);
-
- /* Find the section to which the address belongs. */
- shdr_info_t *shdr = find_section(value);
- s_num_total_patches++;
- if(shdr == NULL) {
- PRINT("DWARF: cannot map address 0x%x to any section!\n", value);
- s_num_failed_patches++;
- return;
- }
-
- long delta = shdr->shdr.sh_addr - shdr->old_shdr.sh_addr;
-
- INFO("DWARF frame info: initial PC value: 0x%lx -> 0x%lx (delta %ld per section %s).\n",
- (long)value,
- (long)(value + delta),
- delta,
- shdr->name);
-
- if (delta) {
- if (!value_visited((unsigned long)data)) {
- value += delta;
- if (is_signed) {
- switch (pointer_size) {
- case 1:
- value &= 0xFF;
- value = (value ^ 0x80) - 0x80;
- break;
- case 2:
- value &= 0xFFFF;
- value = (value ^ 0x8000) - 0x8000;
- break;
- case 4:
- value &= 0xFFFFFFFF;
- value = (value ^ 0x80000000) - 0x80000000;
- break;
- case 8:
- break;
- default:
- FAILIF(1, "Unsupported data size %d!\n", pointer_size);
- }
- }
- byte_set(data, pointer_size, value);
- }
- }
-}
-
-static void byte_set_little_endian (unsigned char *field, int size, dwarf_vma val)
-{
- switch (size) {
- case 1:
- FAILIF(val > 0xFF,
- "Attempting to set value 0x%lx to %d-bit integer!\n",
- val, size*8);
- *((uint8_t *)field) = (uint8_t)val;
- break;
- case 2:
- FAILIF(val > 0xFFFF,
- "Attempting to set value 0x%lx to %d-bit integer!\n",
- val, size*8);
- field[1] = (uint8_t)(val >> 8);
- field[0] = (uint8_t)val;
- break;
- case 4:
-#if 0
- // this will signal false negatives when running on a 64 bit system.
- FAILIF(val > 0xFFFFFFFF,
- "Attempting to set value 0x%lx to %d-bit integer!\n",
- val, size*8);
-#endif
- field[3] = (uint8_t)(val >> 23);
- field[2] = (uint8_t)(val >> 16);
- field[1] = (uint8_t)(val >> 8);
- field[0] = (uint8_t)val;
- break;
- default:
- FAILIF(1, "Unhandled data length: %d\n", size);
- }
-}
-
-static void byte_set_big_endian (unsigned char *field __attribute__((unused)),
- int size __attribute__((unused)),
- dwarf_vma val __attribute__((unused)))
-{
- FAILIF(1, "Not implemented.\n");
-}
diff --git a/fixdwarf.h b/fixdwarf.h
deleted file mode 100644
index 32f2f48..0000000
--- a/fixdwarf.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef FIXDWARF_H
-#define FIXDWARF_H
-
-#include <elf.h>
-#include <gelf.h>
-#include <elfcopy.h>
-
-extern void update_dwarf_if_necessary(
- Elf *elf, GElf_Ehdr *ehdr, Elf *newelf,
- shdr_info_t *shdr_info, int num_shdr_info,
- int *num_total_patches, int *num_failed_patches);
-
-
-#endif
diff --git a/hash.c b/hash.c
deleted file mode 100644
index e2cffcc..0000000
--- a/hash.c
+++ /dev/null
@@ -1,76 +0,0 @@
-#include <common.h>
-#include <debug.h>
-#include <libelf.h>
-#include <hash.h>
-#include <string.h>
-
-void setup_hash(Elf_Data *hash_data,
- Elf32_Word nbuckets,
- Elf32_Word nchains)
-{
- hash_data->d_size = 2;
- hash_data->d_size += nbuckets;
- hash_data->d_size += nchains;
- hash_data->d_buf = CALLOC(hash_data->d_size, sizeof(Elf32_Word));
- hash_data->d_size *= sizeof(Elf32_Word);
- ((Elf32_Word *)hash_data->d_buf)[0] = nbuckets;
- ((Elf32_Word *)hash_data->d_buf)[1] = nchains;
-}
-
-void add_to_hash(Elf_Data *hash_data,
- const char *symbol,
- int symindex)
-{
- Elf32_Word *buckets = (Elf32_Word *)hash_data->d_buf;
- Elf32_Word nbuckets = *buckets++;
- Elf32_Word *chains = ++buckets + nbuckets;
- Elf32_Word last_chain_index;
- unsigned long bucket = elf_hash(symbol) % nbuckets;
-
- ASSERT(symindex != STN_UNDEF);
-
- if (buckets[bucket] == STN_UNDEF) {
- INFO("Adding [%s] to hash at bucket [%ld] (first add)\n",
- symbol, bucket);
- buckets[bucket] = symindex;
- }
- else {
- INFO("Collision on adding [%s] to hash at bucket [%ld]\n",
- symbol, bucket);
- last_chain_index = buckets[bucket];
- while (chains[last_chain_index] != STN_UNDEF) {
- INFO("\ttrying at chain index [%d]...\n", last_chain_index);
- last_chain_index = chains[last_chain_index];
- }
- INFO("\tsuccess at chain index [%d]...\n", last_chain_index);
- chains[last_chain_index] = symindex;
- }
-}
-
-int hash_lookup(Elf *elf,
- section_info_t *hash_info,
- section_info_t *symtab_info,
- const char *symname,
- GElf_Sym *sym_mem)
-{
- Elf32_Word *hash_data = (Elf32_Word *)hash_info->data->d_buf;
- Elf32_Word index;
- Elf32_Word nbuckets = *hash_data++;
- Elf32_Word *buckets = ++hash_data;
- Elf32_Word *chains = hash_data + nbuckets;
-
- GElf_Sym *sym;
-
- index = buckets[elf_hash(symname) % nbuckets];
- while(index != STN_UNDEF)
- {
- sym = gelf_getsymshndx (symtab_info->data, NULL, index, sym_mem, NULL);
- FAILIF_LIBELF(NULL == sym, gelf_getsymshndx);
- if (!strcmp(symname,
- elf_strptr(elf, symtab_info->hdr->sh_link, sym->st_name)))
- break;
- index = chains[index];
- }
-
- return index;
-}
diff --git a/hash.h b/hash.h
deleted file mode 100644
index f2d5806..0000000
--- a/hash.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef HASH_H
-#define HASH_H
-
-#include <common.h>
-#include <libelf.h>
-#include <gelf.h>
-
-void setup_hash(Elf_Data *hash_data,
- Elf32_Word nbuckets,
- Elf32_Word nchains);
-
-void add_to_hash(Elf_Data *hash_data,
- const char *symbol,
- int symindex);
-
-int hash_lookup(Elf *elf,
- section_info_t *hash,
- section_info_t *symtab,
- const char *symname,
- GElf_Sym *sym_mem);
-
-#endif/*HASH_H*/
diff --git a/rangesort.c b/rangesort.c
deleted file mode 100644
index fa35325..0000000
--- a/rangesort.c
+++ /dev/null
@@ -1,335 +0,0 @@
-#include <common.h>
-#include <debug.h>
-#include <rangesort.h>
-
-#define PARALLEL_ARRAY_SIZE (5)
-
-struct range_list_t {
- range_t *array;
-#ifdef DEBUG
- int is_sorted;
-#endif
- int array_length;
- int num_ranges;
-};
-
-range_list_t* init_range_list(void) {
- range_list_t *ranges = (range_list_t *)MALLOC(sizeof(range_list_t));
-
- ranges->array = (range_t *)MALLOC(PARALLEL_ARRAY_SIZE*sizeof(range_t));
- ranges->array_length = PARALLEL_ARRAY_SIZE;
- ranges->num_ranges = 0;
-#ifdef DEBUG
- ranges->is_sorted = 0;
-#endif
- return ranges;
-}
-
-void destroy_range_list(range_list_t *ranges) {
- int idx;
- for (idx = 0; idx < ranges->num_ranges; idx++) {
- if (ranges->array[idx].user_dtor) {
- ASSERT(ranges->array[idx].user);
- ranges->array[idx].user_dtor(ranges->array[idx].user);
- }
- }
- FREE(ranges->array);
- FREE(ranges);
-}
-
-static inline int CONTAINS(range_t *container, range_t *contained) {
- return container->start <= contained->start && contained->length &&
- (container->start + container->length >
- contained->start + contained->length);
-}
-
-static inline int IN_RANGE(range_t *range, GElf_Off point) {
- return
- range->start <= point &&
- point < (range->start + range->length);
-}
-
-static inline int INTERSECT(range_t *left, range_t *right) {
- return
- (IN_RANGE(left, right->start) &&
- IN_RANGE(right, left->start + left->length)) ||
- (IN_RANGE(right, left->start) &&
- IN_RANGE(left, right->start + right->length));
-}
-
-static int range_cmp_for_search(const void *l, const void *r) {
- range_t *left = (range_t *)l, *right = (range_t *)r;
- if (INTERSECT(left, right) ||
- CONTAINS(left, right) ||
- CONTAINS(right, left)) {
- return 0;
- }
-
- /* elfcopy.c checks that the start of a section begins at or
- after end of the previous section in the sorted list. So we need
- to be careful about empty sections. */
- if (left->start != right->start)
- return left->start - right->start;
- else {
- ASSERT(left->length == 0 || right->length == 0);
- return left->length - right->length;
- }
-}
-
-static inline void run_checks(const void *l, const void *r) {
- range_t *left = (range_t *)l, *right = (range_t *)r;
- if (CONTAINS(left, right)) {
- if (left->err_fn)
- left->err_fn(ERROR_CONTAINS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld) contains [%lld, %lld)!\n",
- left->start, left->start + left->length,
- right->start, right->start + right->length);
- }
- if (CONTAINS(right, left)) {
- if (right->err_fn)
- right->err_fn(ERROR_CONTAINS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld) contains [%lld, %lld)!\n",
- right->start, right->start + right->length,
- left->start, left->start + left->length);
- }
- if (INTERSECT(left, right)) {
- if (left->err_fn)
- left->err_fn(ERROR_OVERLAPS, left, right);
- FAILIF(1, "Range sorting error: [%lld, %lld)and [%lld, %lld) intersect!\n",
- left->start, left->start + left->length,
- right->start, right->start + right->length);
- }
-}
-
-static int range_cmp(const void *l, const void *r) {
- run_checks(l, r);
- range_t *left = (range_t *)l, *right = (range_t *)r;
-
- /* elfcopy.c checks that the start of a section begins at or
- after end of the previous section in the sorted list. So we need
- to be careful about empty sections. */
- if (left->start != right->start)
- return left->start - right->start;
- else {
- ASSERT(left->length == 0 || right->length == 0);
- return left->length - right->length;
- }
-}
-
-void add_unique_range_nosort(
- range_list_t *ranges,
- GElf_Off start,
- GElf_Off length,
- void *user,
- void (*err_fn)(range_error_t, range_t *, range_t *),
- void (*user_dtor)(void * ))
-{
- if (ranges->num_ranges == ranges->array_length) {
- ranges->array_length += PARALLEL_ARRAY_SIZE;
- ranges->array = REALLOC(ranges->array,
- ranges->array_length*sizeof(range_t));
- }
- ranges->array[ranges->num_ranges].start = start;
- ranges->array[ranges->num_ranges].length = length;
- ranges->array[ranges->num_ranges].user = user;
- ranges->array[ranges->num_ranges].err_fn = err_fn;
- ranges->array[ranges->num_ranges].user_dtor = user_dtor;
- ranges->num_ranges++;
-}
-
-range_list_t *sort_ranges(range_list_t *ranges) {
- if (ranges->num_ranges > 1)
- qsort(ranges->array, ranges->num_ranges, sizeof(range_t), range_cmp);
- ranges->is_sorted = 1;
- return ranges;
-}
-
-range_t *find_range(range_list_t *ranges, GElf_Off value) {
-#if 1
- int i;
- for (i = 0; i < ranges->num_ranges; i++) {
- if (ranges->array[i].start <= value &&
- value < ranges->array[i].start + ranges->array[i].length)
- return ranges->array + i;
- }
- return NULL;
-#else
- ASSERT(ranges->is_sorted); /* The range list must be sorted */
- range_t lookup;
- lookup.start = value;
- lookup.length = 0;
- return
- (range_t *)bsearch(&lookup,
- ranges->array, ranges->num_ranges, sizeof(range_t),
- range_cmp_for_search);
-#endif
-}
-
-int get_num_ranges(const range_list_t *ranges)
-{
- return ranges->num_ranges;
-}
-
-range_t *get_sorted_ranges(const range_list_t *ranges, int *num_ranges) {
- ASSERT(ranges->is_sorted); /* The range list must be sorted */
- if (num_ranges) {
- *num_ranges = ranges->num_ranges;
- }
- return ranges->array;
-}
-
-GElf_Off get_last_address(const range_list_t *ranges) {
- ASSERT(ranges->num_ranges);
- return
- ranges->array[ranges->num_ranges-1].start +
- ranges->array[ranges->num_ranges-1].length;
-}
-
-static void handle_range_error(range_error_t err,
- range_t *left, range_t *right) {
- switch (err) {
- case ERROR_CONTAINS:
- ERROR("ERROR: section (%lld, %lld bytes) contains "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- case ERROR_OVERLAPS:
- ERROR("ERROR: Section (%lld, %lld bytes) intersects "
- "section (%lld, %lld bytes)\n",
- left->start, left->length,
- right->start, right->length);
- break;
- default:
- ASSERT(!"Unknown range error code!");
- }
-
- FAILIF(1, "Range error.\n");
-}
-
-static void destroy_contiguous_range_info(void *user) {
- contiguous_range_info_t *info = (contiguous_range_info_t *)user;
- FREE(info->ranges);
- FREE(info);
-}
-
-static void handle_contiguous_range_error(range_error_t err,
- range_t *left,
- range_t *right)
-{
- contiguous_range_info_t *left_data =
- (contiguous_range_info_t *)left->user;
- ASSERT(left_data);
- contiguous_range_info_t *right_data =
- (contiguous_range_info_t *)right->user;
- ASSERT(right_data);
-
- PRINT("Contiguous-range overlap error. Printing contained ranges:\n");
- int cnt;
- PRINT("\tLeft ranges:\n");
- for (cnt = 0; cnt < left_data->num_ranges; cnt++) {
- PRINT("\t\t[%lld, %lld)\n",
- left_data->ranges[cnt].start,
- left_data->ranges[cnt].start + left_data->ranges[cnt].length);
- }
- PRINT("\tRight ranges:\n");
- for (cnt = 0; cnt < right_data->num_ranges; cnt++) {
- PRINT("\t\t[%lld, %lld)\n",
- right_data->ranges[cnt].start,
- right_data->ranges[cnt].start + right_data->ranges[cnt].length);
- }
-
- handle_range_error(err, left, right);
-}
-
-range_list_t* get_contiguous_ranges(const range_list_t *input)
-{
- ASSERT(input);
- FAILIF(!input->is_sorted,
- "get_contiguous_ranges(): input range list is not sorted!\n");
-
- range_list_t* ret = init_range_list();
- int num_ranges;
- range_t *ranges = get_sorted_ranges(input, &num_ranges);
-
- int end_idx = 0;
- while (end_idx < num_ranges) {
- int start_idx = end_idx++;
- int old_end_idx = start_idx;
- int total_length = ranges[start_idx].length;
- while (end_idx < num_ranges) {
- if (ranges[old_end_idx].start + ranges[old_end_idx].length !=
- ranges[end_idx].start)
- break;
- old_end_idx = end_idx++;
- total_length += ranges[old_end_idx].length;
- }
-
- contiguous_range_info_t *user =
- (contiguous_range_info_t *)MALLOC(sizeof(contiguous_range_info_t));
- user->num_ranges = end_idx - start_idx;
- user->ranges = (range_t *)MALLOC(user->num_ranges * sizeof(range_t));
- int i;
- for (i = 0; i < end_idx - start_idx; i++)
- user->ranges[i] = ranges[start_idx + i];
- add_unique_range_nosort(ret,
- ranges[start_idx].start,
- total_length,
- user,
- handle_contiguous_range_error,
- destroy_contiguous_range_info);
- }
-
- return ret;
-}
-
-range_list_t* subtract_ranges(const range_list_t *r, const range_list_t *s)
-{
- ASSERT(r); ASSERT(r->is_sorted);
- ASSERT(s); ASSERT(s->is_sorted);
-
- range_list_t *result = init_range_list();
-
- int r_num_ranges, r_idx;
- range_t *r_ranges = get_sorted_ranges(r, &r_num_ranges);
- ASSERT(r_ranges);
-
- int s_num_ranges, s_idx;
- range_t *s_ranges = get_sorted_ranges(s, &s_num_ranges);
- ASSERT(s_ranges);
-
- s_idx = 0;
- for (r_idx = 0; r_idx < r_num_ranges; r_idx++) {
- GElf_Off last_start = r_ranges[r_idx].start;
- for (; s_idx < s_num_ranges; s_idx++) {
- if (CONTAINS(&r_ranges[r_idx], &s_ranges[s_idx])) {
- if (last_start ==
- r_ranges[r_idx].start + r_ranges[r_idx].length) {
- break;
- }
- if (last_start == s_ranges[s_idx].start) {
- last_start += s_ranges[s_idx].length;
- continue;
- }
- INFO("Adding subtracted range [%lld, %lld)\n",
- last_start,
- s_ranges[s_idx].start);
- add_unique_range_nosort(
- result,
- last_start,
- s_ranges[s_idx].start - last_start,
- NULL,
- NULL,
- NULL);
- last_start = s_ranges[s_idx].start + s_ranges[s_idx].length;
- } else {
- ASSERT(!INTERSECT(&r_ranges[r_idx], &s_ranges[s_idx]));
- break;
- }
- } /* while (s_idx < s_num_ranges) */
- } /* for (r_idx = 0; r_idx < r_num_ranges; r_idx++) */
-
- return result;
-}
-
-
diff --git a/rangesort.h b/rangesort.h
deleted file mode 100644
index 21db357..0000000
--- a/rangesort.h
+++ /dev/null
@@ -1,105 +0,0 @@
-#ifndef RANGESORT_H
-#define RANGESORT_H
-
-/* This implements a simple sorted list of non-overlapping ranges. */
-
-#include <debug.h>
-#include <common.h>
-#include <gelf.h>
-
-typedef enum range_error_t {
- ERROR_CONTAINS,
- ERROR_OVERLAPS
-} range_error_t;
-
-typedef struct range_t range_t;
-struct range_t {
- GElf_Off start;
- GElf_Off length;
- void *user;
- void (*err_fn)(range_error_t, range_t *, range_t *);
- void (*user_dtor)(void *);
-};
-
-typedef struct range_list_t range_list_t;
-
-range_list_t* init_range_list();
-void destroy_range_list(range_list_t *);
-
-/* Just adds a range to the list. We won't detect whether the range overlaps
- other ranges or contains them, or is contained by them, till we call
- sort_ranges(). */
-void add_unique_range_nosort(range_list_t *ranges,
- GElf_Off start, GElf_Off length,
- void *user,
- void (*err_fn)(range_error_t, range_t *, range_t *),
- void (*user_dtor)(void * ));
-
-/* Sorts the ranges. If there are overlapping ranges or ranges that contain
- other ranges, it will cause the program to exit with a FAIL. */
-range_list_t* sort_ranges(range_list_t *ranges);
-/* Find which range value falls in. Return that range or NULL if value does
- not fall within any range. */
-range_t *find_range(range_list_t *ranges, GElf_Off value);
-int get_num_ranges(const range_list_t *ranges);
-range_t *get_sorted_ranges(const range_list_t *ranges, int *num_ranges);
-GElf_Off get_last_address(const range_list_t *ranges);
-
-/* This returns a range_list_t handle that contains ranges composed of the
- adjacent ranges of the input range list. The user data of each range in
- the range list is a structure of the type contiguous_range_info_t.
- This structure contains an array of pointers to copies of the original
- range_t structures comprising each new contiguous range, as well as the
- length of that array.
-
- NOTE: The input range must be sorted!
-
- NOTE: destroy_range_list() will take care of releasing the data that it
- allocates as a result of calling get_contiguous_ranges(). Do not free that
- data yourself.
-
- NOTE: the user data of the original range_t structures is simply copied, so
- be careful handling it. You can destroy the range_list_t with
- destroy_range_list() as usual. On error, the function does not return--the
- program terminates.
-
- NOTE: The returned range is not sorted. You must call sort_ranges() if you
- need to.
-*/
-
-typedef struct {
- int num_ranges;
- range_t *ranges;
-} contiguous_range_info_t;
-
-range_list_t* get_contiguous_ranges(const range_list_t *);
-
-/* The function below takes in two range lists: r and s, and subtracts the
- ranges in s from those in r. For example, if r and s are as follows:
-
- r = { [0, 10) }
- s = { [3, 5), [7, 9) }
-
- Then r - s is { [0, 3), [5, 7), [9, 10) }
-
- NOTE: Both range lists must be sorted on input. This is guarded by an
- assertion.
-
- NOTE: Range s must contain ranges, which are fully contained by the span of
- range r (the span being the interval between the start of the lowest
- range in r, inclusive, and the end of the highest range in r,
- exclusive).
-
- NOTE: In addition to the requirement above, range s must contain ranges,
- each of which is a subrange of one of the ranges of r.
-
- NOTE: There is no user info associated with the resulting range.
-
- NOTE: The resulting range is not sorted.
-
- Ther returned list must be destroyed with destroy_range_list().
-*/
-
-range_list_t* subtract_ranges(const range_list_t *r, const range_list_t *s);
-
-#endif/*RANGESORT_H*/