diff options
Diffstat (limited to 'trunk')
223 files changed, 89569 insertions, 0 deletions
diff --git a/trunk/AUTHORS b/trunk/AUTHORS new file mode 100644 index 0000000..96a4141 --- /dev/null +++ b/trunk/AUTHORS @@ -0,0 +1,2 @@ +For Now: +Jakub Jelinek. diff --git a/trunk/COPYING b/trunk/COPYING new file mode 100644 index 0000000..eeb586b --- /dev/null +++ b/trunk/COPYING @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy <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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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) 19yy 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/trunk/ChangeLog b/trunk/ChangeLog new file mode 100644 index 0000000..9e2961f --- /dev/null +++ b/trunk/ChangeLog @@ -0,0 +1,114 @@ +2006-12-01 Jakub Jelinek <jakub@redhat.com> + + * src/verify.c (prelink_verify): Unlink ent->filename in case of + failures between closing the unprelinked dso and unlinking + ent->filename. + +2006-10-27 Jakub Jelinek <jakub@redhat.com> + + * src/prelink.h (READWRITEPROTOSIZE): Undef after use. + +2006-10-24 Richard Sandiford <richard@codesourcery.com> + + * testsuite/tls3.sh: Use -fpic for MIPS too. + * testsuite/reloc2.sh: Likewise. + + * testsuite/reloc4.sh: Use -mxgot when compiling for MIPS targets. + * testsuite/reloc5.c (main): Make the printed inline asm globalize + testzero. + + * testsuite/shuffle2.c (testzero): Globalize asm definition. + + * src/Makefile.am (arch_SOURCES): Add arch-mips.c + * src/Makefile.in: Regenerate. + * src/arch-mips.c: New file. + + * src/prelink.h (DT_MIPS_RLD_VERSION): Define. + (DT_MIPS_TIME_STAMP): Likewise. + (DT_MIPS_ICHECKSUM): Likewise. + (DT_MIPS_IVERSION): Likewise. + (DT_MIPS_FLAGS): Likewise. + (DT_MIPS_BASE_ADDRESS): Likewise. + (DT_MIPS_CONFLICT): Likewise. + (DT_MIPS_LIBLIST): Likewise. + (DT_MIPS_LOCAL_GOTNO): Likewise. + (DT_MIPS_CONFLICTNO): Likewise. + (DT_MIPS_LIBLISTNO): Likewise. + (DT_MIPS_SYMTABNO): Likewise. + (DT_MIPS_UNREFEXTNO): Likewise. + (DT_MIPS_GOTSYM): Likewise. + (DT_MIPS_HIPAGENO): Likewise. + (DT_MIPS_RLD_MAP): Likewise. + (R_MIPS_TLS_DTPMOD): Likewise. + (R_MIPS_TLS_DTPREL): Likewise. + (R_MIPS_TLS_TPREL): Likewise. + (R_MIPS_GLOB_DAT): Likewise. + (DSO): Add info_DT_MIPS_LOCAL_GOTNO, info_DT_MIPS_GOTSYM, + and info_DT_MIPS_SYMTABNO. + + * src/dso.c (read_dynamic): Initialize the new DSO fields. + (adjust_symbol_p): Handle stub values on MIPS. + * src/prelink.c (prelink_prepare): Handle SHT_DYNAMIC and + SHT_MIPS_REGINFO on MIPS. + * src/space.c (find_readonly_space): Don't place the new section + in the PT_PHDR segment. + + * src/prelink.h (data_iterator): New structure. + (init_data_iterator): Declare. + (get_data_from_iterator): Likewise. + (get_sym_from_iterator): Likewise. + * src/data.c (init_data_iterator): New function. + (get_data_from_iterator): Likewise. + (get_sym_from_iterator): Likewise. + + * src/prelink.h (READWRITEPROTOSIZE): New macro. Instantiate + READWRITEPROTO for big and little endian. Add prototypes for + native-endian functions (buf_read_uneNN, read_uneNN, buf_write_neNN + and write_neNN). Replace uses of READWRITEPROTO with uses of + this macro. + * src/data.c (BUFREADUNE, READUNE, WRITENE, BUFWRITENE): New macros. + (READWRITESIZE): New macro. Instantiate READWRITE for big and + little endian. Instantiate BUFREADUNE, READUNE, WRITENE + and BUFWRITENE. Replace uses of READWRITE with uses of this macro. + * src/arch-sh.c (read_une32, write_ne32, buf_write_ne32): Delete. + + * src/prelink.h (PLArch): Add an arch_prelink_conflict callback. + * src/conflict.c (prelink_build_conflicts): If defined, call it + for each dependency. + + * src/prelink.h (PLArch): Make the arch_prelink callback take + a "struct prelink_info *" argument, not a "DSO *" argument. + * src/prelink.c (prelink): Adjust call accordingly. + * src/arch-alpha.c (alpha_arch_prelink): Adjust definition accordingly. + * src/arch-arm.c (arm_arch_prelink): Likewise. + * src/arch-cris.c (cris_arch_prelink): Likewise. + * src/arch-i386.c (i386_arch_prelink): Likewise. + * src/arch-ia64.c (ia64_arch_prelink): Likewise. + * src/arch-ppc.c (ppc_arch_prelink): Likewise. + * src/arch-s390.c (s390_arch_prelink): Likewise + * src/arch-s390x.c (s390x_arch_prelink): Likewise + * src/arch-sh.c (sh_arch_prelink): Likewise. + * src/arch-sparc64.c (sparc64_arch_prelink): Likewise. + * src/arch-sparc.c (sparc_arch_prelink): Likewise + * src/arch-x86_64.c (x86_64_arch_prelink): Likewise. + + * src/prelink.h (PLArch): Add an arch_adjust callback. + * src/dso.c (adjust_dso): Use it, if defined. + + * src/prelink.h (adjust_symbol_p): Declare. + * src/dso.c (adjust_symbol_p): New function, extracted from... + (adjust_symtab): ...here. + +2006-10-27 Jakub Jelinek <jakub@redhat.com> + + * src/dwarf2.c (adjust_dwarf2_ranges): Fix adjusting if end of range + is at the end of some section and there is padding before the + following one. + +2006-07-28 Alexandre Oliva <aoliva@redhat.com> + + * src/cache.c (deps_cmp): Avoid segfault if both a and b are NULL. + +2001-05-24 Jakub Jelinek <jakub@redhat.com> + + * The beginning. diff --git a/trunk/ChangeLog.cross b/trunk/ChangeLog.cross new file mode 100644 index 0000000..1578fd6 --- /dev/null +++ b/trunk/ChangeLog.cross @@ -0,0 +1,115 @@ +2006-12-01 Mark Hatle <mark.hatle@windriver.com> + + * merge to 20061201 (r151) + * src/arch-arm.c: remove read_une32, write_ne32, buf_write_ne32, + buf_read_une32 + * src/dso-readonly.c: sync to changes in src/dso.c + +2006-08-18 Mark Hatle <mark.hatle@windriver.com> + + * arch-arm.c: remove prelink_conflict_rela + * arch-arm.c: Add big-endian arm support, based on arch-sh.c + +2006-08-17 Mark Hatle <mark.hatle@windriver.com> + + * data.c, dso.c, prelink.h: when using elfutils/libelf, we need + to byte swap only if the type is ELF_T_BYTE. + * dso-readonly.c: add get_data prototype change for byteswapping + * ld-libs.c: add get_data prototype change for byteswapping + +2006-08-10 Mark Hatle <mark.hatle@windriver.com> + + * testsuite/Makefile.in: Allow testsuite to run using cross prelink. + Disable the run-time tests, but keep all basic + prelink testing. + * testsuite/ccx1.sh, testsuite/cycle1.sh, testsuite/cycle2.sh + testsuite/deps1.sh, testsuite/deps2.sh, testuite/functions.sh + testuite/layout1.sh, testuite/layout2.sh, testsuite/movelibs.sh + testsuite/quick1.sh, testsuite/quick2.sh, testsuite/quick3.sh + testsuite/reloc1.sh, testsuite/reloc2.sh, testsuite/reloc3.sh + testsuite/reloc4.sh, testsuite/reloc5.sh, testsuite/reloc6.sh + testsuite/reloc7.sh, testsuite/reloc8.sh, testsuite/reloc9.sh + testsuite/reloc10.sh, testsuite/reloc11.sh, testsuite/shuffle1.sh + testsuite/shuffle2.c, testsuite/shuffle2.sh, testsuite/shuffle3.sh + testsuite/shuffle4.sh, testsuite/shuffle5.sh, testsuite/shuffle6.sh + testsuite/shuffle7.sh, testsuite/shuffle8.sh, testsuite/tls1.sh + testsuite/tls2.sh, testsuite/tls3.sh, testsuite/tls4.sh + testsuite/tls5.sh, testsuite/tls6.sh, testsuite/tls7.sh + testsuite/undo1.sh: ditto + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * execstack.c: add WR versioning + * ld-libs.c: add argp option processing and WR versioning + * main.c: add WR versioning + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * ld-libs.c: Add --root argument to prelink-rtld + +2006-08-09 Mark Hatle <mark.hatle@windriver.com> + + * cross-prelink code merged and upreved + original code from: + MontaVista Software, Inc. + CodeSourcery, LLC. + * Makefile.am: add prelink-rtld, libiberty + * dso-readonly.c: new file based on dso.c + * gather.c: use cross-rtld + * get.c: use cross-rtld + * ld-do-lookup.h: Add ld-do-lookup.h from glibc + * ld-libs.c: add cross-rtld functionality + * ld-libs.h: ditto + * ld-lookup.c: ditto + * ld-lookup64.c: ditto + * main.c: Add rtld option + * prelink.h: add extern rtld variable + +2006-08-09 CodeSourcery, LLC. + + * main.c: if we modified /sbin/init, re-run init + +2006-08-08 CodeSourcery, LLC. + + * arch-arm.c: add ARM EABI support, dynamic_linker_alt + * src/dso.c: STT_ARM_TFUNC support + * src/get.c: ld-linux.so.3 to the list of ldso names + +2006-08-08 CodeSourcery, LLC. + + * gather.c: add new dynamic_linker_alt + * prelink.h: ditto + +2006-08-08 MontaVista Software, Inc. + + * main.c: Add relative sysroot support + +2006-08-08 Montavista Software, Inc. + + * Makefile.am: Add function wrapper support for sysroots + * main.c: add --root option + * cache.c, doit.c, dso.c, execstack.c, gather.c, get.c, + prelink.h, undoall.c, verify.c: Add functional wrappers for sysroot + * wrap-file.c: add function wrapper definitions + +2006-07-28 Alexandre Oliva <aoliva@redhat.com> + + * src/cache.c: Avoid SEGFAULT when sorting cache entries (#197451) + +2006-07-21 MontaVista Software, Inc. + + * prelink.c: add PRELINK_TIMESTAMP support + +2006-07-21 MontaVista Software, Inc. + + * dso.c: Don't adjust reloc for debug info + +2006-06-30 Mark Hatle <mark.hatle@windriver.com> + + * src/elf.h: Make available the elf.h file from glibc 2.3.6 + +2006-06-10 MontaVista Software, Inc. + + * arch-sh.c: Fix R_SH_RELATIVE endian swap problem, + change max page size + diff --git a/trunk/INSTALL b/trunk/INSTALL new file mode 100644 index 0000000..b42a17a --- /dev/null +++ b/trunk/INSTALL @@ -0,0 +1,182 @@ +Basic Installation +================== + + These are generic installation instructions. + + The `configure' shell script attempts to guess correct values for +various system-dependent variables used during compilation. It uses +those values to create a `Makefile' in each directory of the package. +It may also create one or more `.h' files containing system-dependent +definitions. Finally, it creates a shell script `config.status' that +you can run in the future to recreate the current configuration, a file +`config.cache' that saves the results of its tests to speed up +reconfiguring, and a file `config.log' containing compiler output +(useful mainly for debugging `configure'). + + If you need to do unusual things to compile the package, please try +to figure out how `configure' could check whether to do them, and mail +diffs or instructions to the address given in the `README' so they can +be considered for the next release. If at some point `config.cache' +contains results you don't want to keep, you may remove or edit it. + + The file `configure.in' is used to create `configure' by a program +called `autoconf'. You only need `configure.in' if you want to change +it or regenerate `configure' using a newer version of `autoconf'. + +The simplest way to compile this package is: + + 1. `cd' to the directory containing the package's source code and type + `./configure' to configure the package for your system. If you're + using `csh' on an old version of System V, you might need to type + `sh ./configure' instead to prevent `csh' from trying to execute + `configure' itself. + + Running `configure' takes awhile. While running, it prints some + messages telling which features it is checking for. + + 2. Type `make' to compile the package. + + 3. Optionally, type `make check' to run any self-tests that come with + the package. + + 4. Type `make install' to install the programs and any data files and + documentation. + + 5. You can remove the program binaries and object files from the + source code directory by typing `make clean'. To also remove the + files that `configure' created (so you can compile the package for + a different kind of computer), type `make distclean'. There is + also a `make maintainer-clean' target, but that is intended mainly + for the package's developers. If you use it, you may have to get + all sorts of other programs in order to regenerate files that came + with the distribution. + +Compilers and Options +===================== + + Some systems require unusual options for compilation or linking that +the `configure' script does not know about. You can give `configure' +initial values for variables by setting them in the environment. Using +a Bourne-compatible shell, you can do that on the command line like +this: + CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure + +Or on systems that have the `env' program, you can do it like this: + env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure + +Compiling For Multiple Architectures +==================================== + + You can compile the package for more than one kind of computer at the +same time, by placing the object files for each architecture in their +own directory. To do this, you must use a version of `make' that +supports the `VPATH' variable, such as GNU `make'. `cd' to the +directory where you want the object files and executables to go and run +the `configure' script. `configure' automatically checks for the +source code in the directory that `configure' is in and in `..'. + + If you have to use a `make' that does not supports the `VPATH' +variable, you have to compile the package for one architecture at a time +in the source code directory. After you have installed the package for +one architecture, use `make distclean' before reconfiguring for another +architecture. + +Installation Names +================== + + By default, `make install' will install the package's files in +`/usr/local/bin', `/usr/local/man', etc. You can specify an +installation prefix other than `/usr/local' by giving `configure' the +option `--prefix=PATH'. + + You can specify separate installation prefixes for +architecture-specific files and architecture-independent files. If you +give `configure' the option `--exec-prefix=PATH', the package will use +PATH as the prefix for installing programs and libraries. +Documentation and other data files will still use the regular prefix. + + In addition, if you use an unusual directory layout you can give +options like `--bindir=PATH' to specify different values for particular +kinds of files. Run `configure --help' for a list of the directories +you can set and what kinds of files go in them. + + If the package supports it, you can cause programs to be installed +with an extra prefix or suffix on their names by giving `configure' the +option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. + +Optional Features +================= + + Some packages pay attention to `--enable-FEATURE' options to +`configure', where FEATURE indicates an optional part of the package. +They may also pay attention to `--with-PACKAGE' options, where PACKAGE +is something like `gnu-as' or `x' (for the X Window System). The +`README' should mention any `--enable-' and `--with-' options that the +package recognizes. + + For packages that use the X Window System, `configure' can usually +find the X include and library files automatically, but if it doesn't, +you can use the `configure' options `--x-includes=DIR' and +`--x-libraries=DIR' to specify their locations. + +Specifying the System Type +========================== + + There may be some features `configure' can not figure out +automatically, but needs to determine by the type of host the package +will run on. Usually `configure' can figure that out, but if it prints +a message saying it can not guess the host type, give it the +`--host=TYPE' option. TYPE can either be a short name for the system +type, such as `sun4', or a canonical name with three fields: + CPU-COMPANY-SYSTEM + +See the file `config.sub' for the possible values of each field. If +`config.sub' isn't included in this package, then this package doesn't +need to know the host type. + + If you are building compiler tools for cross-compiling, you can also +use the `--target=TYPE' option to select the type of system they will +produce code for and the `--build=TYPE' option to select the type of +system on which you are compiling the package. + +Sharing Defaults +================ + + If you want to set default values for `configure' scripts to share, +you can create a site shell script called `config.site' that gives +default values for variables like `CC', `cache_file', and `prefix'. +`configure' looks for `PREFIX/share/config.site' if it exists, then +`PREFIX/etc/config.site' if it exists. Or, you can set the +`CONFIG_SITE' environment variable to the location of the site script. +A warning: not all `configure' scripts look for a site script. + +Operation Controls +================== + + `configure' recognizes the following options to control how it +operates. + +`--cache-file=FILE' + Use and save the results of the tests in FILE instead of + `./config.cache'. Set FILE to `/dev/null' to disable caching, for + debugging `configure'. + +`--help' + Print a summary of the options to `configure', and exit. + +`--quiet' +`--silent' +`-q' + Do not print messages saying which checks are being made. To + suppress all normal output, redirect it to `/dev/null' (any error + messages will still be shown). + +`--srcdir=DIR' + Look for the package's source code in directory DIR. Usually + `configure' can determine that directory automatically. + +`--version' + Print the version of Autoconf used to generate the `configure' + script, and exit. + +`configure' also accepts some other, not widely useful, options. diff --git a/trunk/Makefile.am b/trunk/Makefile.am new file mode 100644 index 0000000..5a50830 --- /dev/null +++ b/trunk/Makefile.am @@ -0,0 +1,12 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu +MAINT_CHARSET = latin1 + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = gelfx gelfx32 gelf src patches doc testsuite + +# Tell version 3.79 and up of GNU make to not build goals in this +# directory in parallel. +.NOTPARALLEL: diff --git a/trunk/Makefile.in b/trunk/Makefile.in new file mode 100644 index 0000000..22ab2b4 --- /dev/null +++ b/trunk/Makefile.in @@ -0,0 +1,456 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = . + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu +MAINT_CHARSET = latin1 + +ACLOCAL_AMFLAGS = -I m4 + +SUBDIRS = gelfx gelfx32 gelf src patches doc testsuite +subdir = . +ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +RECURSIVE_TARGETS = info-recursive dvi-recursive install-info-recursive \ + uninstall-info-recursive all-recursive install-data-recursive \ + install-exec-recursive installdirs-recursive install-recursive \ + uninstall-recursive check-recursive installcheck-recursive +DIST_COMMON = README AUTHORS COPYING ChangeLog INSTALL Makefile.am \ + Makefile.in NEWS THANKS TODO aclocal.m4 config.guess \ + config.h.in config.sub configure configure.in depcomp \ + install-sh ltconfig ltmain.sh missing mkinstalldirs +DIST_SUBDIRS = $(SUBDIRS) +all: config.h + $(MAKE) $(AM_MAKEFLAGS) all-recursive + +.SUFFIXES: + +am__CONFIG_DISTCLEAN_FILES = config.status config.cache config.log \ + configure.lineno +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $@ $(am__depfiles_maybe) + +$(top_builddir)/config.status: $(srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) + $(SHELL) ./config.status --recheck +$(srcdir)/configure: $(srcdir)/configure.in $(ACLOCAL_M4) $(CONFIGURE_DEPENDENCIES) + cd $(srcdir) && $(AUTOCONF) + +$(ACLOCAL_M4): configure.in m4/libelf.m4 + cd $(srcdir) && $(ACLOCAL) $(ACLOCAL_AMFLAGS) + +config.h: stamp-h1 + @if test ! -f $@; then \ + rm -f stamp-h1; \ + $(MAKE) stamp-h1; \ + else :; fi + +stamp-h1: $(srcdir)/config.h.in $(top_builddir)/config.status + @rm -f stamp-h1 + cd $(top_builddir) && $(SHELL) ./config.status config.h + +$(srcdir)/config.h.in: $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOHEADER) + touch $(srcdir)/config.h.in + +distclean-hdr: + -rm -f config.h stamp-h1 + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +# This directory's subdirectories are mostly independent; you can cd +# into them and run `make' without going through this Makefile. +# To change the values of `make' variables: instead of editing Makefiles, +# (1) if the variable is set in `config.status', edit `config.status' +# (which will cause the Makefiles to be regenerated when you run `make'); +# (2) otherwise, pass the desired values on the `make' command line. +$(RECURSIVE_TARGETS): + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + target=`echo $@ | sed s/-recursive//`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + dot_seen=yes; \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done; \ + if test "$$dot_seen" = "no"; then \ + $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \ + fi; test -z "$$fail" + +mostlyclean-recursive clean-recursive distclean-recursive \ +maintainer-clean-recursive: + @set fnord $$MAKEFLAGS; amf=$$2; \ + dot_seen=no; \ + case "$@" in \ + distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \ + *) list='$(SUBDIRS)' ;; \ + esac; \ + rev=''; for subdir in $$list; do \ + if test "$$subdir" = "."; then :; else \ + rev="$$subdir $$rev"; \ + fi; \ + done; \ + rev="$$rev ."; \ + target=`echo $@ | sed s/-recursive//`; \ + for subdir in $$rev; do \ + echo "Making $$target in $$subdir"; \ + if test "$$subdir" = "."; then \ + local_target="$$target-am"; \ + else \ + local_target="$$target"; \ + fi; \ + (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \ + || case "$$amf" in *=*) exit 1;; *k*) fail=yes;; *) exit 1;; esac; \ + done && test -z "$$fail" +tags-recursive: + list='$(SUBDIRS)'; for subdir in $$list; do \ + test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \ + done + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: tags-recursive $(HEADERS) $(SOURCES) config.h.in $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -f $$subdir/TAGS && tags="$$tags -i $$here/$$subdir/TAGS"; \ + fi; \ + done; \ + list='$(SOURCES) $(HEADERS) config.h.in $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = . +distdir = $(PACKAGE)-$(VERSION) + +am__remove_distdir = \ + { test ! -d $(distdir) \ + || { find $(distdir) -type d ! -perm -200 -exec chmod u+w {} ';' \ + && rm -fr $(distdir); }; } + +GZIP_ENV = --best +distcleancheck_listfiles = find . -type f -print + +distdir: $(DISTFILES) + $(am__remove_distdir) + mkdir $(distdir) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done + list='$(SUBDIRS)'; for subdir in $$list; do \ + if test "$$subdir" = .; then :; else \ + test -d $(distdir)/$$subdir \ + || mkdir $(distdir)/$$subdir \ + || exit 1; \ + (cd $$subdir && \ + $(MAKE) $(AM_MAKEFLAGS) \ + top_distdir="$(top_distdir)" \ + distdir=../$(distdir)/$$subdir \ + distdir) \ + || exit 1; \ + fi; \ + done + -find $(distdir) -type d ! -perm -777 -exec chmod a+rwx {} \; -o \ + ! -type d ! -perm -444 -links 1 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -400 -exec chmod a+r {} \; -o \ + ! -type d ! -perm -444 -exec $(SHELL) $(install_sh) -c -m a+r {} {} \; \ + || chmod -R a+r $(distdir) +dist-gzip: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +dist dist-all: distdir + $(AMTAR) chof - $(distdir) | GZIP=$(GZIP_ENV) gzip -c >$(distdir).tar.gz + $(am__remove_distdir) + +# This target untars the dist file and tries a VPATH configuration. Then +# it guarantees that the distribution is self-contained by making another +# tarfile. +distcheck: dist + $(am__remove_distdir) + GZIP=$(GZIP_ENV) gunzip -c $(distdir).tar.gz | $(AMTAR) xf - + chmod -R a-w $(distdir); chmod a+w $(distdir) + mkdir $(distdir)/=build + mkdir $(distdir)/=inst + chmod a-w $(distdir) + dc_install_base=`$(am__cd) $(distdir)/=inst && pwd` \ + && cd $(distdir)/=build \ + && ../configure --srcdir=.. --prefix=$$dc_install_base \ + $(DISTCHECK_CONFIGURE_FLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) \ + && $(MAKE) $(AM_MAKEFLAGS) dvi \ + && $(MAKE) $(AM_MAKEFLAGS) check \ + && $(MAKE) $(AM_MAKEFLAGS) install \ + && $(MAKE) $(AM_MAKEFLAGS) installcheck \ + && $(MAKE) $(AM_MAKEFLAGS) uninstall \ + && (test `find $$dc_install_base -type f -print | wc -l` -le 1 \ + || { echo "ERROR: files left after uninstall:" ; \ + find $$dc_install_base -type f -print ; \ + exit 1; } >&2 ) \ + && $(MAKE) $(AM_MAKEFLAGS) dist-gzip \ + && rm -f $(distdir).tar.gz \ + && $(MAKE) $(AM_MAKEFLAGS) distcleancheck + $(am__remove_distdir) + @echo "$(distdir).tar.gz is ready for distribution" | \ + sed 'h;s/./=/g;p;x;p;x' +distcleancheck: distclean + if test '$(srcdir)' = . ; then \ + echo "ERROR: distcleancheck can only run from a VPATH build" ; \ + exit 1 ; \ + fi + test `$(distcleancheck_listfiles) | wc -l` -eq 0 \ + || { echo "ERROR: files left after distclean:" ; \ + $(distcleancheck_listfiles) ; \ + exit 1; } >&2 +check-am: all-am +check: check-recursive +all-am: Makefile config.h +installdirs: installdirs-recursive +installdirs-am: + +install: install-recursive +install-exec: install-exec-recursive +install-data: install-data-recursive +uninstall: uninstall-recursive + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-recursive +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-recursive + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) +distclean-am: clean-am distclean-generic distclean-hdr distclean-libtool \ + distclean-tags + +dvi: dvi-recursive + +dvi-am: + +info: info-recursive + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-recursive + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-recursive + -rm -f $(am__CONFIG_DISTCLEAN_FILES) + -rm -rf autom4te.cache +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-recursive + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +uninstall-info: uninstall-info-recursive + +.PHONY: $(RECURSIVE_TARGETS) GTAGS all all-am check check-am clean \ + clean-generic clean-libtool clean-recursive dist dist-all \ + dist-gzip distcheck distclean distclean-generic distclean-hdr \ + distclean-libtool distclean-recursive distclean-tags \ + distcleancheck distdir dvi dvi-am dvi-recursive info info-am \ + info-recursive install install-am install-data install-data-am \ + install-data-recursive install-exec install-exec-am \ + install-exec-recursive install-info install-info-am \ + install-info-recursive install-man install-recursive \ + install-strip installcheck installcheck-am installdirs \ + installdirs-am installdirs-recursive maintainer-clean \ + maintainer-clean-generic maintainer-clean-recursive mostlyclean \ + mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \ + tags tags-recursive uninstall uninstall-am uninstall-info-am \ + uninstall-info-recursive uninstall-recursive + + +# Tell version 3.79 and up of GNU make to not build goals in this +# directory in parallel. +.NOTPARALLEL: +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/NEWS b/trunk/NEWS new file mode 100644 index 0000000..c36e768 --- /dev/null +++ b/trunk/NEWS @@ -0,0 +1 @@ +No news yet. diff --git a/trunk/README b/trunk/README new file mode 100644 index 0000000..b6dc3ba --- /dev/null +++ b/trunk/README @@ -0,0 +1 @@ +ELF prelinking utility to speed up dynamic linking. diff --git a/trunk/THANKS b/trunk/THANKS new file mode 100644 index 0000000..9f42254 --- /dev/null +++ b/trunk/THANKS @@ -0,0 +1 @@ +We'll see. diff --git a/trunk/TODO b/trunk/TODO new file mode 100644 index 0000000..0a3d072 --- /dev/null +++ b/trunk/TODO @@ -0,0 +1,7 @@ +- sparse files +- security audit: + - should we only limit prelinking in non-world writeable directories +- more ports +- hack support for multi-ABI arches +- more testing +- some more C++ optimizations diff --git a/trunk/aclocal.m4 b/trunk/aclocal.m4 new file mode 100644 index 0000000..a357ef7 --- /dev/null +++ b/trunk/aclocal.m4 @@ -0,0 +1,6833 @@ +# aclocal.m4 generated automatically by aclocal 1.6.3 -*- Autoconf -*- + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This file is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +# Like AC_CONFIG_HEADER, but automatically create stamp file. -*- Autoconf -*- + +# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_PREREQ([2.52]) + +# serial 6 + +# When config.status generates a header, we must update the stamp-h file. +# This file resides in the same directory as the config header +# that is generated. We must strip everything past the first ":", +# and everything past the last "/". + +# _AM_DIRNAME(PATH) +# ----------------- +# Like AS_DIRNAME, only do it during macro expansion +AC_DEFUN([_AM_DIRNAME], + [m4_if(regexp([$1], [^.*[^/]//*[^/][^/]*/*$]), -1, + m4_if(regexp([$1], [^//\([^/]\|$\)]), -1, + m4_if(regexp([$1], [^/.*]), -1, + [.], + patsubst([$1], [^\(/\).*], [\1])), + patsubst([$1], [^\(//\)\([^/].*\|$\)], [\1])), + patsubst([$1], [^\(.*[^/]\)//*[^/][^/]*/*$], [\1]))[]dnl +])# _AM_DIRNAME + + +# The stamp files are numbered to have different names. +# We could number them on a directory basis, but that's additional +# complications, let's have a unique counter. +m4_define([_AM_STAMP_Count], [0]) + + +# _AM_STAMP(HEADER) +# ----------------- +# The name of the stamp file for HEADER. +AC_DEFUN([_AM_STAMP], +[m4_define([_AM_STAMP_Count], m4_incr(_AM_STAMP_Count))dnl +AS_ESCAPE(_AM_DIRNAME(patsubst([$1], + [:.*])))/stamp-h[]_AM_STAMP_Count]) + + +# _AM_CONFIG_HEADER(HEADER[:SOURCES], COMMANDS, INIT-COMMANDS) +# ------------------------------------------------------------ +# We used to try to get a real timestamp in stamp-h. But the fear is that +# that will cause unnecessary cvs conflicts. +AC_DEFUN([_AM_CONFIG_HEADER], +[# Add the stamp file to the list of files AC keeps track of, +# along with our hook. +AC_CONFIG_HEADERS([$1], + [# update the timestamp +echo 'timestamp for $1' >"_AM_STAMP([$1])" +$2], + [$3]) +])# _AM_CONFIG_HEADER + + +# AM_CONFIG_HEADER(HEADER[:SOURCES]..., COMMANDS, INIT-COMMANDS) +# -------------------------------------------------------------- +AC_DEFUN([AM_CONFIG_HEADER], +[AC_FOREACH([_AM_File], [$1], [_AM_CONFIG_HEADER(_AM_File, [$2], [$3])]) +])# AM_CONFIG_HEADER + +# Do all the work for Automake. -*- Autoconf -*- + +# This macro actually does too much some checks are only needed if +# your package does certain things. But this isn't really a big deal. + +# Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 8 + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + +AC_PREREQ([2.52]) + +# Autoconf 2.50 wants to disallow AM_ names. We explicitly allow +# the ones we care about. +m4_pattern_allow([^AM_[A-Z]+FLAGS$])dnl + +# AM_INIT_AUTOMAKE(PACKAGE, VERSION, [NO-DEFINE]) +# AM_INIT_AUTOMAKE([OPTIONS]) +# ----------------------------------------------- +# The call with PACKAGE and VERSION arguments is the old style +# call (pre autoconf-2.50), which is being phased out. PACKAGE +# and VERSION should now be passed to AC_INIT and removed from +# the call to AM_INIT_AUTOMAKE. +# We support both call styles for the transition. After +# the next Automake release, Autoconf can make the AC_INIT +# arguments mandatory, and then we can depend on a new Autoconf +# release and drop the old call support. +AC_DEFUN([AM_INIT_AUTOMAKE], +[AC_REQUIRE([AM_SET_CURRENT_AUTOMAKE_VERSION])dnl + AC_REQUIRE([AC_PROG_INSTALL])dnl +# test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + AC_MSG_ERROR([source directory already configured; run "make distclean" there first]) +fi + +# Define the identity of the package. +dnl Distinguish between old-style and new-style calls. +m4_ifval([$2], +[m4_ifval([$3], [_AM_SET_OPTION([no-define])])dnl + AC_SUBST([PACKAGE], [$1])dnl + AC_SUBST([VERSION], [$2])], +[_AM_SET_OPTIONS([$1])dnl + AC_SUBST([PACKAGE], [AC_PACKAGE_TARNAME])dnl + AC_SUBST([VERSION], [AC_PACKAGE_VERSION])])dnl + +_AM_IF_OPTION([no-define],, +[AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE", [Name of package]) + AC_DEFINE_UNQUOTED(VERSION, "$VERSION", [Version number of package])])dnl + +# Some tools Automake needs. +AC_REQUIRE([AM_SANITY_CHECK])dnl +AC_REQUIRE([AC_ARG_PROGRAM])dnl +AM_MISSING_PROG(ACLOCAL, aclocal-${am__api_version}) +AM_MISSING_PROG(AUTOCONF, autoconf) +AM_MISSING_PROG(AUTOMAKE, automake-${am__api_version}) +AM_MISSING_PROG(AUTOHEADER, autoheader) +AM_MISSING_PROG(MAKEINFO, makeinfo) +AM_MISSING_PROG(AMTAR, tar) +AM_PROG_INSTALL_SH +AM_PROG_INSTALL_STRIP +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. +AC_REQUIRE([AC_PROG_AWK])dnl +AC_REQUIRE([AC_PROG_MAKE_SET])dnl + +_AM_IF_OPTION([no-dependencies],, +[AC_PROVIDE_IFELSE([AC_PROG_][CC], + [_AM_DEPENDENCIES(CC)], + [define([AC_PROG_][CC], + defn([AC_PROG_][CC])[_AM_DEPENDENCIES(CC)])])dnl +AC_PROVIDE_IFELSE([AC_PROG_][CXX], + [_AM_DEPENDENCIES(CXX)], + [define([AC_PROG_][CXX], + defn([AC_PROG_][CXX])[_AM_DEPENDENCIES(CXX)])])dnl +]) +]) + +# Copyright 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA + +# AM_AUTOMAKE_VERSION(VERSION) +# ---------------------------- +# Automake X.Y traces this macro to ensure aclocal.m4 has been +# generated from the m4 files accompanying Automake X.Y. +AC_DEFUN([AM_AUTOMAKE_VERSION],[am__api_version="1.6"]) + +# AM_SET_CURRENT_AUTOMAKE_VERSION +# ------------------------------- +# Call AM_AUTOMAKE_VERSION so it can be traced. +# This function is AC_REQUIREd by AC_INIT_AUTOMAKE. +AC_DEFUN([AM_SET_CURRENT_AUTOMAKE_VERSION], + [AM_AUTOMAKE_VERSION([1.6.3])]) + +# Helper functions for option handling. -*- Autoconf -*- + +# Copyright 2001, 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# _AM_MANGLE_OPTION(NAME) +# ----------------------- +AC_DEFUN([_AM_MANGLE_OPTION], +[[_AM_OPTION_]m4_bpatsubst($1, [[^a-zA-Z0-9_]], [_])]) + +# _AM_SET_OPTION(NAME) +# ------------------------------ +# Set option NAME. Presently that only means defining a flag for this option. +AC_DEFUN([_AM_SET_OPTION], +[m4_define(_AM_MANGLE_OPTION([$1]), 1)]) + +# _AM_SET_OPTIONS(OPTIONS) +# ---------------------------------- +# OPTIONS is a space-separated list of Automake options. +AC_DEFUN([_AM_SET_OPTIONS], +[AC_FOREACH([_AM_Option], [$1], [_AM_SET_OPTION(_AM_Option)])]) + +# _AM_IF_OPTION(OPTION, IF-SET, [IF-NOT-SET]) +# ------------------------------------------- +# Execute IF-SET if OPTION is set, IF-NOT-SET otherwise. +AC_DEFUN([_AM_IF_OPTION], +[m4_ifset(_AM_MANGLE_OPTION([$1]), [$2], [$3])]) + +# +# Check to make sure that the build environment is sane. +# + +# Copyright 1996, 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_SANITY_CHECK +# --------------- +AC_DEFUN([AM_SANITY_CHECK], +[AC_MSG_CHECKING([whether build environment is sane]) +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$[*]" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$[*]" != "X $srcdir/configure conftest.file" \ + && test "$[*]" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + AC_MSG_ERROR([ls -t appears to fail. Make sure there is not a broken +alias in your environment]) + fi + + test "$[2]" = conftest.file + ) +then + # Ok. + : +else + AC_MSG_ERROR([newly created file is older than distributed files! +Check your system clock]) +fi +AC_MSG_RESULT(yes)]) + +# -*- Autoconf -*- + + +# Copyright 1997, 1999, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 3 + +# AM_MISSING_PROG(NAME, PROGRAM) +# ------------------------------ +AC_DEFUN([AM_MISSING_PROG], +[AC_REQUIRE([AM_MISSING_HAS_RUN]) +$1=${$1-"${am_missing_run}$2"} +AC_SUBST($1)]) + + +# AM_MISSING_HAS_RUN +# ------------------ +# Define MISSING if not defined so far and test if it supports --run. +# If it does, set am_missing_run to use it, otherwise, to nothing. +AC_DEFUN([AM_MISSING_HAS_RUN], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + AC_MSG_WARN([`missing' script is too old or missing]) +fi +]) + +# AM_AUX_DIR_EXPAND + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# For projects using AC_CONFIG_AUX_DIR([foo]), Autoconf sets +# $ac_aux_dir to `$srcdir/foo'. In other projects, it is set to +# `$srcdir', `$srcdir/..', or `$srcdir/../..'. +# +# Of course, Automake must honor this variable whenever it calls a +# tool from the auxiliary directory. The problem is that $srcdir (and +# therefore $ac_aux_dir as well) can be either absolute or relative, +# depending on how configure is run. This is pretty annoying, since +# it makes $ac_aux_dir quite unusable in subdirectories: in the top +# source directory, any form will work fine, but in subdirectories a +# relative path needs to be adjusted first. +# +# $ac_aux_dir/missing +# fails when called from a subdirectory if $ac_aux_dir is relative +# $top_srcdir/$ac_aux_dir/missing +# fails if $ac_aux_dir is absolute, +# fails when called from a subdirectory in a VPATH build with +# a relative $ac_aux_dir +# +# The reason of the latter failure is that $top_srcdir and $ac_aux_dir +# are both prefixed by $srcdir. In an in-source build this is usually +# harmless because $srcdir is `.', but things will broke when you +# start a VPATH build or use an absolute $srcdir. +# +# So we could use something similar to $top_srcdir/$ac_aux_dir/missing, +# iff we strip the leading $srcdir from $ac_aux_dir. That would be: +# am_aux_dir='\$(top_srcdir)/'`expr "$ac_aux_dir" : "$srcdir//*\(.*\)"` +# and then we would define $MISSING as +# MISSING="\${SHELL} $am_aux_dir/missing" +# This will work as long as MISSING is not called from configure, because +# unfortunately $(top_srcdir) has no meaning in configure. +# However there are other variables, like CC, which are often used in +# configure, and could therefore not use this "fixed" $ac_aux_dir. +# +# Another solution, used here, is to always expand $ac_aux_dir to an +# absolute PATH. The drawback is that using absolute paths prevent a +# configured tree to be moved without reconfiguration. + +# Rely on autoconf to set up CDPATH properly. +AC_PREREQ([2.50]) + +AC_DEFUN([AM_AUX_DIR_EXPAND], [ +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` +]) + +# AM_PROG_INSTALL_SH +# ------------------ +# Define $install_sh. + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +AC_DEFUN([AM_PROG_INSTALL_SH], +[AC_REQUIRE([AM_AUX_DIR_EXPAND])dnl +install_sh=${install_sh-"$am_aux_dir/install-sh"} +AC_SUBST(install_sh)]) + +# AM_PROG_INSTALL_STRIP + +# Copyright 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# One issue with vendor `install' (even GNU) is that you can't +# specify the program used to strip binaries. This is especially +# annoying in cross-compiling environments, where the build's strip +# is unlikely to handle the host's binaries. +# Fortunately install-sh will honor a STRIPPROG variable, so we +# always use install-sh in `make install-strip', and initialize +# STRIPPROG with the value of the STRIP variable (set by the user). +AC_DEFUN([AM_PROG_INSTALL_STRIP], +[AC_REQUIRE([AM_PROG_INSTALL_SH])dnl +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +dnl Don't test for $cross_compiling = yes, because it might be `maybe'. +if test "$cross_compiling" != no; then + AC_CHECK_TOOL([STRIP], [strip], :) +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" +AC_SUBST([INSTALL_STRIP_PROGRAM])]) + +# serial 4 -*- Autoconf -*- + +# Copyright 1999, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + + +# There are a few dirty hacks below to avoid letting `AC_PROG_CC' be +# written in clear, in which case automake, when reading aclocal.m4, +# will think it sees a *use*, and therefore will trigger all it's +# C support machinery. Also note that it means that autoscan, seeing +# CC etc. in the Makefile, will ask for an AC_PROG_CC use... + + + +# _AM_DEPENDENCIES(NAME) +# ---------------------- +# See how the compiler implements dependency checking. +# NAME is "CC", "CXX", "GCJ", or "OBJC". +# We try a few techniques and use that to set a single cache variable. +# +# We don't AC_REQUIRE the corresponding AC_PROG_CC since the latter was +# modified to invoke _AM_DEPENDENCIES(CC); we would have a circular +# dependency, and given that the user is not expected to run this macro, +# just rely on AC_PROG_CC. +AC_DEFUN([_AM_DEPENDENCIES], +[AC_REQUIRE([AM_SET_DEPDIR])dnl +AC_REQUIRE([AM_OUTPUT_DEPENDENCY_COMMANDS])dnl +AC_REQUIRE([AM_MAKE_INCLUDE])dnl +AC_REQUIRE([AM_DEP_TRACK])dnl + +ifelse([$1], CC, [depcc="$CC" am_compiler_list=], + [$1], CXX, [depcc="$CXX" am_compiler_list=], + [$1], OBJC, [depcc="$OBJC" am_compiler_list='gcc3 gcc'], + [$1], GCJ, [depcc="$GCJ" am_compiler_list='gcc3 gcc'], + [depcc="$$1" am_compiler_list=]) + +AC_CACHE_CHECK([dependency style of $depcc], + [am_cv_$1_dependencies_compiler_type], +[if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_$1_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n ['s/^#*\([a-zA-Z0-9]*\))$/\1/p'] < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_$1_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_$1_dependencies_compiler_type=none +fi +]) +AC_SUBST([$1DEPMODE], [depmode=$am_cv_$1_dependencies_compiler_type]) +]) + + +# AM_SET_DEPDIR +# ------------- +# Choose a directory name for dependency files. +# This macro is AC_REQUIREd in _AM_DEPENDENCIES +AC_DEFUN([AM_SET_DEPDIR], +[rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null +AC_SUBST([DEPDIR]) +]) + + +# AM_DEP_TRACK +# ------------ +AC_DEFUN([AM_DEP_TRACK], +[AC_ARG_ENABLE(dependency-tracking, +[ --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors]) +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi +AM_CONDITIONAL([AMDEP], [test "x$enable_dependency_tracking" != xno]) +AC_SUBST([AMDEPBACKSLASH]) +]) + +# Generate code to set up dependency tracking. -*- Autoconf -*- + +# Copyright 1999, 2000, 2001, 2002 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +#serial 2 + +# _AM_OUTPUT_DEPENDENCY_COMMANDS +# ------------------------------ +AC_DEFUN([_AM_OUTPUT_DEPENDENCY_COMMANDS], +[for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`AS_DIRNAME("$mf")` + else + continue + fi + grep '^DEP_FILES *= *[[^ @%:@]]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`AS_DIRNAME(["$file"])` + AS_MKDIR_P([$dirpart/$fdir]) + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done +])# _AM_OUTPUT_DEPENDENCY_COMMANDS + + +# AM_OUTPUT_DEPENDENCY_COMMANDS +# ----------------------------- +# This macro should only be invoked once -- use via AC_REQUIRE. +# +# This code is only required when automatic dependency tracking +# is enabled. FIXME. This creates each `.P' file that we will +# need in order to bootstrap the dependency handling code. +AC_DEFUN([AM_OUTPUT_DEPENDENCY_COMMANDS], +[AC_CONFIG_COMMANDS([depfiles], + [test x"$AMDEP_TRUE" != x"" || _AM_OUTPUT_DEPENDENCY_COMMANDS], + [AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir"]) +]) + +# Copyright 2001 Free Software Foundation, Inc. -*- Autoconf -*- + +# 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, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 2 + +# AM_MAKE_INCLUDE() +# ----------------- +# Check to see how make treats includes. +AC_DEFUN([AM_MAKE_INCLUDE], +[am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +AC_MSG_CHECKING([for style of include used by $am_make]) +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi +AC_SUBST(am__include) +AC_SUBST(am__quote) +AC_MSG_RESULT($_am_result) +rm -f confinc confmf +]) + +# AM_CONDITIONAL -*- Autoconf -*- + +# Copyright 1997, 2000, 2001 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# serial 5 + +AC_PREREQ(2.52) + +# AM_CONDITIONAL(NAME, SHELL-CONDITION) +# ------------------------------------- +# Define a conditional. +AC_DEFUN([AM_CONDITIONAL], +[ifelse([$1], [TRUE], [AC_FATAL([$0: invalid condition: $1])], + [$1], [FALSE], [AC_FATAL([$0: invalid condition: $1])])dnl +AC_SUBST([$1_TRUE]) +AC_SUBST([$1_FALSE]) +if $2; then + $1_TRUE= + $1_FALSE='#' +else + $1_TRUE='#' + $1_FALSE= +fi +AC_CONFIG_COMMANDS_PRE( +[if test -z "${$1_TRUE}" && test -z "${$1_FALSE}"; then + AC_MSG_ERROR([conditional \"$1\" was never defined. +Usually this means the macro was only invoked conditionally.]) +fi])]) + +# libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- + +# serial 47 AC_PROG_LIBTOOL + + +# AC_PROVIDE_IFELSE(MACRO-NAME, IF-PROVIDED, IF-NOT-PROVIDED) +# ----------------------------------------------------------- +# If this macro is not defined by Autoconf, define it here. +m4_ifdef([AC_PROVIDE_IFELSE], + [], + [m4_define([AC_PROVIDE_IFELSE], + [m4_ifdef([AC_PROVIDE_$1], + [$2], [$3])])]) + + +# AC_PROG_LIBTOOL +# --------------- +AC_DEFUN([AC_PROG_LIBTOOL], +[AC_REQUIRE([_AC_PROG_LIBTOOL])dnl +dnl If AC_PROG_CXX has already been expanded, run AC_LIBTOOL_CXX +dnl immediately, otherwise, hook it in at the end of AC_PROG_CXX. + AC_PROVIDE_IFELSE([AC_PROG_CXX], + [AC_LIBTOOL_CXX], + [define([AC_PROG_CXX], defn([AC_PROG_CXX])[AC_LIBTOOL_CXX + ])]) +dnl And a similar setup for Fortran 77 support + AC_PROVIDE_IFELSE([AC_PROG_F77], + [AC_LIBTOOL_F77], + [define([AC_PROG_F77], defn([AC_PROG_F77])[AC_LIBTOOL_F77 +])]) + +dnl Quote A][M_PROG_GCJ so that aclocal doesn't bring it in needlessly. +dnl If either AC_PROG_GCJ or A][M_PROG_GCJ have already been expanded, run +dnl AC_LIBTOOL_GCJ immediately, otherwise, hook it in at the end of both. + AC_PROVIDE_IFELSE([AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ], + [AC_LIBTOOL_GCJ], + [ifdef([AC_PROG_GCJ], + [define([AC_PROG_GCJ], defn([AC_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([A][M_PROG_GCJ], + [define([A][M_PROG_GCJ], defn([A][M_PROG_GCJ])[AC_LIBTOOL_GCJ])]) + ifdef([LT_AC_PROG_GCJ], + [define([LT_AC_PROG_GCJ], + defn([LT_AC_PROG_GCJ])[AC_LIBTOOL_GCJ])])])]) +])])# AC_PROG_LIBTOOL + + +# _AC_PROG_LIBTOOL +# ---------------- +AC_DEFUN([_AC_PROG_LIBTOOL], +[AC_REQUIRE([AC_LIBTOOL_SETUP])dnl +AC_BEFORE([$0],[AC_LIBTOOL_CXX])dnl +AC_BEFORE([$0],[AC_LIBTOOL_F77])dnl +AC_BEFORE([$0],[AC_LIBTOOL_GCJ])dnl + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' +AC_SUBST(LIBTOOL)dnl + +# Prevent multiple expansion +define([AC_PROG_LIBTOOL], []) +])# _AC_PROG_LIBTOOL + + +# AC_LIBTOOL_SETUP +# ---------------- +AC_DEFUN([AC_LIBTOOL_SETUP], +[AC_PREREQ(2.50)dnl +AC_REQUIRE([AC_ENABLE_SHARED])dnl +AC_REQUIRE([AC_ENABLE_STATIC])dnl +AC_REQUIRE([AC_ENABLE_FAST_INSTALL])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_LD])dnl +AC_REQUIRE([AC_PROG_LD_RELOAD_FLAG])dnl +AC_REQUIRE([AC_PROG_NM])dnl + +AC_REQUIRE([AC_PROG_LN_S])dnl +AC_REQUIRE([AC_DEPLIBS_CHECK_METHOD])dnl +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! +AC_REQUIRE([AC_OBJEXT])dnl +AC_REQUIRE([AC_EXEEXT])dnl +dnl + +AC_LIBTOOL_SYS_MAX_CMD_LEN +AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +AC_LIBTOOL_OBJDIR + +AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +_LT_AC_PROG_ECHO_BACKSLASH + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +[sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g'] + +# Same as above, but do not quote variable references. +[double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g'] + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +AC_CHECK_TOOL(AR, ar, false) +AC_CHECK_TOOL(RANLIB, ranlib, :) +AC_CHECK_TOOL(STRIP, strip, :) + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + AC_PATH_MAGIC + fi + ;; +esac + +AC_PROVIDE_IFELSE([AC_LIBTOOL_DLOPEN], enable_dlopen=yes, enable_dlopen=no) +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +enable_win32_dll=yes, enable_win32_dll=no) + +AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +AC_ARG_WITH([pic], + [AC_HELP_STRING([--with-pic], + [try to use only PIC/non-PIC objects @<:@default=use both@:>@])], + [pic_mode="$withval"], + [pic_mode=default]) +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +AC_LIBTOOL_LANG_C_CONFIG +_LT_AC_TAGCONFIG +])# AC_LIBTOOL_SETUP + + +# _LT_AC_SYS_COMPILER +# ------------------- +AC_DEFUN([_LT_AC_SYS_COMPILER], +[AC_REQUIRE([AC_PROG_CC])dnl + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC +])# _LT_AC_SYS_COMPILER + + +# _LT_AC_SYS_LIBPATH_AIX +# ---------------------- +# Links a minimal program and checks the executable +# for the system default hardcoded library path. In most cases, +# this is /usr/lib:/lib, but when the MPI compilers are used +# the location of the communication and MPI libs are included too. +# If we don't find anything, use the default library path according +# to the aix ld manual. +AC_DEFUN([_LT_AC_SYS_LIBPATH_AIX], +[AC_LINK_IFELSE(AC_LANG_PROGRAM,[ +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi],[]) +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi +])# _LT_AC_SYS_LIBPATH_AIX + + +# _LT_AC_SHELL_INIT(ARG) +# ---------------------- +AC_DEFUN([_LT_AC_SHELL_INIT], +[ifdef([AC_DIVERSION_NOTICE], + [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], + [AC_DIVERT_PUSH(NOTICE)]) +$1 +AC_DIVERT_POP +])# _LT_AC_SHELL_INIT + + +# _LT_AC_PROG_ECHO_BACKSLASH +# -------------------------- +# Add some code to the start of the generated configure script which +# will find an echo command which doesn't interpret backslashes. +AC_DEFUN([_LT_AC_PROG_ECHO_BACKSLASH], +[_LT_AC_SHELL_INIT([ +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` + ;; +esac + +echo=${ECHO-echo} +if test "X[$]1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X[$]1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} +fi + +if test "X[$]1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +[$]* +EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL [$]0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL [$]0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "[$]0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" +fi + +AC_SUBST(ECHO) +])])# _LT_AC_PROG_ECHO_BACKSLASH + + +# _LT_AC_LOCK +# ----------- +AC_DEFUN([_LT_AC_LOCK], +[AC_ARG_ENABLE([libtool-lock], + [AC_HELP_STRING([--disable-libtool-lock], + [avoid locking (might break parallel builds)])]) +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + AC_CACHE_CHECK([whether the C compiler needs -belf], lt_cv_cc_needs_belf, + [AC_LANG_PUSH(C) + AC_TRY_LINK([],[],[lt_cv_cc_needs_belf=yes],[lt_cv_cc_needs_belf=no]) + AC_LANG_POP]) + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; +AC_PROVIDE_IFELSE([AC_LIBTOOL_WIN32_DLL], +[*-*-cygwin* | *-*-mingw* | *-*-pw32*) + AC_CHECK_TOOL(DLLTOOL, dlltool, false) + AC_CHECK_TOOL(AS, as, false) + AC_CHECK_TOOL(OBJDUMP, objdump, false) + ;; + ]) +esac + +need_locks="$enable_libtool_lock" + +])# _LT_AC_LOCK + + +# AC_LIBTOOL_COMPILER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [OUTPUT-FILE], [ACTION-SUCCESS], [ACTION-FAILURE]) +# ---------------------------------------------------------------- +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_COMPILER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + ifelse([$4], , [ac_outfile=conftest.$ac_objext], [ac_outfile=$4]) + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$3" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + $2=yes + fi + fi + $rm conftest* +]) + +if test x"[$]$2" = xyes; then + ifelse([$5], , :, [$5]) +else + ifelse([$6], , :, [$6]) +fi +])# AC_LIBTOOL_COMPILER_OPTION + + +# AC_LIBTOOL_LINKER_OPTION(MESSAGE, VARIABLE-NAME, FLAGS, +# [ACTION-SUCCESS], [ACTION-FAILURE]) +# ------------------------------------------------------------ +# Check whether the given compiler option works +AC_DEFUN([AC_LIBTOOL_LINKER_OPTION], +[AC_CACHE_CHECK([$1], [$2], + [$2=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $3" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&AS_MESSAGE_LOG_FD + else + $2=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" +]) + +if test x"[$]$2" = xyes; then + ifelse([$4], , :, [$4]) +else + ifelse([$5], , :, [$5]) +fi +])# AC_LIBTOOL_LINKER_OPTION + + +# AC_LIBTOOL_SYS_MAX_CMD_LEN +# -------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_MAX_CMD_LEN], +[# find the maximum length of command line arguments +AC_MSG_CHECKING([the maximum length of command line arguments]) +AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl + i=0 + testring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL [$]0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring=$testring$testring + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac +]) +if test -n $lt_cv_sys_max_cmd_len ; then + AC_MSG_RESULT($lt_cv_sys_max_cmd_len) +else + AC_MSG_RESULT(none) +fi +])# AC_LIBTOOL_SYS_MAX_CMD_LEN + + +# _LT_AC_CHECK_DLFCN +# -------------------- +AC_DEFUN([_LT_AC_CHECK_DLFCN], +[AC_CHECK_HEADERS(dlfcn.h)dnl +])# _LT_AC_CHECK_DLFCN + + +# _LT_AC_TRY_DLOPEN_SELF (ACTION-IF-TRUE, ACTION-IF-TRUE-W-USCORE, +# ACTION-IF-FALSE, ACTION-IF-CROSS-COMPILING) +# ------------------------------------------------------------------ +AC_DEFUN([_LT_AC_TRY_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "$cross_compiling" = yes; then : + [$4] +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +[#line __oline__ "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +}] +EOF + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) $1 ;; + x$lt_dlneed_uscore) $2 ;; + x$lt_unknown|x*) $3 ;; + esac + else : + # compilation failed + $3 + fi +fi +rm -fr conftest* +])# _LT_AC_TRY_DLOPEN_SELF + + +# AC_LIBTOOL_DLOPEN_SELF +# ------------------- +AC_DEFUN([AC_LIBTOOL_DLOPEN_SELF], +[AC_REQUIRE([_LT_AC_CHECK_DLFCN])dnl +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"],[ + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ]) + ;; + + *) + AC_CHECK_FUNC([shl_load], + [lt_cv_dlopen="shl_load"], + [AC_CHECK_LIB([dld], [shl_load], + [lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld"], + [AC_CHECK_FUNC([dlopen], + [lt_cv_dlopen="dlopen"], + [AC_CHECK_LIB([dl], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl"], + [AC_CHECK_LIB([svld], [dlopen], + [lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld"], + [AC_CHECK_LIB([dld], [dld_link], + [lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld"]) + ]) + ]) + ]) + ]) + ]) + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + AC_CACHE_CHECK([whether a program can dlopen itself], + lt_cv_dlopen_self, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self=yes, lt_cv_dlopen_self=yes, + lt_cv_dlopen_self=no, lt_cv_dlopen_self=cross) + ]) + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + AC_CACHE_CHECK([whether a statically linked program can dlopen itself], + lt_cv_dlopen_self_static, [dnl + _LT_AC_TRY_DLOPEN_SELF( + lt_cv_dlopen_self_static=yes, lt_cv_dlopen_self_static=yes, + lt_cv_dlopen_self_static=no, lt_cv_dlopen_self_static=cross) + ]) + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi +])# AC_LIBTOOL_DLOPEN_SELF + + +# AC_LIBTOOL_PROG_CC_C_O([TAGNAME]) +# --------------------------------- +# Check to see if options -c and -o are simultaneously supported by compiler +AC_DEFUN([AC_LIBTOOL_PROG_CC_C_O], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl +AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)], + [_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&AS_MESSAGE_LOG_FD + echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* +]) +])# AC_LIBTOOL_PROG_CC_C_O + + +# AC_LIBTOOL_SYS_HARD_LINK_LOCKS([TAGNAME]) +# ----------------------------------------- +# Check to see if we can do hard links to lock some files if needed +AC_DEFUN([AC_LIBTOOL_SYS_HARD_LINK_LOCKS], +[AC_REQUIRE([_LT_AC_LOCK])dnl + +hard_links="nottested" +if test "$_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + AC_MSG_CHECKING([if we can lock with hard links]) + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + AC_MSG_RESULT([$hard_links]) + if test "$hard_links" = no; then + AC_MSG_WARN([`$CC' does not support `-c -o', so `make -j' may be unsafe]) + need_locks=warn + fi +else + need_locks=no +fi +])# AC_LIBTOOL_SYS_HARD_LINK_LOCKS + + +# AC_LIBTOOL_OBJDIR +# ----------------- +AC_DEFUN([AC_LIBTOOL_OBJDIR], +[AC_CACHE_CHECK([for objdir], [lt_cv_objdir], +[rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null]) +objdir=$lt_cv_objdir +])# AC_LIBTOOL_OBJDIR + + +# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH([TAGNAME]) +# ---------------------------------------------- +# Check hardcoding attributes. +AC_DEFUN([AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH], +[AC_MSG_CHECKING([how to hardcode library paths into programs]) +_LT_AC_TAGVAR(hardcode_action, $1)= +if test -n "$_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)" || \ + test -n "$_LT_AC_TAGVAR(runpath_var $1)" || \ + test "X$_LT_AC_TAGVAR(hardcode_automatic, $1)"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$_LT_AC_TAGVAR(hardcode_direct, $1)" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1)" != no && + test "$_LT_AC_TAGVAR(hardcode_minus_L, $1)" != no; then + # Linking always hardcodes the temporary library directory. + _LT_AC_TAGVAR(hardcode_action, $1)=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + _LT_AC_TAGVAR(hardcode_action, $1)=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + _LT_AC_TAGVAR(hardcode_action, $1)=unsupported +fi +AC_MSG_RESULT([$_LT_AC_TAGVAR(hardcode_action, $1)]) + +if test "$_LT_AC_TAGVAR(hardcode_action, $1)" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi +])# AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH + + +# AC_LIBTOOL_SYS_LIB_STRIP +# ------------------------ +AC_DEFUN([AC_LIBTOOL_SYS_LIB_STRIP], +[striplib= +old_striplib= +AC_MSG_CHECKING([whether stripping libraries is possible]) +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + AC_MSG_RESULT([yes]) +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + AC_MSG_RESULT([yes]) + else + AC_MSG_RESULT([no]) +fi + ;; + *) + AC_MSG_RESULT([no]) + ;; + esac +fi +])# AC_LIBTOOL_SYS_LIB_STRIP + + +# AC_LIBTOOL_SYS_DYNAMIC_LINKER +# ----------------------------- +# PORTME Fill in your ld.so characteristics +AC_DEFUN([AC_LIBTOOL_SYS_DYNAMIC_LINKER], +[AC_MSG_CHECKING([dynamic linker characteristics]) +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[[01]] | aix4.[[01]].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | [grep ';[c-zC-Z]:/' >/dev/null]; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '[#]line __oline__ "configure"' > conftest.$ac_ext + if AC_TRY_EVAL(ac_compile); then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[[89]] | openbsd2.[[89]].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +AC_MSG_RESULT([$dynamic_linker]) +test "$dynamic_linker" = no && can_build_shared=no +])# AC_LIBTOOL_SYS_DYNAMIC_LINKER + + +# _LT_AC_TAGCONFIG +# ---------------- +AC_DEFUN([_LT_AC_TAGCONFIG], +[AC_ARG_WITH([tags], + [AC_HELP_STRING([--with-tags@<:@=TAGS@:>@], + [include additional configurations @<:@automatic@:>@])], + [tagnames="$withval"]) + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + AC_MSG_WARN([output file `$ofile' does not exist]) + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + AC_MSG_WARN([output file `$ofile' does not look like a libtool script]) + else + AC_MSG_WARN([using `LTCC=$LTCC', extracted from `$ofile']) + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]]::g'` in + "") ;; + *) AC_MSG_ERROR([invalid tag name: $tagname]) + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + AC_MSG_ERROR([tag name \"$tagname\" already exists]) + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && test "X$CXX" != "Xno"; then + AC_LIBTOOL_LANG_CXX_CONFIG + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + AC_LIBTOOL_LANG_F77_CONFIG + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + AC_LIBTOOL_LANG_GCJ_CONFIG + else + tagname="" + fi + ;; + + RC) + AC_LIBTOOL_LANG_RC_CONFIG + ;; + + *) + AC_MSG_ERROR([Unsupported tag name: $tagname]) + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + AC_MSG_ERROR([unable to update list of available tagged configurations.]) + fi +fi +])# _LT_AC_TAGCONFIG + + +# AC_LIBTOOL_DLOPEN +# ----------------- +# enable checks for dlopen support +AC_DEFUN([AC_LIBTOOL_DLOPEN], + [AC_BEFORE([$0],[AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_DLOPEN + + +# AC_LIBTOOL_WIN32_DLL +# -------------------- +# declare package support for building win32 dll's +AC_DEFUN([AC_LIBTOOL_WIN32_DLL], +[AC_BEFORE([$0], [AC_LIBTOOL_SETUP]) +])# AC_LIBTOOL_WIN32_DLL + + +# AC_ENABLE_SHARED([DEFAULT]) +# --------------------------- +# implement the --enable-shared flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_SHARED], +[define([AC_ENABLE_SHARED_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([shared], + [AC_HELP_STRING([--enable-shared@<:@=PKGS@:>@], + [build shared libraries @<:@default=]AC_ENABLE_SHARED_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_shared=]AC_ENABLE_SHARED_DEFAULT) +])# AC_ENABLE_SHARED + + +# AC_DISABLE_SHARED +# ----------------- +#- set the default shared flag to --disable-shared +AC_DEFUN([AC_DISABLE_SHARED], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_SHARED(no) +])# AC_DISABLE_SHARED + + +# AC_ENABLE_STATIC([DEFAULT]) +# --------------------------- +# implement the --enable-static flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_STATIC], +[define([AC_ENABLE_STATIC_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([static], + [AC_HELP_STRING([--enable-static@<:@=PKGS@:>@], + [build static libraries @<:@default=]AC_ENABLE_STATIC_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_static=]AC_ENABLE_STATIC_DEFAULT) +])# AC_ENABLE_STATIC + + +# AC_DISABLE_STATIC +# ----------------- +# set the default static flag to --disable-static +AC_DEFUN([AC_DISABLE_STATIC], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_STATIC(no) +])# AC_DISABLE_STATIC + + +# AC_ENABLE_FAST_INSTALL([DEFAULT]) +# --------------------------------- +# implement the --enable-fast-install flag +# DEFAULT is either `yes' or `no'. If omitted, it defaults to `yes'. +AC_DEFUN([AC_ENABLE_FAST_INSTALL], +[define([AC_ENABLE_FAST_INSTALL_DEFAULT], ifelse($1, no, no, yes))dnl +AC_ARG_ENABLE([fast-install], + [AC_HELP_STRING([--enable-fast-install@<:@=PKGS@:>@], + [optimize for fast installation @<:@default=]AC_ENABLE_FAST_INSTALL_DEFAULT[@:>@])], + [p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac], + [enable_fast_install=]AC_ENABLE_FAST_INSTALL_DEFAULT) +])# AC_ENABLE_FAST_INSTALL + + +# AC_DISABLE_FAST_INSTALL +# ----------------------- +# set the default to --disable-fast-install +AC_DEFUN([AC_DISABLE_FAST_INSTALL], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +AC_ENABLE_FAST_INSTALL(no) +])# AC_DISABLE_FAST_INSTALL + + +# AC_LIBTOOL_PICMODE([MODE]) +# -------------------------- +# implement the --with-pic flag +# MODE is either `yes' or `no'. If omitted, it defaults to `both'. +AC_DEFUN([AC_LIBTOOL_PICMODE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl +pic_mode=ifelse($#,1,$1,default) +])# AC_LIBTOOL_PICMODE + + +# AC_PROG_EGREP +# ------------- +# This is predefined starting with Autoconf 2.54, so this conditional +# definition can be removed once we require Autoconf 2.54 or later. +m4_ifndef([AC_PROG_EGREP], [AC_DEFUN([AC_PROG_EGREP], +[AC_CACHE_CHECK([for egrep], [ac_cv_prog_egrep], + [if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi]) + EGREP=$ac_cv_prog_egrep + AC_SUBST([EGREP]) +])]) + + +# AC_PATH_TOOL_PREFIX +# ------------------- +# find a file program which can recognise shared library +AC_DEFUN([AC_PATH_TOOL_PREFIX], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_MSG_CHECKING([for $1]) +AC_CACHE_VAL(lt_cv_path_MAGIC_CMD, +[case $MAGIC_CMD in +[[\\/*] | ?:[\\/]*]) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR +dnl $ac_dummy forces splitting on constant user-supplied paths. +dnl POSIX.2 word splitting is done only on the output of word expansions, +dnl not every word. This closes a longstanding sh security hole. + ac_dummy="ifelse([$2], , $PATH, [$2])" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/$1; then + lt_cv_path_MAGIC_CMD="$ac_dir/$1" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac]) +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + AC_MSG_RESULT($MAGIC_CMD) +else + AC_MSG_RESULT(no) +fi +])# AC_PATH_TOOL_PREFIX + + +# AC_PATH_MAGIC +# ------------- +# find a file program which can recognise a shared library +AC_DEFUN([AC_PATH_MAGIC], +[AC_PATH_TOOL_PREFIX(${ac_tool_prefix}file, /usr/bin$PATH_SEPARATOR$PATH) +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + AC_PATH_TOOL_PREFIX(file, /usr/bin$PATH_SEPARATOR$PATH) + else + MAGIC_CMD=: + fi +fi +])# AC_PATH_MAGIC + + +# AC_PROG_LD +# ---------- +# find the path to the GNU or non-GNU linker +AC_DEFUN([AC_PROG_LD], +[AC_ARG_WITH([gnu-ld], + [AC_HELP_STRING([--with-gnu-ld], + [assume the C compiler uses GNU ld @<:@default=no@:>@])], + [test "$withval" = no || with_gnu_ld=yes], + [with_gnu_ld=no]) +AC_REQUIRE([LT_AC_PROG_SED])dnl +AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_CANONICAL_HOST])dnl +AC_REQUIRE([AC_CANONICAL_BUILD])dnl +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + AC_MSG_CHECKING([for ld used by $CC]) + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [[\\/]]* | ?:[[\\/]]*) + re_direlt='/[[^/]][[^/]]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + AC_MSG_CHECKING([for GNU ld]) +else + AC_MSG_CHECKING([for non-GNU ld]) +fi +AC_CACHE_VAL(lt_cv_path_LD, +[if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi]) +LD="$lt_cv_path_LD" +if test -n "$LD"; then + AC_MSG_RESULT($LD) +else + AC_MSG_RESULT(no) +fi +test -z "$LD" && AC_MSG_ERROR([no acceptable ld found in \$PATH]) +AC_PROG_LD_GNU +])# AC_PROG_LD + + +# AC_PROG_LD_GNU +# -------------- +AC_DEFUN([AC_PROG_LD_GNU], +[AC_REQUIRE([AC_PROG_EGREP])dnl +AC_CACHE_CHECK([if the linker ($LD) is GNU ld], lt_cv_prog_gnu_ld, +[# I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac]) +with_gnu_ld=$lt_cv_prog_gnu_ld +])# AC_PROG_LD_GNU + + +# AC_PROG_LD_RELOAD_FLAG +# ---------------------- +# find reload flag for linker +# -- PORTME Some linkers may need a different reload flag. +AC_DEFUN([AC_PROG_LD_RELOAD_FLAG], +[AC_CACHE_CHECK([for $LD option to reload object files], + lt_cv_ld_reload_flag, + [lt_cv_ld_reload_flag='-r']) +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' +])# AC_PROG_LD_RELOAD_FLAG + + +# AC_DEPLIBS_CHECK_METHOD +# ----------------------- +# how to check for library dependencies +# -- PORTME fill in with the dynamic library characteristics +AC_DEFUN([AC_DEPLIBS_CHECK_METHOD], +[AC_CACHE_CHECK([how to recognise dependent libraries], +lt_cv_deplibs_check_method, +[lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi4*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin* | mingw* | pw32*) + # win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='win32_libid' + ;; + +darwin* | rhapsody*) + # this will be overwritten by pass_all, but leave it in just in case + lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' + lt_cv_file_magic_cmd='/usr/bin/file -L' + case "$host_os" in + rhapsody* | darwin1.[[012]]) + lt_cv_file_magic_test_file=`/System/Library/Frameworks/System.framework/System` + ;; + *) # Darwin 1.3 on + lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' + ;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[[3-9]]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case "$host_cpu" in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|ELF-[[0-9]][[0-9]]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + irix5* | nonstopux*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[[1234]] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + case $host_cpu in + alpha* | hppa* | i*86 | ia64* | m68* | mips | mipsel | powerpc* | sparc* | s390* | sh* | x86_64*) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so\.[[0-9]]+\.[[0-9]]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[[^/]]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[ML]]SB (shared object|dynamic lib) M[[0-9]][[0-9]]* Version [[0-9]]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [[0-9]][[0-9]]*-bit [[LM]]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac +]) +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown +])# AC_DEPLIBS_CHECK_METHOD + + +# AC_PROG_NM +# ---------- +# find the path to a BSD-compatible name lister +AC_DEFUN([AC_PROG_NM], +[AC_CACHE_CHECK([for BSD-compatible nm], lt_cv_path_NM, +[if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi]) +NM="$lt_cv_path_NM" +])# AC_PROG_NM + + +# AC_CHECK_LIBM +# ------------- +# check for math library +AC_DEFUN([AC_CHECK_LIBM], +[AC_REQUIRE([AC_CANONICAL_HOST])dnl +LIBM= +case $host in +*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) + # These system don't have libm, or don't need it + ;; +*-ncr-sysv4.3*) + AC_CHECK_LIB(mw, _mwvalidcheckl, LIBM="-lmw") + AC_CHECK_LIB(m, cos, LIBM="$LIBM -lm") + ;; +*) + AC_CHECK_LIB(m, cos, LIBM="-lm") + ;; +esac +])# AC_CHECK_LIBM + + +# AC_LIBLTDL_CONVENIENCE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl convenience library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-convenience to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided, it is assumed to be `libltdl'. LIBLTDL will +# be prefixed with '${top_builddir}/' and LTDLINCL will be prefixed with +# '${top_srcdir}/' (note the single quotes!). If your package is not +# flat and you're not using automake, define top_builddir and +# top_srcdir appropriately in the Makefiles. +AC_DEFUN([AC_LIBLTDL_CONVENIENCE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + case $enable_ltdl_convenience in + no) AC_MSG_ERROR([this package needs a convenience libltdl]) ;; + "") enable_ltdl_convenience=yes + ac_configure_args="$ac_configure_args --enable-ltdl-convenience" ;; + esac + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdlc.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_CONVENIENCE + + +# AC_LIBLTDL_INSTALLABLE([DIRECTORY]) +# ----------------------------------- +# sets LIBLTDL to the link flags for the libltdl installable library and +# LTDLINCL to the include flags for the libltdl header and adds +# --enable-ltdl-install to the configure arguments. Note that LIBLTDL +# and LTDLINCL are not AC_SUBSTed, nor is AC_CONFIG_SUBDIRS called. If +# DIRECTORY is not provided and an installed libltdl is not found, it is +# assumed to be `libltdl'. LIBLTDL will be prefixed with '${top_builddir}/' +# and LTDLINCL will be prefixed with '${top_srcdir}/' (note the single +# quotes!). If your package is not flat and you're not using automake, +# define top_builddir and top_srcdir appropriately in the Makefiles. +# In the future, this macro may have to be called after AC_PROG_LIBTOOL. +AC_DEFUN([AC_LIBLTDL_INSTALLABLE], +[AC_BEFORE([$0],[AC_LIBTOOL_SETUP])dnl + AC_CHECK_LIB(ltdl, lt_dlinit, + [test x"$enable_ltdl_install" != xyes && enable_ltdl_install=no], + [if test x"$enable_ltdl_install" = xno; then + AC_MSG_WARN([libltdl not installed, but installation disabled]) + else + enable_ltdl_install=yes + fi + ]) + if test x"$enable_ltdl_install" = x"yes"; then + ac_configure_args="$ac_configure_args --enable-ltdl-install" + LIBLTDL='${top_builddir}/'ifelse($#,1,[$1],['libltdl'])/libltdl.la + LTDLINCL='-I${top_srcdir}/'ifelse($#,1,[$1],['libltdl']) + else + ac_configure_args="$ac_configure_args --enable-ltdl-install=no" + LIBLTDL="-lltdl" + LTDLINCL= + fi + # For backwards non-gettext consistent compatibility... + INCLTDL="$LTDLINCL" +])# AC_LIBLTDL_INSTALLABLE + + +# AC_LIBTOOL_CXX +# -------------- +# enable support for C++ libraries +AC_DEFUN([AC_LIBTOOL_CXX], +[AC_REQUIRE([_LT_AC_LANG_CXX]) +])# AC_LIBTOOL_CXX + + +# _LT_AC_LANG_CXX +# --------------- +AC_DEFUN([_LT_AC_LANG_CXX], +[AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) +_LT_AC_SHELL_INIT([tagnames=`echo "$tagnames,CXX" | sed 's/^,//'`]) +])# _LT_AC_LANG_CXX + + +# AC_LIBTOOL_F77 +# -------------- +# enable support for Fortran 77 libraries +AC_DEFUN([AC_LIBTOOL_F77], +[AC_REQUIRE([_LT_AC_LANG_F77]) +])# AC_LIBTOOL_F77 + + +# _LT_AC_LANG_F77 +# --------------- +AC_DEFUN([_LT_AC_LANG_F77], +[AC_REQUIRE([AC_PROG_F77]) +_LT_AC_SHELL_INIT([tagnames=`echo "$tagnames,F77" | sed 's/^,//'`]) +])# _LT_AC_LANG_F77 + + +# AC_LIBTOOL_GCJ +# -------------- +# enable support for GCJ libraries +AC_DEFUN([AC_LIBTOOL_GCJ], +[AC_REQUIRE([_LT_AC_LANG_GCJ]) +])# AC_LIBTOOL_GCJ + + +# _LT_AC_LANG_GCJ +# --------------- +AC_DEFUN([_LT_AC_LANG_GCJ], +[AC_PROVIDE_IFELSE([AC_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([A][M_PROG_GCJ],[], + [AC_PROVIDE_IFELSE([LT_AC_PROG_GCJ],[], + [ifdef([AC_PROG_GCJ],[AC_REQUIRE([AC_PROG_GCJ])], + [ifdef([A][M_PROG_GCJ],[AC_REQUIRE([A][M_PROG_GCJ])], + [AC_REQUIRE([A][C_PROG_GCJ_OR_A][M_PROG_GCJ])])])])])]) +_LT_AC_SHELL_INIT([tagnames=`echo "$tagnames,GCJ" | sed 's/^,//'`]) +])# _LT_AC_LANG_GCJ + + +# AC_LIBTOOL_RC +# -------------- +# enable support for Windows resource files +AC_DEFUN([AC_LIBTOOL_RC], +[AC_REQUIRE([LT_AC_PROG_RC]) +_LT_AC_SHELL_INIT([tagnames=`echo "$tagnames,RC" | sed 's/^,//'`]) +])# AC_LIBTOOL_RC + + +# AC_LIBTOOL_LANG_C_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG], [_LT_AC_LANG_C_CONFIG]) +AC_DEFUN([_LT_AC_LANG_C_CONFIG], +[lt_save_CC="$CC" +AC_LANG_PUSH(C) + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + +_LT_AC_SYS_COMPILER + +# +# Check for any special shared library compilation flags. +# +_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_cc_shlib, $1)='-belf' + ;; + esac +fi +if test -n "$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)"; then + AC_MSG_WARN([`$CC' requires `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to build shared libraries]) + if echo "$old_CC $old_CFLAGS " | grep "[[ ]]$]_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)[[[ ]]" >/dev/null; then : + else + AC_MSG_WARN([add `$_LT_AC_TAGVAR(lt_prog_cc_shlib, $1)' to the CC or CFLAGS env variable and reconfigure]) + _LT_AC_TAGVAR(lt_cv_prog_cc_can_build_shared, $1)=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +AC_LIBTOOL_LINKER_OPTION([if $compiler static flag $_LT_AC_TAGVAR(lt_prog_compiler_static, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_static_works, $1), + $_LT_AC_TAGVAR(lt_prog_compiler_static, $1), + [], + [_LT_AC_TAGVAR(lt_prog_compiler_static, $1)=]) + + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +# Report which librarie types wil actually be built +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + output_verbose_link_cmd='echo' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' + _LT_AC_TAGVAR(module_cmds, $1)='$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + fi + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_C_CONFIG + + +# AC_LIBTOOL_LANG_CXX_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG], [_LT_AC_LANG_CXX_CONFIG(CXX)]) +AC_DEFUN([_LT_AC_LANG_CXX_CONFIG], +[AC_LANG_PUSH(C++) +AC_REQUIRE([AC_PROG_CXX]) +AC_REQUIRE([AC_PROG_CXXCPP]) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Dependencies to place before and after the object being linked: +_LT_AC_TAGVAR(predep_objects, $1)= +_LT_AC_TAGVAR(postdep_objects, $1)= +_LT_AC_TAGVAR(predeps, $1)= +_LT_AC_TAGVAR(postdeps, $1)= +_LT_AC_TAGVAR(compiler_lib_search_path, $1)= + +# Source file extension for C++ test sources. +ac_ext=cc + +# Object file extension for compiled C++ test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *[]) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' +else + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + AC_PROG_LD + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +_LT_AC_TAGVAR(ld_shlibs, $1)=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GXX" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + fi + ;; + + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + freebsd[12]*) + # C++ shared libraries reported to be fairly broken before switch to ELF + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + freebsd-elf*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + freebsd*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + ;; + gnu*) + ;; + hpux9*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + esac + fi + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + aCC) + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case "$host_cpu" in + ia64*|hppa*64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + esac + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc) + # Intel C++ + with_gnu_ld=yes + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + cxx) + # Compaq C++ + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + m88k*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + _LT_AC_TAGVAR(archive_cmds, $1)='tempext=`echo $shared_ext | $SED -e '\''s/\([[^()0-9A-Za-z{}]]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + cxx) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + sco*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -zdefs' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[[LR]]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + _LT_AC_TAGVAR(old_archive_cmds, $1)='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + *) + # FIXME: insert proper C++ library support + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; +esac +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$GXX" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_POSTDEP_PREDEP($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld +])# AC_LIBTOOL_LANG_CXX_CONFIG + +# AC_LIBTOOL_POSTDEP_PREDEP([TAGNAME]) +# ------------------------ +# Figure out "hidden" library dependencies from verbose +# compiler output when linking a shared library. +# Parse the compiler output and extract the necessary +# objects, libraries and library flags. +AC_DEFUN([AC_LIBTOOL_POSTDEP_PREDEP],[ +dnl we can't use the lt_simple_compile_test_code here, +dnl because it contains code intended for an executable, +dnl not a library. It's possible we should let each +dnl tag define a new lt_????_link_test_code variable, +dnl but it's only used here... +ifelse([$1],[],[cat > conftest.$ac_ext <<EOF +int a; +void foo (void) { a = 0; } +EOF +],[$1],[CXX],[cat > conftest.$ac_ext <<EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +EOF +],[$1],[F77],[cat > conftest.$ac_ext <<EOF + subroutine foo + implicit none + integer*4 a + a=0 + return + end +EOF +],[$1],[GCJ],[cat > conftest.$ac_ext <<EOF +public class foo { + private int a; + public void bar (void) { + a = 0; + } +}; +EOF +]) +dnl Parse the compiler output and extract the necessary +dnl objects, libraries and library flags. +if AC_TRY_EVAL(ac_compile); then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$_LT_AC_TAGVAR(compiler_lib_search_path, $1)"; then + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(compiler_lib_search_path, $1)="${_LT_AC_TAGVAR(compiler_lib_search_path, $1)} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$_LT_AC_TAGVAR(postdeps, $1)"; then + _LT_AC_TAGVAR(postdeps, $1)="${prev}${p}" + else + _LT_AC_TAGVAR(postdeps, $1)="${_LT_AC_TAGVAR(postdeps, $1)} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$_LT_AC_TAGVAR(predep_objects, $1)"; then + _LT_AC_TAGVAR(predep_objects, $1)="$p" + else + _LT_AC_TAGVAR(predep_objects, $1)="$_LT_AC_TAGVAR(predep_objects, $1) $p" + fi + else + if test -z "$_LT_AC_TAGVAR(postdep_objects, $1)"; then + _LT_AC_TAGVAR(postdep_objects, $1)="$p" + else + _LT_AC_TAGVAR(postdep_objects, $1)="$_LT_AC_TAGVAR(postdep_objects, $1) $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling $1 test program" +fi + +$rm -f confest.$objext + +case " $_LT_AC_TAGVAR(postdeps, $1) " in +*" -lc "*) _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no ;; +esac +])# AC_LIBTOOL_POSTDEP_PREDEP + +# AC_LIBTOOL_LANG_F77_CONFIG +# ------------------------ +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_F77_CONFIG], [_LT_AC_LANG_F77_CONFIG(F77)]) +AC_DEFUN([_LT_AC_LANG_F77_CONFIG], +[AC_REQUIRE([AC_PROG_F77]) +AC_LANG_PUSH(Fortran 77) + +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no +_LT_AC_TAGVAR(allow_undefined_flag, $1)= +_LT_AC_TAGVAR(always_export_symbols, $1)=no +_LT_AC_TAGVAR(archive_expsym_cmds, $1)= +_LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_direct, $1)=no +_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= +_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= +_LT_AC_TAGVAR(hardcode_libdir_separator, $1)= +_LT_AC_TAGVAR(hardcode_minus_L, $1)=no +_LT_AC_TAGVAR(hardcode_automatic, $1)=no +_LT_AC_TAGVAR(module_cmds, $1)= +_LT_AC_TAGVAR(module_expsym_cmds, $1)= +_LT_AC_TAGVAR(link_all_deplibs, $1)=unknown +_LT_AC_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_AC_TAGVAR(no_undefined_flag, $1)= +_LT_AC_TAGVAR(whole_archive_flag_spec, $1)= +_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +AC_MSG_CHECKING([if libtool supports shared libraries]) +AC_MSG_RESULT([$can_build_shared]) + +AC_MSG_CHECKING([whether to build shared libraries]) +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac +AC_MSG_RESULT([$enable_shared]) + +AC_MSG_CHECKING([whether to build static libraries]) +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +AC_MSG_RESULT([$enable_static]) + +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +_LT_AC_TAGVAR(GCC, $1)="$G77" +_LT_AC_TAGVAR(LD, $1)="$LD" + +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_POP +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_F77_CONFIG + + +# AC_LIBTOOL_LANG_GCJ_CONFIG +# -------------------------- +# Ensure that the configuration vars for the C compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_GCJ_CONFIG], [_LT_AC_LANG_GCJ_CONFIG(GCJ)]) +AC_DEFUN([_LT_AC_LANG_GCJ_CONFIG], +[AC_LANG_SAVE + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String[] argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +_LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + +AC_LIBTOOL_PROG_COMPILER_NO_RTTI($1) +AC_LIBTOOL_PROG_COMPILER_PIC($1) +AC_LIBTOOL_PROG_CC_C_O($1) +AC_LIBTOOL_SYS_HARD_LINK_LOCKS($1) +AC_LIBTOOL_PROG_LD_SHLIBS($1) +AC_LIBTOOL_PROG_LD_HARDCODE_LIBPATH($1) +AC_LIBTOOL_SYS_LIB_STRIP +AC_LIBTOOL_SYS_DYNAMIC_LINKER($1) +AC_LIBTOOL_DLOPEN_SELF($1) + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_GCJ_CONFIG + + +# AC_LIBTOOL_LANG_RC_CONFIG +# -------------------------- +# Ensure that the configuration vars for the Windows resource compiler are +# suitably defined. Those variables are subsequently used by +# AC_LIBTOOL_CONFIG to write the compiler configuration to `libtool'. +AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG], [_LT_AC_LANG_RC_CONFIG(RC)]) +AC_DEFUN([_LT_AC_LANG_RC_CONFIG], +[AC_LANG_SAVE + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +_LT_AC_TAGVAR(objext, $1)=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. +_LT_AC_SYS_COMPILER + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +_LT_AC_TAGVAR(compiler, $1)=$CC +_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes + +AC_LIBTOOL_CONFIG($1) + +AC_LANG_RESTORE +CC="$lt_save_CC" +])# AC_LIBTOOL_LANG_RC_CONFIG + + +# AC_LIBTOOL_CONFIG([TAGNAME]) +# ---------------------------- +# If TAGNAME is not passed, then create an initial libtool script +# with a default configuration from the untagged config vars. Otherwise +# add code to config.status for appending the configuration named by +# TAGNAME from the matching tagged config vars. +AC_DEFUN([AC_LIBTOOL_CONFIG], +[# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + _LT_AC_TAGVAR(compiler, $1) \ + _LT_AC_TAGVAR(CC, $1) \ + _LT_AC_TAGVAR(LD, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_static, $1) \ + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) \ + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1) \ + _LT_AC_TAGVAR(thread_safe_flag_spec, $1) \ + _LT_AC_TAGVAR(whole_archive_flag_spec, $1) \ + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) \ + _LT_AC_TAGVAR(old_archive_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) \ + _LT_AC_TAGVAR(predep_objects, $1) \ + _LT_AC_TAGVAR(postdep_objects, $1) \ + _LT_AC_TAGVAR(predeps, $1) \ + _LT_AC_TAGVAR(postdeps, $1) \ + _LT_AC_TAGVAR(compiler_lib_search_path, $1) \ + _LT_AC_TAGVAR(archive_cmds, $1) \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) \ + _LT_AC_TAGVAR(postinstall_cmds, $1) \ + _LT_AC_TAGVAR(postuninstall_cmds, $1) \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) \ + _LT_AC_TAGVAR(allow_undefined_flag, $1) \ + _LT_AC_TAGVAR(no_undefined_flag, $1) \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) \ + _LT_AC_TAGVAR(hardcode_libdir_separator, $1) \ + _LT_AC_TAGVAR(hardcode_automatic, $1) \ + _LT_AC_TAGVAR(module_cmds, $1) \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) \ + _LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) \ + _LT_AC_TAGVAR(exclude_expsyms, $1) \ + _LT_AC_TAGVAR(include_expsyms, $1); do + + case $var in + _LT_AC_TAGVAR(old_archive_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_new_cmds, $1) | \ + _LT_AC_TAGVAR(archive_cmds, $1) | \ + _LT_AC_TAGVAR(archive_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(module_cmds, $1) | \ + _LT_AC_TAGVAR(module_expsym_cmds, $1) | \ + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) | \ + _LT_AC_TAGVAR(export_symbols_cmds, $1) | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\[$]0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\[$]0 --fallback-echo"[$]/[$]0 --fallback-echo"/'` + ;; + esac + +ifelse([$1], [], + [cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + AC_MSG_NOTICE([creating $ofile])], + [cfgfile="$ofile"]) + + cat <<__EOF__ >> "$cfgfile" +ifelse([$1], [], +[#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG], +[# ### BEGIN LIBTOOL TAG CONFIG: $tagname]) + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$_LT_AC_TAGVAR(archive_cmds_need_lc, $1) + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$_LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1) + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_[]_LT_AC_TAGVAR(compiler, $1) + +# Is the compiler the GNU C compiler? +with_gcc=$_LT_AC_TAGVAR(GCC, $1) + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_[]_LT_AC_TAGVAR(LD, $1) + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_[]_LT_AC_TAGVAR(lt_cv_prog_compiler_c_o, $1) + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_static, $1) + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_[]_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_[]_LT_AC_TAGVAR(export_dynamic_flag_spec, $1) + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_[]_LT_AC_TAGVAR(whole_archive_flag_spec, $1) + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_[]_LT_AC_TAGVAR(thread_safe_flag_spec, $1) + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_cmds, $1) +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_new_cmds, $1) + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_[]_LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1) + +# Commands used to build and install a shared archive. +archive_cmds=$lt_[]_LT_AC_TAGVAR(archive_cmds, $1) +archive_expsym_cmds=$lt_[]_LT_AC_TAGVAR(archive_expsym_cmds, $1) +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_[]_LT_AC_TAGVAR(module_cmds, $1) +module_expsym_cmds=$lt_[]_LT_AC_TAGVAR(module_expsym_cmds, $1) + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_[]_LT_AC_TAGVAR(predep_objects, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_[]_LT_AC_TAGVAR(postdep_objects, $1) + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_[]_LT_AC_TAGVAR(predeps, $1) + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_[]_LT_AC_TAGVAR(postdeps, $1) + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_[]_LT_AC_TAGVAR(compiler_lib_search_path, $1) + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_[]_LT_AC_TAGVAR(allow_undefined_flag, $1) + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_[]_LT_AC_TAGVAR(no_undefined_flag, $1) + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$_LT_AC_TAGVAR(hardcode_action, $1) + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1) + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_[]_LT_AC_TAGVAR(hardcode_libdir_separator, $1) + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$_LT_AC_TAGVAR(hardcode_direct, $1) + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$_LT_AC_TAGVAR(hardcode_minus_L, $1) + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$_LT_AC_TAGVAR(hardcode_shlibpath_var, $1) + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$_LT_AC_TAGVAR(hardcode_automatic, $1) + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$_LT_AC_TAGVAR(link_all_deplibs, $1) + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$_LT_AC_TAGVAR(fix_srcfile_path, $1)" + +# Set to yes if exported symbols are required. +always_export_symbols=$_LT_AC_TAGVAR(always_export_symbols, $1) + +# The commands to list exported symbols. +export_symbols_cmds=$lt_[]_LT_AC_TAGVAR(export_symbols_cmds, $1) + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_[]_LT_AC_TAGVAR(exclude_expsyms, $1) + +# Symbols that must always be exported. +include_expsyms=$lt_[]_LT_AC_TAGVAR(include_expsyms, $1) + +ifelse([$1],[], +[# ### END LIBTOOL CONFIG], +[# ### END LIBTOOL TAG CONFIG: $tagname]) + +__EOF__ + +ifelse([$1],[], [ + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" +]) +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi +])# AC_LIBTOOL_CONFIG + + +# AC_LIBTOOL_PROG_COMPILER_NO_RTTI([TAGNAME]) +# ------------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_NO_RTTI], +[AC_REQUIRE([_LT_AC_SYS_COMPILER])dnl + +_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= + +if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + + AC_LIBTOOL_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], + lt_cv_prog_compiler_rtti_exceptions, + [-fno-rtti -fno-exceptions], [], + [_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1) -fno-rtti -fno-exceptions"]) +fi +])# AC_LIBTOOL_PROG_COMPILER_NO_RTTI + + +# AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE +# --------------------------------- +AC_DEFUN([AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE], +[AC_REQUIRE([AC_CANONICAL_HOST]) +AC_REQUIRE([AC_PROG_NM]) +AC_REQUIRE([AC_OBJEXT]) +# Check for command to grab the raw symbol name followed by C symbol from nm. +AC_MSG_CHECKING([command to parse $NM output from $compiler object]) +AC_CACHE_VAL([lt_cv_sys_global_symbol_pipe], +[ +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[[BCDEGRST]]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([[_A-Za-z]][[_A-Za-z0-9]]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[[BCDT]]' + ;; +cygwin* | mingw* | pw32*) + symcode='[[ABCDGISTW]]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[[ABCDEGRST]]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([[^ ]]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([[^ ]]*\) \([[^ ]]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[[BCDEGRST]]' + ;; +osf*) + symcode='[[BCDEGQRST]]' + ;; +solaris* | sysv5*) + symcode='[[BDRT]]' + ;; +sysv4) + symcode='[[DFNSTU]]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[[ABCDGIRSTW]]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[[ ]]\($symcode$symcode*\)[[ ]][[ ]]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + if AC_TRY_EVAL(ac_compile); then + # Now try to grab the symbols. + nlist=conftest.nm + if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <<EOF >> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[[]] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$_LT_AC_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)" + if AC_TRY_EVAL(ac_link) && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot find nm_test_var in $nlist" >&AS_MESSAGE_LOG_FD + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&AS_MESSAGE_LOG_FD + fi + else + echo "$progname: failed program was:" >&AS_MESSAGE_LOG_FD + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done +]) +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + AC_MSG_RESULT(failed) +else + AC_MSG_RESULT(ok) +fi +]) # AC_LIBTOOL_SYS_GLOBAL_SYMBOL_PIPE + + +# AC_LIBTOOL_PROG_COMPILER_PIC([TAGNAME]) +# --------------------------------------- +AC_DEFUN([AC_LIBTOOL_PROG_COMPILER_PIC], +[_LT_AC_TAGVAR(lt_prog_compiler_wl, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= +_LT_AC_TAGVAR(lt_prog_compiler_static, $1)= + +AC_MSG_CHECKING([for $compiler option to produce PIC]) + ifelse([$1],[CXX],[ + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + freebsd*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + fi + ;; + aCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + icpc) + # Intel C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + cxx) + # Digital/Compaq C++ + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + lcc) + # Lucid + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +], +[ + if test "$GCC" = yes; then + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + else + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # PIC (with -KPIC) is the default. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + newsos6) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + linux*) + case $CC in + icc|ecc) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-static' + ;; + ccc) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All Alpha code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + # All OSF/1 code is PIC. + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kpic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-dn' + ;; + + solaris*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sunos4*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-PIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + _LT_AC_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-Kconform_pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + fi + ;; + + uts4*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)='-pic' + _LT_AC_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' + ;; + + *) + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)]) + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)"; then + AC_LIBTOOL_COMPILER_OPTION([if $compiler PIC flag $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) works], + _LT_AC_TAGVAR(lt_prog_compiler_pic_works, $1), + [$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])], [], + [case $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1) in + "" | " "*) ;; + *) _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)=" $_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)" ;; + esac], + [_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + _LT_AC_TAGVAR(lt_prog_compiler_can_build_shared, $1)=no]) +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)= + ;; + *) + _LT_AC_TAGVAR(lt_prog_compiler_pic, $1)="$_LT_AC_TAGVAR(lt_prog_compiler_pic, $1)ifelse([$1],[],[ -DPIC],[ifelse([$1],[CXX],[ -DPIC],[])])" + ;; +esac +]) + + +# AC_LIBTOOL_PROG_LD_SHLIBS([TAGNAME]) +# ------------------------------------ +# See if the linker supports building shared libraries. +AC_DEFUN([AC_LIBTOOL_PROG_LD_SHLIBS], +[AC_MSG_CHECKING([whether the $compiler linker ($LD) supports shared libraries]) +ifelse([$1],[CXX],[ + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)="$ltdll_cmds" + ;; + cygwin* | mingw*) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac +],[ + runpath_var= + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=no + _LT_AC_TAGVAR(archive_cmds, $1)= + _LT_AC_TAGVAR(archive_expsym_cmds, $1)= + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)= + _LT_AC_TAGVAR(old_archive_from_expsyms_cmds, $1)= + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)= + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + _LT_AC_TAGVAR(thread_safe_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)= + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(link_all_deplibs, $1)=unknown + _LT_AC_TAGVAR(hardcode_automatic, $1)=no + _LT_AC_TAGVAR(module_cmds, $1)= + _LT_AC_TAGVAR(module_expsym_cmds, $1)= + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + _LT_AC_TAGVAR(include_expsyms, $1)= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + _LT_AC_TAGVAR(exclude_expsyms, $1)="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, + # as there is no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=no + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[[BCDGS]] /s/.* \([[^ ]]*\)/\1 DATA/'\'' | $SED -e '\''/^[[AITW]] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + _LT_AC_TAGVAR(ld_shlibs, $1)=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + sunos4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_cmds, $1)="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ [01].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="$tmp_archive_cmds" + fi + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + _LT_AC_TAGVAR(ld_shlibs, $1)=no + fi + ;; + esac + + if test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = yes; then + runpath_var=LD_RUN_PATH + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + else + _LT_AC_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\[$]2 == "T") || (\[$]2 == "D") || (\[$]2 == "B")) && ([substr](\[$]3,1,1) != ".")) { print \[$]3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[[23]]|aix4.[[23]].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + _LT_AC_TAGVAR(archive_cmds, $1)='' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=':' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + + if test "$GCC" = yes; then + case $host_os in aix4.[012]|aix4.[012].*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + else + # We have old collect2 + _LT_AC_TAGVAR(hardcode_direct, $1)=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-berok' + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' + _LT_AC_TAGVAR(allow_undefined_flag, $1)="-z nodefs" + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + _LT_AC_SYS_LIBPATH_AIX + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + _LT_AC_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + _LT_AC_TAGVAR(always_export_symbols, $1)=yes + # Exported symbols can be pulled into shared objects from archives + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)=' ' + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + # This is similar to how AIX traditionally builds it's shared libraries. + _LT_AC_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + # see comment about different semantics on the GNU ld section + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + bsdi4*) + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)=' ' + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext=".dll" + # FIXME: Setting linknames here is a bad hack. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='true' + # FIXME: Should let the user specify the lib program. + _LT_AC_TAGVAR(old_archive_cmds, $1)='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + _LT_AC_TAGVAR(enable_shared_with_static_runtimes, $1)=yes + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + case "$host_os" in + rhapsody* | darwin1.[[012]]) + _LT_AC_TAGVAR(allow_undefined_flag, $1)='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && _LT_AC_TAGVAR(allow_undefined_flag, $1)='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + _LT_AC_TAGVAR(module_cmds, $1)='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + _LT_AC_TAGVAR(module_expsym_cmds, $1)='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_automatic, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=unsupported + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-all_load $convenience' + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + fi + ;; + + dgux*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + freebsd1*) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + hpux9*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='+b $libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + ia64*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + *) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + newsos6) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + openbsd*) + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' + else + case $host_os in + openbsd[[01]].* | openbsd2.[[0-7]] | openbsd2.[[0-7]].*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + ;; + *) + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(allow_undefined_flag, $1)=unsupported + _LT_AC_TAGVAR(archive_cmds, $1)='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_AC_TAGVAR(old_archive_From_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' + else + _LT_AC_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' + fi + _LT_AC_TAGVAR(hardcode_libdir_separator, $1)=: + ;; + + sco3.2v5*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + case $host_os in + solaris2.[[0-5]] | solaris2.[[0-5]].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + _LT_AC_TAGVAR(whole_archive_flag_spec, $1)='-z allextract$convenience -z defaultextract' ;; + esac + _LT_AC_TAGVAR(link_all_deplibs, $1)=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=yes + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4) + case $host_vendor in + sni) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(reload_cmds, $1)='$CC -r -o $output$reload_objs' + _LT_AC_TAGVAR(hardcode_direct, $1)=no + ;; + motorola) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv4.3*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + _LT_AC_TAGVAR(export_dynamic_flag_spec, $1)='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + _LT_AC_TAGVAR(ld_shlibs, $1)=yes + fi + ;; + + sysv4.2uw2*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_direct, $1)=yes + _LT_AC_TAGVAR(hardcode_minus_L, $1)=no + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[[78]]* | unixware7*) + _LT_AC_TAGVAR(no_undefined_flag, $1)='${wl}-z ${wl}text' + if test "$GCC" = yes; then + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + _LT_AC_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + sysv5*) + _LT_AC_TAGVAR(no_undefined_flag, $1)=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(archive_expsym_cmds, $1)='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)= + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + _LT_AC_TAGVAR(archive_cmds, $1)='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + _LT_AC_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_AC_TAGVAR(hardcode_shlibpath_var, $1)=no + ;; + + *) + _LT_AC_TAGVAR(ld_shlibs, $1)=no + ;; + esac + fi +]) +AC_MSG_RESULT([$_LT_AC_TAGVAR(ld_shlibs, $1)]) +test "$_LT_AC_TAGVAR(ld_shlibs, $1)" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)" in +x|xyes) + # Assume -lc should be added + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $_LT_AC_TAGVAR(archive_cmds, $1) in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + AC_MSG_CHECKING([whether -lc should be explicitly linked in]) + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_AC_TAGVAR(lt_prog_compiler_wl, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_AC_TAGVAR(allow_undefined_flag, $1) + _LT_AC_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_AC_TAGVAR(archive_cmds, $1) 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) + then + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=no + else + _LT_AC_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_AC_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + AC_MSG_RESULT([$_LT_AC_TAGVAR(archive_cmds_need_lc, $1)]) + ;; + esac + fi + ;; +esac +])# AC_LIBTOOL_PROG_LD_SHLIBS + + +# _LT_AC_FILE_LTDLL_C +# ------------------- +# Be careful that the start marker always follows a newline. +AC_DEFUN([_LT_AC_FILE_LTDLL_C], [ +# /* ltdll.c starts here */ +# #define WIN32_LEAN_AND_MEAN +# #include <windows.h> +# #undef WIN32_LEAN_AND_MEAN +# #include <stdio.h> +# +# #ifndef __CYGWIN__ +# # ifdef __CYGWIN32__ +# # define __CYGWIN__ __CYGWIN32__ +# # endif +# #endif +# +# #ifdef __cplusplus +# extern "C" { +# #endif +# BOOL APIENTRY DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved); +# #ifdef __cplusplus +# } +# #endif +# +# #ifdef __CYGWIN__ +# #include <cygwin/cygwin_dll.h> +# DECLARE_CYGWIN_DLL( DllMain ); +# #endif +# HINSTANCE __hDllInstance_base; +# +# BOOL APIENTRY +# DllMain (HINSTANCE hInst, DWORD reason, LPVOID reserved) +# { +# __hDllInstance_base = hInst; +# return TRUE; +# } +# /* ltdll.c ends here */ +])# _LT_AC_FILE_LTDLL_C + + +# _LT_AC_TAGVAR(VARNAME, [TAGNAME]) +# --------------------------------- +AC_DEFUN([_LT_AC_TAGVAR], [ifelse([$2], [], [$1], [$1_$2])]) + + +# old names +AC_DEFUN([AM_PROG_LIBTOOL], [AC_PROG_LIBTOOL]) +AC_DEFUN([AM_ENABLE_SHARED], [AC_ENABLE_SHARED($@)]) +AC_DEFUN([AM_ENABLE_STATIC], [AC_ENABLE_STATIC($@)]) +AC_DEFUN([AM_DISABLE_SHARED], [AC_DISABLE_SHARED($@)]) +AC_DEFUN([AM_DISABLE_STATIC], [AC_DISABLE_STATIC($@)]) +AC_DEFUN([AM_PROG_LD], [AC_PROG_LD]) +AC_DEFUN([AM_PROG_NM], [AC_PROG_NM]) + +# This is just to silence aclocal about the macro not being used +ifelse([AC_DISABLE_FAST_INSTALL]) + +AC_DEFUN([LT_AC_PROG_GCJ], +[AC_CHECK_TOOL(GCJ, gcj, no) + test "x${GCJFLAGS+set}" = xset || GCJFLAGS="-g -O2" + AC_SUBST(GCJFLAGS) +]) + +AC_DEFUN([LT_AC_PROG_RC], +[AC_CHECK_TOOL(RC, windres, no) +]) + +# NOTE: This macro has been submitted for inclusion into # +# GNU Autoconf as AC_PROG_SED. When it is available in # +# a released version of Autoconf we should remove this # +# macro and use it instead. # +# LT_AC_PROG_SED +# -------------- +# Check for a fully-functional sed program, that truncates +# as few characters as possible. Prefer GNU sed if found. +AC_DEFUN([LT_AC_PROG_SED], +[AC_MSG_CHECKING([for a sed that does not truncate output]) +AC_CACHE_VAL(lt_cv_path_SED, +[# Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && break + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +SED=$lt_cv_path_SED +]) +AC_MSG_RESULT([$SED]) +]) + +#serial 7 + +dnl Some libelf versions have bugs in Elf64_Sxword conversions. +dnl Detect it. + +dnl Written by Jakub Jelinek <jakub@redhat.com>. + +AC_DEFUN(AC_LIBELF_SXWORD, + [AC_TRY_RUN([ +#include <errno.h> +#include <fcntl.h> +#include <elf.h> +#include <libelf.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static unsigned char sparc64_elf[] = { +0x7f,0x45,0x4c,0x46,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,0x05, +0x00,0x00,0x07,0xff,0xf0,0x00,0x00,0x00,0x00,0x2e,0x73,0x79,0x6d,0x74,0x61,0x62, +0x00,0x2e,0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x73,0x68,0x73,0x74,0x72,0x74, +0x61,0x62,0x00,0x2e,0x74,0x65,0x78,0x74,0x00,0x2e,0x64,0x61,0x74,0x61,0x00,0x2e, +0x62,0x73,0x73,0x00,0x66,0x6f,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x04, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00 }; + +int main (void) +{ + Elf *elf; + int fd; + Elf64_Ehdr *ehdr; + Elf64_Addr val; + Elf_Scn *scn; + + fd = open ("conflibelftest", O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd == -1) exit (1); + unlink ("conflibelftest"); + if (write (fd, sparc64_elf, sizeof(sparc64_elf)) != sizeof(sparc64_elf)) + exit (1); + if (lseek (fd, 0, SEEK_SET) != 0) exit (1); + elf_version (EV_CURRENT); + elf = elf_begin (fd, ELF_C_RDWR, NULL); if (elf == NULL) exit (2); + if ((ehdr = elf64_getehdr (elf)) == NULL) exit (3); + scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + char *name = NULL; + Elf64_Shdr *shdr; + Elf_Data *src, *dst; + + if ((shdr = elf64_getshdr (scn)) + && (name = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name)) + && !strcmp (name, "foo")) + { + src = elf_rawdata (scn, NULL); + if (shdr->sh_size != 8 || src->d_off || src->d_size != 8) exit (4); + if (src == NULL || elf_rawdata (scn, src) != NULL) exit (5); + if ((dst = elf_newdata (scn)) == NULL) exit (6); + dst->d_buf = &val; + dst->d_size = 8; + dst->d_off = 0; + dst->d_type = ELF_T_SXWORD; + src->d_type = ELF_T_SXWORD; + if (elf64_xlatetom (dst, src, ELFDATA2MSB) == NULL) exit (7); + if (val != 0x7fff0000000) + exit (42); + elf_end (elf); + exit (0); + } + } + exit (8); +} + ],,[AC_MSG_ERROR([libelf does not properly convert Elf64_Sxword quantities. +If you are using libelf-0.7.0, please use patches/libelf-0.7.0.patch.])], +[AC_MSG_WARN([Could not test whether libelf properly converts Elf64_Sxword quantities. +If you are using libelf-0.7.0 and your libelf is buggy, please use +patches/libelf-0.7.0.patch.])]) + ]) + diff --git a/trunk/config.guess b/trunk/config.guess new file mode 100755 index 0000000..f1657bb --- /dev/null +++ b/trunk/config.guess @@ -0,0 +1,1363 @@ +#! /bin/sh +# Attempt to guess a canonical system name. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-09-03' + +# This file is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Per Bothner <per@bothner.com>. +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# This script attempts to guess a canonical system name similar to +# config.sub. If it succeeds, it prints the system name on stdout, and +# exits with 0. Otherwise, it exits with 1. +# +# The plan is that this can be called by configure scripts if you +# don't specify an explicit build system type. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] + +Output the configuration name of the system \`$me' is run on. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.guess ($timestamp) + +Originally written by Per Bothner. +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" >&2 + exit 1 ;; + * ) + break ;; + esac +done + +if test $# != 0; then + echo "$me: too many arguments$help" >&2 + exit 1 +fi + +trap 'exit 1' 1 2 15 + +# CC_FOR_BUILD -- compiler used by this script. Note that the use of a +# compiler to aid in system detection is discouraged as it requires +# temporary files to be created and, as you can see below, it is a +# headache to deal with in a portable fashion. + +# Historically, `CC_FOR_BUILD' used to be named `HOST_CC'. We still +# use `HOST_CC' if defined, but it is deprecated. + +# This shell variable is my proudest work .. or something. --bje + +set_cc_for_build='tmpdir=${TMPDIR-/tmp}/config-guess-$$ ; +(old=`umask` && umask 077 && mkdir $tmpdir && umask $old && unset old) + || (echo "$me: cannot create $tmpdir" >&2 && exit 1) ; +dummy=$tmpdir/dummy ; +files="$dummy.c $dummy.o $dummy.rel $dummy" ; +trap '"'"'rm -f $files; rmdir $tmpdir; exit 1'"'"' 1 2 15 ; +case $CC_FOR_BUILD,$HOST_CC,$CC in + ,,) echo "int x;" > $dummy.c ; + for c in cc gcc c89 c99 ; do + if ($c $dummy.c -c -o $dummy.o) >/dev/null 2>&1 ; then + CC_FOR_BUILD="$c"; break ; + fi ; + done ; + rm -f $files ; + if test x"$CC_FOR_BUILD" = x ; then + CC_FOR_BUILD=no_compiler_found ; + fi + ;; + ,,*) CC_FOR_BUILD=$CC ;; + ,*,*) CC_FOR_BUILD=$HOST_CC ;; +esac ; +unset files' + +# This is needed to find uname on a Pyramid OSx when run in the BSD universe. +# (ghazi@noc.rutgers.edu 1994-08-24) +if (test -f /.attbin/uname) >/dev/null 2>&1 ; then + PATH=$PATH:/.attbin ; export PATH +fi + +UNAME_MACHINE=`(uname -m) 2>/dev/null` || UNAME_MACHINE=unknown +UNAME_RELEASE=`(uname -r) 2>/dev/null` || UNAME_RELEASE=unknown +UNAME_SYSTEM=`(uname -s) 2>/dev/null` || UNAME_SYSTEM=unknown +UNAME_VERSION=`(uname -v) 2>/dev/null` || UNAME_VERSION=unknown + +# Note: order is significant - the case branches are not exclusive. + +case "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" in + *:NetBSD:*:*) + # NetBSD (nbsd) targets should (where applicable) match one or + # more of the tupples: *-*-netbsdelf*, *-*-netbsdaout*, + # *-*-netbsdecoff* and *-*-netbsd*. For targets that recently + # switched to ELF, *-*-netbsd* would select the old + # object file format. This provides both forward + # compatibility and a consistent mechanism for selecting the + # object file format. + # + # Note: NetBSD doesn't particularly care about the vendor + # portion of the name. We always set it to "unknown". + sysctl="sysctl -n hw.machine_arch" + UNAME_MACHINE_ARCH=`(/sbin/$sysctl 2>/dev/null || \ + /usr/sbin/$sysctl 2>/dev/null || echo unknown)` + case "${UNAME_MACHINE_ARCH}" in + armeb) machine=armeb-unknown ;; + arm*) machine=arm-unknown ;; + sh3el) machine=shl-unknown ;; + sh3eb) machine=sh-unknown ;; + *) machine=${UNAME_MACHINE_ARCH}-unknown ;; + esac + # The Operating System including object format, if it has switched + # to ELF recently, or will in the future. + case "${UNAME_MACHINE_ARCH}" in + arm*|i386|m68k|ns32k|sh3*|sparc|vax) + eval $set_cc_for_build + if echo __ELF__ | $CC_FOR_BUILD -E - 2>/dev/null \ + | grep __ELF__ >/dev/null + then + # Once all utilities can be ECOFF (netbsdecoff) or a.out (netbsdaout). + # Return netbsd for either. FIX? + os=netbsd + else + os=netbsdelf + fi + ;; + *) + os=netbsd + ;; + esac + # The OS release + release=`echo ${UNAME_RELEASE}|sed -e 's/[-_].*/\./'` + # Since CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM: + # contains redundant information, the shorter form: + # CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM is used. + echo "${machine}-${os}${release}" + exit 0 ;; + amiga:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + arc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + hp300:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mac68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + macppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme68k:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvme88k:OpenBSD:*:*) + echo m88k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + mvmeppc:OpenBSD:*:*) + echo powerpc-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + pmax:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sgi:OpenBSD:*:*) + echo mipseb-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + sun3:OpenBSD:*:*) + echo m68k-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + wgrisc:OpenBSD:*:*) + echo mipsel-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + *:OpenBSD:*:*) + echo ${UNAME_MACHINE}-unknown-openbsd${UNAME_RELEASE} + exit 0 ;; + alpha:OSF1:*:*) + if test $UNAME_RELEASE = "V4.0"; then + UNAME_RELEASE=`/usr/sbin/sizer -v | awk '{print $3}'` + fi + # A Vn.n version is a released version. + # A Tn.n version is a released field test version. + # A Xn.n version is an unreleased experimental baselevel. + # 1.2 uses "1.2" for uname -r. + eval $set_cc_for_build + cat <<EOF >$dummy.s + .data +\$Lformat: + .byte 37,100,45,37,120,10,0 # "%d-%x\n" + + .text + .globl main + .align 4 + .ent main +main: + .frame \$30,16,\$26,0 + ldgp \$29,0(\$27) + .prologue 1 + .long 0x47e03d80 # implver \$0 + lda \$2,-1 + .long 0x47e20c21 # amask \$2,\$1 + lda \$16,\$Lformat + mov \$0,\$17 + not \$1,\$18 + jsr \$26,printf + ldgp \$29,0(\$26) + mov 0,\$16 + jsr \$26,exit + .end main +EOF + $CC_FOR_BUILD $dummy.s -o $dummy 2>/dev/null + if test "$?" = 0 ; then + case `$dummy` in + 0-0) + UNAME_MACHINE="alpha" + ;; + 1-0) + UNAME_MACHINE="alphaev5" + ;; + 1-1) + UNAME_MACHINE="alphaev56" + ;; + 1-101) + UNAME_MACHINE="alphapca56" + ;; + 2-303) + UNAME_MACHINE="alphaev6" + ;; + 2-307) + UNAME_MACHINE="alphaev67" + ;; + 2-1307) + UNAME_MACHINE="alphaev68" + ;; + 3-1307) + UNAME_MACHINE="alphaev7" + ;; + esac + fi + rm -f $dummy.s $dummy && rmdir $tmpdir + echo ${UNAME_MACHINE}-dec-osf`echo ${UNAME_RELEASE} | sed -e 's/^[VTX]//' | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + exit 0 ;; + Alpha\ *:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # Should we change UNAME_MACHINE based on the output of uname instead + # of the specific Alpha model? + echo alpha-pc-interix + exit 0 ;; + 21064:Windows_NT:50:3) + echo alpha-dec-winnt3.5 + exit 0 ;; + Amiga*:UNIX_System_V:4.0:*) + echo m68k-unknown-sysv4 + exit 0;; + *:[Aa]miga[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-amigaos + exit 0 ;; + *:[Mm]orph[Oo][Ss]:*:*) + echo ${UNAME_MACHINE}-unknown-morphos + exit 0 ;; + *:OS/390:*:*) + echo i370-ibm-openedition + exit 0 ;; + arm:RISC*:1.[012]*:*|arm:riscix:1.[012]*:*) + echo arm-acorn-riscix${UNAME_RELEASE} + exit 0;; + SR2?01:HI-UX/MPP:*:* | SR8000:HI-UX/MPP:*:*) + echo hppa1.1-hitachi-hiuxmpp + exit 0;; + Pyramid*:OSx*:*:* | MIS*:OSx*:*:* | MIS*:SMP_DC-OSx*:*:*) + # akee@wpdis03.wpafb.af.mil (Earle F. Ake) contributed MIS and NILE. + if test "`(/bin/universe) 2>/dev/null`" = att ; then + echo pyramid-pyramid-sysv3 + else + echo pyramid-pyramid-bsd + fi + exit 0 ;; + NILE*:*:*:dcosx) + echo pyramid-pyramid-svr4 + exit 0 ;; + DRS?6000:UNIX_SV:4.2*:7*) + case `/usr/bin/uname -p` in + sparc) echo sparc-icl-nx7 && exit 0 ;; + esac ;; + sun4H:SunOS:5.*:*) + echo sparc-hal-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:5.*:* | tadpole*:SunOS:5.*:*) + echo sparc-sun-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + i86pc:SunOS:5.*:*) + echo i386-pc-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:6*:*) + # According to config.sub, this is the proper way to canonicalize + # SunOS6. Hard to guess exactly what SunOS6 will be like, but + # it's likely to be more like Solaris than SunOS4. + echo sparc-sun-solaris3`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + sun4*:SunOS:*:*) + case "`/usr/bin/arch -k`" in + Series*|S4*) + UNAME_RELEASE=`uname -v` + ;; + esac + # Japanese Language versions have a version number like `4.1.3-JL'. + echo sparc-sun-sunos`echo ${UNAME_RELEASE}|sed -e 's/-/_/'` + exit 0 ;; + sun3*:SunOS:*:*) + echo m68k-sun-sunos${UNAME_RELEASE} + exit 0 ;; + sun*:*:4.2BSD:*) + UNAME_RELEASE=`(sed 1q /etc/motd | awk '{print substr($5,1,3)}') 2>/dev/null` + test "x${UNAME_RELEASE}" = "x" && UNAME_RELEASE=3 + case "`/bin/arch`" in + sun3) + echo m68k-sun-sunos${UNAME_RELEASE} + ;; + sun4) + echo sparc-sun-sunos${UNAME_RELEASE} + ;; + esac + exit 0 ;; + aushp:SunOS:*:*) + echo sparc-auspex-sunos${UNAME_RELEASE} + exit 0 ;; + # The situation for MiNT is a little confusing. The machine name + # can be virtually everything (everything which is not + # "atarist" or "atariste" at least should have a processor + # > m68000). The system name ranges from "MiNT" over "FreeMiNT" + # to the lowercase version "mint" (or "freemint"). Finally + # the system name "TOS" denotes a system which is actually not + # MiNT. But MiNT is downward compatible to TOS, so this should + # be no problem. + atarist[e]:*MiNT:*:* | atarist[e]:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + atari*:*MiNT:*:* | atari*:*mint:*:* | atarist[e]:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + *falcon*:*MiNT:*:* | *falcon*:*mint:*:* | *falcon*:*TOS:*:*) + echo m68k-atari-mint${UNAME_RELEASE} + exit 0 ;; + milan*:*MiNT:*:* | milan*:*mint:*:* | *milan*:*TOS:*:*) + echo m68k-milan-mint${UNAME_RELEASE} + exit 0 ;; + hades*:*MiNT:*:* | hades*:*mint:*:* | *hades*:*TOS:*:*) + echo m68k-hades-mint${UNAME_RELEASE} + exit 0 ;; + *:*MiNT:*:* | *:*mint:*:* | *:*TOS:*:*) + echo m68k-unknown-mint${UNAME_RELEASE} + exit 0 ;; + powerpc:machten:*:*) + echo powerpc-apple-machten${UNAME_RELEASE} + exit 0 ;; + RISC*:Mach:*:*) + echo mips-dec-mach_bsd4.3 + exit 0 ;; + RISC*:ULTRIX:*:*) + echo mips-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + VAX*:ULTRIX*:*:*) + echo vax-dec-ultrix${UNAME_RELEASE} + exit 0 ;; + 2020:CLIX:*:* | 2430:CLIX:*:*) + echo clipper-intergraph-clix${UNAME_RELEASE} + exit 0 ;; + mips:*:*:UMIPS | mips:*:*:RISCos) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c +#ifdef __cplusplus +#include <stdio.h> /* for printf() prototype */ + int main (int argc, char *argv[]) { +#else + int main (argc, argv) int argc; char *argv[]; { +#endif + #if defined (host_mips) && defined (MIPSEB) + #if defined (SYSTYPE_SYSV) + printf ("mips-mips-riscos%ssysv\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_SVR4) + printf ("mips-mips-riscos%ssvr4\n", argv[1]); exit (0); + #endif + #if defined (SYSTYPE_BSD43) || defined(SYSTYPE_BSD) + printf ("mips-mips-riscos%sbsd\n", argv[1]); exit (0); + #endif + #endif + exit (-1); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy \ + && $dummy `echo "${UNAME_RELEASE}" | sed -n 's/\([0-9]*\).*/\1/p'` \ + && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo mips-mips-riscos${UNAME_RELEASE} + exit 0 ;; + Motorola:PowerMAX_OS:*:*) + echo powerpc-motorola-powermax + exit 0 ;; + Motorola:*:4.3:PL8-*) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:*:*:PowerMAX_OS) + echo powerpc-harris-powermax + exit 0 ;; + Night_Hawk:Power_UNIX:*:*) + echo powerpc-harris-powerunix + exit 0 ;; + m88k:CX/UX:7*:*) + echo m88k-harris-cxux7 + exit 0 ;; + m88k:*:4*:R4*) + echo m88k-motorola-sysv4 + exit 0 ;; + m88k:*:3*:R3*) + echo m88k-motorola-sysv3 + exit 0 ;; + AViiON:dgux:*:*) + # DG/UX returns AViiON for all architectures + UNAME_PROCESSOR=`/usr/bin/uname -p` + if [ $UNAME_PROCESSOR = mc88100 ] || [ $UNAME_PROCESSOR = mc88110 ] + then + if [ ${TARGET_BINARY_INTERFACE}x = m88kdguxelfx ] || \ + [ ${TARGET_BINARY_INTERFACE}x = x ] + then + echo m88k-dg-dgux${UNAME_RELEASE} + else + echo m88k-dg-dguxbcs${UNAME_RELEASE} + fi + else + echo i586-dg-dgux${UNAME_RELEASE} + fi + exit 0 ;; + M88*:DolphinOS:*:*) # DolphinOS (SVR3) + echo m88k-dolphin-sysv3 + exit 0 ;; + M88*:*:R3*:*) + # Delta 88k system running SVR3 + echo m88k-motorola-sysv3 + exit 0 ;; + XD88*:*:*:*) # Tektronix XD88 system running UTekV (SVR3) + echo m88k-tektronix-sysv3 + exit 0 ;; + Tek43[0-9][0-9]:UTek:*:*) # Tektronix 4300 system running UTek (BSD) + echo m68k-tektronix-bsd + exit 0 ;; + *:IRIX*:*:*) + echo mips-sgi-irix`echo ${UNAME_RELEASE}|sed -e 's/-/_/g'` + exit 0 ;; + ????????:AIX?:[12].1:2) # AIX 2.2.1 or AIX 2.1.1 is RT/PC AIX. + echo romp-ibm-aix # uname -m gives an 8 hex-code CPU id + exit 0 ;; # Note that: echo "'`uname -s`'" gives 'AIX ' + i*86:AIX:*:*) + echo i386-ibm-aix + exit 0 ;; + ia64:AIX:*:*) + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${UNAME_MACHINE}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:2:3) + if grep bos325 /usr/include/stdio.h >/dev/null 2>&1; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <sys/systemcfg.h> + + main() + { + if (!__power_pc()) + exit(1); + puts("powerpc-ibm-aix3.2.5"); + exit(0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo rs6000-ibm-aix3.2.5 + elif grep bos324 /usr/include/stdio.h >/dev/null 2>&1; then + echo rs6000-ibm-aix3.2.4 + else + echo rs6000-ibm-aix3.2 + fi + exit 0 ;; + *:AIX:*:[45]) + IBM_CPU_ID=`/usr/sbin/lsdev -C -c processor -S available | sed 1q | awk '{ print $1 }'` + if /usr/sbin/lsattr -El ${IBM_CPU_ID} | grep ' POWER' >/dev/null 2>&1; then + IBM_ARCH=rs6000 + else + IBM_ARCH=powerpc + fi + if [ -x /usr/bin/oslevel ] ; then + IBM_REV=`/usr/bin/oslevel` + else + IBM_REV=${UNAME_VERSION}.${UNAME_RELEASE} + fi + echo ${IBM_ARCH}-ibm-aix${IBM_REV} + exit 0 ;; + *:AIX:*:*) + echo rs6000-ibm-aix + exit 0 ;; + ibmrt:4.4BSD:*|romp-ibm:BSD:*) + echo romp-ibm-bsd4.4 + exit 0 ;; + ibmrt:*BSD:*|romp-ibm:BSD:*) # covers RT/PC BSD and + echo romp-ibm-bsd${UNAME_RELEASE} # 4.3 with uname added to + exit 0 ;; # report: romp-ibm BSD 4.3 + *:BOSX:*:*) + echo rs6000-bull-bosx + exit 0 ;; + DPX/2?00:B.O.S.:*:*) + echo m68k-bull-sysv3 + exit 0 ;; + 9000/[34]??:4.3bsd:1.*:*) + echo m68k-hp-bsd + exit 0 ;; + hp300:4.4BSD:*:* | 9000/[34]??:4.3bsd:2.*:*) + echo m68k-hp-bsd4.4 + exit 0 ;; + 9000/[34678]??:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + case "${UNAME_MACHINE}" in + 9000/31? ) HP_ARCH=m68000 ;; + 9000/[34]?? ) HP_ARCH=m68k ;; + 9000/[678][0-9][0-9]) + if [ -x /usr/bin/getconf ]; then + sc_cpu_version=`/usr/bin/getconf SC_CPU_VERSION 2>/dev/null` + sc_kernel_bits=`/usr/bin/getconf SC_KERNEL_BITS 2>/dev/null` + case "${sc_cpu_version}" in + 523) HP_ARCH="hppa1.0" ;; # CPU_PA_RISC1_0 + 528) HP_ARCH="hppa1.1" ;; # CPU_PA_RISC1_1 + 532) # CPU_PA_RISC2_0 + case "${sc_kernel_bits}" in + 32) HP_ARCH="hppa2.0n" ;; + 64) HP_ARCH="hppa2.0w" ;; + '') HP_ARCH="hppa2.0" ;; # HP-UX 10.20 + esac ;; + esac + fi + if [ "${HP_ARCH}" = "" ]; then + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + + #define _HPUX_SOURCE + #include <stdlib.h> + #include <unistd.h> + + int main () + { + #if defined(_SC_KERNEL_BITS) + long bits = sysconf(_SC_KERNEL_BITS); + #endif + long cpu = sysconf (_SC_CPU_VERSION); + + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1"); break; + case CPU_PA_RISC2_0: + #if defined(_SC_KERNEL_BITS) + switch (bits) + { + case 64: puts ("hppa2.0w"); break; + case 32: puts ("hppa2.0n"); break; + default: puts ("hppa2.0"); break; + } break; + #else /* !defined(_SC_KERNEL_BITS) */ + puts ("hppa2.0"); break; + #endif + default: puts ("hppa1.0"); break; + } + exit (0); + } +EOF + (CCOPTS= $CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null) && HP_ARCH=`$dummy` + if test -z "$HP_ARCH"; then HP_ARCH=hppa; fi + rm -f $dummy.c $dummy && rmdir $tmpdir + fi ;; + esac + echo ${HP_ARCH}-hp-hpux${HPUX_REV} + exit 0 ;; + ia64:HP-UX:*:*) + HPUX_REV=`echo ${UNAME_RELEASE}|sed -e 's/[^.]*.[0B]*//'` + echo ia64-hp-hpux${HPUX_REV} + exit 0 ;; + 3050*:HI-UX:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <unistd.h> + int + main () + { + long cpu = sysconf (_SC_CPU_VERSION); + /* The order matters, because CPU_IS_HP_MC68K erroneously returns + true for CPU_PA_RISC1_0. CPU_IS_PA_RISC returns correct + results, however. */ + if (CPU_IS_PA_RISC (cpu)) + { + switch (cpu) + { + case CPU_PA_RISC1_0: puts ("hppa1.0-hitachi-hiuxwe2"); break; + case CPU_PA_RISC1_1: puts ("hppa1.1-hitachi-hiuxwe2"); break; + case CPU_PA_RISC2_0: puts ("hppa2.0-hitachi-hiuxwe2"); break; + default: puts ("hppa-hitachi-hiuxwe2"); break; + } + } + else if (CPU_IS_HP_MC68K (cpu)) + puts ("m68k-hitachi-hiuxwe2"); + else puts ("unknown-hitachi-hiuxwe2"); + exit (0); + } +EOF + $CC_FOR_BUILD $dummy.c -o $dummy && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 + rm -f $dummy.c $dummy && rmdir $tmpdir + echo unknown-hitachi-hiuxwe2 + exit 0 ;; + 9000/7??:4.3bsd:*:* | 9000/8?[79]:4.3bsd:*:* ) + echo hppa1.1-hp-bsd + exit 0 ;; + 9000/8??:4.3bsd:*:*) + echo hppa1.0-hp-bsd + exit 0 ;; + *9??*:MPE/iX:*:* | *3000*:MPE/iX:*:*) + echo hppa1.0-hp-mpeix + exit 0 ;; + hp7??:OSF1:*:* | hp8?[79]:OSF1:*:* ) + echo hppa1.1-hp-osf + exit 0 ;; + hp8??:OSF1:*:*) + echo hppa1.0-hp-osf + exit 0 ;; + i*86:OSF1:*:*) + if [ -x /usr/sbin/sysversion ] ; then + echo ${UNAME_MACHINE}-unknown-osf1mk + else + echo ${UNAME_MACHINE}-unknown-osf1 + fi + exit 0 ;; + parisc*:Lites*:*:*) + echo hppa1.1-hp-lites + exit 0 ;; + C1*:ConvexOS:*:* | convex:ConvexOS:C1*:*) + echo c1-convex-bsd + exit 0 ;; + C2*:ConvexOS:*:* | convex:ConvexOS:C2*:*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + C34*:ConvexOS:*:* | convex:ConvexOS:C34*:*) + echo c34-convex-bsd + exit 0 ;; + C38*:ConvexOS:*:* | convex:ConvexOS:C38*:*) + echo c38-convex-bsd + exit 0 ;; + C4*:ConvexOS:*:* | convex:ConvexOS:C4*:*) + echo c4-convex-bsd + exit 0 ;; + CRAY*Y-MP:*:*:*) + echo ymp-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*[A-Z]90:*:*:*) + echo ${UNAME_MACHINE}-cray-unicos${UNAME_RELEASE} \ + | sed -e 's/CRAY.*\([A-Z]90\)/\1/' \ + -e y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ \ + -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*TS:*:*:*) + echo t90-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3D:*:*:*) + echo alpha-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*T3E:*:*:*) + echo alphaev5-cray-unicosmk${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + CRAY*SV1:*:*:*) + echo sv1-cray-unicos${UNAME_RELEASE} | sed -e 's/\.[^.]*$/.X/' + exit 0 ;; + F30[01]:UNIX_System_V:*:* | F700:UNIX_System_V:*:*) + FUJITSU_PROC=`uname -m | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + FUJITSU_SYS=`uname -p | tr 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz' | sed -e 's/\///'` + FUJITSU_REL=`echo ${UNAME_RELEASE} | sed -e 's/ /_/'` + echo "${FUJITSU_PROC}-fujitsu-${FUJITSU_SYS}${FUJITSU_REL}" + exit 0 ;; + i*86:BSD/386:*:* | i*86:BSD/OS:*:* | *:Ascend\ Embedded/OS:*:*) + echo ${UNAME_MACHINE}-pc-bsdi${UNAME_RELEASE} + exit 0 ;; + sparc*:BSD/OS:*:*) + echo sparc-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:BSD/OS:*:*) + echo ${UNAME_MACHINE}-unknown-bsdi${UNAME_RELEASE} + exit 0 ;; + *:FreeBSD:*:*) + # Determine whether the default compiler uses glibc. + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #if __GLIBC__ >= 2 + LIBC=gnu + #else + LIBC= + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + echo ${UNAME_MACHINE}-unknown-freebsd`echo ${UNAME_RELEASE}|sed -e 's/[-(].*//'`${LIBC:+-$LIBC} + exit 0 ;; + i*:CYGWIN*:*) + echo ${UNAME_MACHINE}-pc-cygwin + exit 0 ;; + i*:MINGW*:*) + echo ${UNAME_MACHINE}-pc-mingw32 + exit 0 ;; + i*:PW*:*) + echo ${UNAME_MACHINE}-pc-pw32 + exit 0 ;; + x86:Interix*:3*) + echo i386-pc-interix3 + exit 0 ;; + i*:Windows_NT*:* | Pentium*:Windows_NT*:*) + # How do we know it's Interix rather than the generic POSIX subsystem? + # It also conflicts with pre-2.0 versions of AT&T UWIN. Should we + # UNAME_MACHINE based on the output of uname instead of i386? + echo i386-pc-interix + exit 0 ;; + i*:UWIN*:*) + echo ${UNAME_MACHINE}-pc-uwin + exit 0 ;; + p*:CYGWIN*:*) + echo powerpcle-unknown-cygwin + exit 0 ;; + prep*:SunOS:5.*:*) + echo powerpcle-unknown-solaris2`echo ${UNAME_RELEASE}|sed -e 's/[^.]*//'` + exit 0 ;; + *:GNU:*:*) + echo `echo ${UNAME_MACHINE}|sed -e 's,[-/].*$,,'`-unknown-gnu`echo ${UNAME_RELEASE}|sed -e 's,/.*$,,'` + exit 0 ;; + i*86:Minix:*:*) + echo ${UNAME_MACHINE}-pc-minix + exit 0 ;; + arm*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + ia64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + m68*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + mips:Linux:*:*) + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #undef CPU + #undef mips + #undef mipsel + #if defined(__MIPSEL__) || defined(__MIPSEL) || defined(_MIPSEL) || defined(MIPSEL) + CPU=mipsel + #else + #if defined(__MIPSEB__) || defined(__MIPSEB) || defined(_MIPSEB) || defined(MIPSEB) + CPU=mips + #else + CPU= + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^CPU=` + rm -f $dummy.c && rmdir $tmpdir + test x"${CPU}" != x && echo "${CPU}-pc-linux-gnu" && exit 0 + ;; + ppc:Linux:*:*) + echo powerpc-unknown-linux-gnu + exit 0 ;; + ppc64:Linux:*:*) + echo powerpc64-unknown-linux-gnu + exit 0 ;; + alpha:Linux:*:*) + case `sed -n '/^cpu model/s/^.*: \(.*\)/\1/p' < /proc/cpuinfo` in + EV5) UNAME_MACHINE=alphaev5 ;; + EV56) UNAME_MACHINE=alphaev56 ;; + PCA56) UNAME_MACHINE=alphapca56 ;; + PCA57) UNAME_MACHINE=alphapca56 ;; + EV6) UNAME_MACHINE=alphaev6 ;; + EV67) UNAME_MACHINE=alphaev67 ;; + EV68*) UNAME_MACHINE=alphaev68 ;; + esac + objdump --private-headers /bin/sh | grep ld.so.1 >/dev/null + if test "$?" = 0 ; then LIBC="libc1" ; else LIBC="" ; fi + echo ${UNAME_MACHINE}-unknown-linux-gnu${LIBC} + exit 0 ;; + parisc:Linux:*:* | hppa:Linux:*:*) + # Look for CPU level + case `grep '^cpu[^a-z]*:' /proc/cpuinfo 2>/dev/null | cut -d' ' -f2` in + PA7*) echo hppa1.1-unknown-linux-gnu ;; + PA8*) echo hppa2.0-unknown-linux-gnu ;; + *) echo hppa-unknown-linux-gnu ;; + esac + exit 0 ;; + parisc64:Linux:*:* | hppa64:Linux:*:*) + echo hppa64-unknown-linux-gnu + exit 0 ;; + s390:Linux:*:* | s390x:Linux:*:*) + echo ${UNAME_MACHINE}-ibm-linux + exit 0 ;; + sh*:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + sparc:Linux:*:* | sparc64:Linux:*:*) + echo ${UNAME_MACHINE}-unknown-linux-gnu + exit 0 ;; + x86_64:Linux:*:*) + echo x86_64-unknown-linux-gnu + exit 0 ;; + i*86:Linux:*:*) + # The BFD linker knows what the default object file format is, so + # first see if it will tell us. cd to the root directory to prevent + # problems with other programs or directories called `ld' in the path. + # Set LC_ALL=C to ensure ld outputs messages in English. + ld_supported_targets=`cd /; LC_ALL=C ld --help 2>&1 \ + | sed -ne '/supported targets:/!d + s/[ ][ ]*/ /g + s/.*supported targets: *// + s/ .*// + p'` + case "$ld_supported_targets" in + elf32-i386) + TENTATIVE="${UNAME_MACHINE}-pc-linux-gnu" + ;; + a.out-i386-linux) + echo "${UNAME_MACHINE}-pc-linux-gnuaout" + exit 0 ;; + coff-i386) + echo "${UNAME_MACHINE}-pc-linux-gnucoff" + exit 0 ;; + "") + # Either a pre-BFD a.out linker (linux-gnuoldld) or + # one that does not give us useful --help. + echo "${UNAME_MACHINE}-pc-linux-gnuoldld" + exit 0 ;; + esac + # Determine whether the default compiler is a.out or elf + eval $set_cc_for_build + sed 's/^ //' << EOF >$dummy.c + #include <features.h> + #ifdef __ELF__ + # ifdef __GLIBC__ + # if __GLIBC__ >= 2 + LIBC=gnu + # else + LIBC=gnulibc1 + # endif + # else + LIBC=gnulibc1 + # endif + #else + #ifdef __INTEL_COMPILER + LIBC=gnu + #else + LIBC=gnuaout + #endif + #endif +EOF + eval `$CC_FOR_BUILD -E $dummy.c 2>/dev/null | grep ^LIBC=` + rm -f $dummy.c && rmdir $tmpdir + test x"${LIBC}" != x && echo "${UNAME_MACHINE}-pc-linux-${LIBC}" && exit 0 + test x"${TENTATIVE}" != x && echo "${TENTATIVE}" && exit 0 + ;; + i*86:DYNIX/ptx:4*:*) + # ptx 4.0 does uname -s correctly, with DYNIX/ptx in there. + # earlier versions are messed up and put the nodename in both + # sysname and nodename. + echo i386-sequent-sysv4 + exit 0 ;; + i*86:UNIX_SV:4.2MP:2.*) + # Unixware is an offshoot of SVR4, but it has its own version + # number series starting with 2... + # I am not positive that other SVR4 systems won't match this, + # I just have to hope. -- rms. + # Use sysv4.2uw... so that sysv4* matches it. + echo ${UNAME_MACHINE}-pc-sysv4.2uw${UNAME_VERSION} + exit 0 ;; + i*86:*:4.*:* | i*86:SYSTEM_V:4.*:*) + UNAME_REL=`echo ${UNAME_RELEASE} | sed 's/\/MP$//'` + if grep Novell /usr/include/link.h >/dev/null 2>/dev/null; then + echo ${UNAME_MACHINE}-univel-sysv${UNAME_REL} + else + echo ${UNAME_MACHINE}-pc-sysv${UNAME_REL} + fi + exit 0 ;; + i*86:*:5:[78]*) + case `/bin/uname -X | grep "^Machine"` in + *486*) UNAME_MACHINE=i486 ;; + *Pentium) UNAME_MACHINE=i586 ;; + *Pent*|*Celeron) UNAME_MACHINE=i686 ;; + esac + echo ${UNAME_MACHINE}-unknown-sysv${UNAME_RELEASE}${UNAME_SYSTEM}${UNAME_VERSION} + exit 0 ;; + i*86:*:3.2:*) + if test -f /usr/options/cb.name; then + UNAME_REL=`sed -n 's/.*Version //p' </usr/options/cb.name` + echo ${UNAME_MACHINE}-pc-isc$UNAME_REL + elif /bin/uname -X 2>/dev/null >/dev/null ; then + UNAME_REL=`(/bin/uname -X|grep Release|sed -e 's/.*= //')` + (/bin/uname -X|grep i80486 >/dev/null) && UNAME_MACHINE=i486 + (/bin/uname -X|grep '^Machine.*Pentium' >/dev/null) \ + && UNAME_MACHINE=i586 + (/bin/uname -X|grep '^Machine.*Pent *II' >/dev/null) \ + && UNAME_MACHINE=i686 + (/bin/uname -X|grep '^Machine.*Pentium Pro' >/dev/null) \ + && UNAME_MACHINE=i686 + echo ${UNAME_MACHINE}-pc-sco$UNAME_REL + else + echo ${UNAME_MACHINE}-pc-sysv32 + fi + exit 0 ;; + i*86:*DOS:*:*) + echo ${UNAME_MACHINE}-pc-msdosdjgpp + exit 0 ;; + pc:*:*:*) + # Left here for compatibility: + # uname -m prints for DJGPP always 'pc', but it prints nothing about + # the processor, so we play safe by assuming i386. + echo i386-pc-msdosdjgpp + exit 0 ;; + Intel:Mach:3*:*) + echo i386-pc-mach3 + exit 0 ;; + paragon:*:*:*) + echo i860-intel-osf1 + exit 0 ;; + i860:*:4.*:*) # i860-SVR4 + if grep Stardent /usr/include/sys/uadmin.h >/dev/null 2>&1 ; then + echo i860-stardent-sysv${UNAME_RELEASE} # Stardent Vistra i860-SVR4 + else # Add other i860-SVR4 vendors below as they are discovered. + echo i860-unknown-sysv${UNAME_RELEASE} # Unknown i860-SVR4 + fi + exit 0 ;; + mini*:CTIX:SYS*5:*) + # "miniframe" + echo m68010-convergent-sysv + exit 0 ;; + mc68k:UNIX:SYSTEM5:3.51m) + echo m68k-convergent-sysv + exit 0 ;; + M68*:*:R3V[567]*:*) + test -r /sysV68 && echo 'm68k-motorola-sysv' && exit 0 ;; + 3[34]??:*:4.0:3.0 | 3[34]??A:*:4.0:3.0 | 3[34]??,*:*:4.0:3.0 | 3[34]??/*:*:4.0:3.0 | 4400:*:4.0:3.0 | 4850:*:4.0:3.0 | SKA40:*:4.0:3.0) + OS_REL='' + test -r /etc/.relid \ + && OS_REL=.`sed -n 's/[^ ]* [^ ]* \([0-9][0-9]\).*/\1/p' < /etc/.relid` + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4.3${OS_REL} && exit 0 + /bin/uname -p 2>/dev/null | /bin/grep entium >/dev/null \ + && echo i586-ncr-sysv4.3${OS_REL} && exit 0 ;; + 3[34]??:*:4.0:* | 3[34]??,*:*:4.0:*) + /bin/uname -p 2>/dev/null | grep 86 >/dev/null \ + && echo i486-ncr-sysv4 && exit 0 ;; + m68*:LynxOS:2.*:* | m68*:LynxOS:3.0*:*) + echo m68k-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + mc68030:UNIX_System_V:4.*:*) + echo m68k-atari-sysv4 + exit 0 ;; + i*86:LynxOS:2.*:* | i*86:LynxOS:3.[01]*:* | i*86:LynxOS:4.0*:*) + echo i386-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + TSUNAMI:LynxOS:2.*:*) + echo sparc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + rs6000:LynxOS:2.*:*) + echo rs6000-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + PowerPC:LynxOS:2.*:* | PowerPC:LynxOS:3.[01]*:* | PowerPC:LynxOS:4.0*:*) + echo powerpc-unknown-lynxos${UNAME_RELEASE} + exit 0 ;; + SM[BE]S:UNIX_SV:*:*) + echo mips-dde-sysv${UNAME_RELEASE} + exit 0 ;; + RM*:ReliantUNIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + RM*:SINIX-*:*:*) + echo mips-sni-sysv4 + exit 0 ;; + *:SINIX-*:*:*) + if uname -p 2>/dev/null >/dev/null ; then + UNAME_MACHINE=`(uname -p) 2>/dev/null` + echo ${UNAME_MACHINE}-sni-sysv4 + else + echo ns32k-sni-sysv + fi + exit 0 ;; + PENTIUM:*:4.0*:*) # Unisys `ClearPath HMP IX 4000' SVR4/MP effort + # says <Richard.M.Bartel@ccMail.Census.GOV> + echo i586-unisys-sysv4 + exit 0 ;; + *:UNIX_System_V:4*:FTX*) + # From Gerald Hewes <hewes@openmarket.com>. + # How about differentiating between stratus architectures? -djm + echo hppa1.1-stratus-sysv4 + exit 0 ;; + *:*:*:FTX*) + # From seanf@swdc.stratus.com. + echo i860-stratus-sysv4 + exit 0 ;; + *:VOS:*:*) + # From Paul.Green@stratus.com. + echo hppa1.1-stratus-vos + exit 0 ;; + mc68*:A/UX:*:*) + echo m68k-apple-aux${UNAME_RELEASE} + exit 0 ;; + news*:NEWS-OS:6*:*) + echo mips-sony-newsos6 + exit 0 ;; + R[34]000:*System_V*:*:* | R4000:UNIX_SYSV:*:* | R*000:UNIX_SV:*:*) + if [ -d /usr/nec ]; then + echo mips-nec-sysv${UNAME_RELEASE} + else + echo mips-unknown-sysv${UNAME_RELEASE} + fi + exit 0 ;; + BeBox:BeOS:*:*) # BeOS running on hardware made by Be, PPC only. + echo powerpc-be-beos + exit 0 ;; + BeMac:BeOS:*:*) # BeOS running on Mac or Mac clone, PPC only. + echo powerpc-apple-beos + exit 0 ;; + BePC:BeOS:*:*) # BeOS running on Intel PC compatible. + echo i586-pc-beos + exit 0 ;; + SX-4:SUPER-UX:*:*) + echo sx4-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-5:SUPER-UX:*:*) + echo sx5-nec-superux${UNAME_RELEASE} + exit 0 ;; + SX-6:SUPER-UX:*:*) + echo sx6-nec-superux${UNAME_RELEASE} + exit 0 ;; + Power*:Rhapsody:*:*) + echo powerpc-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Rhapsody:*:*) + echo ${UNAME_MACHINE}-apple-rhapsody${UNAME_RELEASE} + exit 0 ;; + *:Darwin:*:*) + echo `uname -p`-apple-darwin${UNAME_RELEASE} + exit 0 ;; + *:procnto*:*:* | *:QNX:[0123456789]*:*) + UNAME_PROCESSOR=`uname -p` + if test "$UNAME_PROCESSOR" = "x86"; then + UNAME_PROCESSOR=i386 + UNAME_MACHINE=pc + fi + echo ${UNAME_PROCESSOR}-${UNAME_MACHINE}-nto-qnx${UNAME_RELEASE} + exit 0 ;; + *:QNX:*:4*) + echo i386-pc-qnx + exit 0 ;; + NSR-[DGKLNPTVW]:NONSTOP_KERNEL:*:*) + echo nsr-tandem-nsk${UNAME_RELEASE} + exit 0 ;; + *:NonStop-UX:*:*) + echo mips-compaq-nonstopux + exit 0 ;; + BS2000:POSIX*:*:*) + echo bs2000-siemens-sysv + exit 0 ;; + DS/*:UNIX_System_V:*:*) + echo ${UNAME_MACHINE}-${UNAME_SYSTEM}-${UNAME_RELEASE} + exit 0 ;; + *:Plan9:*:*) + # "uname -m" is not consistent, so use $cputype instead. 386 + # is converted to i386 for consistency with other x86 + # operating systems. + if test "$cputype" = "386"; then + UNAME_MACHINE=i386 + else + UNAME_MACHINE="$cputype" + fi + echo ${UNAME_MACHINE}-unknown-plan9 + exit 0 ;; + i*86:OS/2:*:*) + # If we were able to find `uname', then EMX Unix compatibility + # is probably installed. + echo ${UNAME_MACHINE}-pc-os2-emx + exit 0 ;; + *:TOPS-10:*:*) + echo pdp10-unknown-tops10 + exit 0 ;; + *:TENEX:*:*) + echo pdp10-unknown-tenex + exit 0 ;; + KS10:TOPS-20:*:* | KL10:TOPS-20:*:* | TYPE4:TOPS-20:*:*) + echo pdp10-dec-tops20 + exit 0 ;; + XKL-1:TOPS-20:*:* | TYPE5:TOPS-20:*:*) + echo pdp10-xkl-tops20 + exit 0 ;; + *:TOPS-20:*:*) + echo pdp10-unknown-tops20 + exit 0 ;; + *:ITS:*:*) + echo pdp10-unknown-its + exit 0 ;; + i*86:XTS-300:*:STOP) + echo ${UNAME_MACHINE}-unknown-stop + exit 0 ;; + i*86:atheos:*:*) + echo ${UNAME_MACHINE}-unknown-atheos + exit 0 ;; +esac + +#echo '(No uname command or uname output not recognized.)' 1>&2 +#echo "${UNAME_MACHINE}:${UNAME_SYSTEM}:${UNAME_RELEASE}:${UNAME_VERSION}" 1>&2 + +eval $set_cc_for_build +cat >$dummy.c <<EOF +#ifdef _SEQUENT_ +# include <sys/types.h> +# include <sys/utsname.h> +#endif +main () +{ +#if defined (sony) +#if defined (MIPSEB) + /* BFD wants "bsd" instead of "newsos". Perhaps BFD should be changed, + I don't know.... */ + printf ("mips-sony-bsd\n"); exit (0); +#else +#include <sys/param.h> + printf ("m68k-sony-newsos%s\n", +#ifdef NEWSOS4 + "4" +#else + "" +#endif + ); exit (0); +#endif +#endif + +#if defined (__arm) && defined (__acorn) && defined (__unix) + printf ("arm-acorn-riscix"); exit (0); +#endif + +#if defined (hp300) && !defined (hpux) + printf ("m68k-hp-bsd\n"); exit (0); +#endif + +#if defined (NeXT) +#if !defined (__ARCHITECTURE__) +#define __ARCHITECTURE__ "m68k" +#endif + int version; + version=`(hostinfo | sed -n 's/.*NeXT Mach \([0-9]*\).*/\1/p') 2>/dev/null`; + if (version < 4) + printf ("%s-next-nextstep%d\n", __ARCHITECTURE__, version); + else + printf ("%s-next-openstep%d\n", __ARCHITECTURE__, version); + exit (0); +#endif + +#if defined (MULTIMAX) || defined (n16) +#if defined (UMAXV) + printf ("ns32k-encore-sysv\n"); exit (0); +#else +#if defined (CMU) + printf ("ns32k-encore-mach\n"); exit (0); +#else + printf ("ns32k-encore-bsd\n"); exit (0); +#endif +#endif +#endif + +#if defined (__386BSD__) + printf ("i386-pc-bsd\n"); exit (0); +#endif + +#if defined (sequent) +#if defined (i386) + printf ("i386-sequent-dynix\n"); exit (0); +#endif +#if defined (ns32000) + printf ("ns32k-sequent-dynix\n"); exit (0); +#endif +#endif + +#if defined (_SEQUENT_) + struct utsname un; + + uname(&un); + + if (strncmp(un.version, "V2", 2) == 0) { + printf ("i386-sequent-ptx2\n"); exit (0); + } + if (strncmp(un.version, "V1", 2) == 0) { /* XXX is V1 correct? */ + printf ("i386-sequent-ptx1\n"); exit (0); + } + printf ("i386-sequent-ptx\n"); exit (0); + +#endif + +#if defined (vax) +# if !defined (ultrix) +# include <sys/param.h> +# if defined (BSD) +# if BSD == 43 + printf ("vax-dec-bsd4.3\n"); exit (0); +# else +# if BSD == 199006 + printf ("vax-dec-bsd4.3reno\n"); exit (0); +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# endif +# else + printf ("vax-dec-bsd\n"); exit (0); +# endif +# else + printf ("vax-dec-ultrix\n"); exit (0); +# endif +#endif + +#if defined (alliant) && defined (i860) + printf ("i860-alliant-bsd\n"); exit (0); +#endif + + exit (1); +} +EOF + +$CC_FOR_BUILD $dummy.c -o $dummy 2>/dev/null && $dummy && rm -f $dummy.c $dummy && rmdir $tmpdir && exit 0 +rm -f $dummy.c $dummy && rmdir $tmpdir + +# Apollos put the system type in the environment. + +test -d /usr/apollo && { echo ${ISP}-apollo-${SYSTYPE}; exit 0; } + +# Convex versions that predate uname can use getsysinfo(1) + +if [ -x /usr/convex/getsysinfo ] +then + case `getsysinfo -f cpu_type` in + c1*) + echo c1-convex-bsd + exit 0 ;; + c2*) + if getsysinfo -f scalar_acc + then echo c32-convex-bsd + else echo c2-convex-bsd + fi + exit 0 ;; + c34*) + echo c34-convex-bsd + exit 0 ;; + c38*) + echo c38-convex-bsd + exit 0 ;; + c4*) + echo c4-convex-bsd + exit 0 ;; + esac +fi + +cat >&2 <<EOF +$0: unable to guess system type + +This script, last modified $timestamp, has failed to recognize +the operating system you are using. It is advised that you +download the most up to date version of the config scripts from + + ftp://ftp.gnu.org/pub/gnu/config/ + +If the version you run ($0) is already up to date, please +send the following data and any information you think might be +pertinent to <config-patches@gnu.org> in order to provide the needed +information to handle your system. + +config.guess timestamp = $timestamp + +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null` + +hostinfo = `(hostinfo) 2>/dev/null` +/bin/universe = `(/bin/universe) 2>/dev/null` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null` +/bin/arch = `(/bin/arch) 2>/dev/null` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null` + +UNAME_MACHINE = ${UNAME_MACHINE} +UNAME_RELEASE = ${UNAME_RELEASE} +UNAME_SYSTEM = ${UNAME_SYSTEM} +UNAME_VERSION = ${UNAME_VERSION} +EOF + +exit 1 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/trunk/config.h.in b/trunk/config.h.in new file mode 100644 index 0000000..a6c7dcc --- /dev/null +++ b/trunk/config.h.in @@ -0,0 +1,73 @@ +/* config.h.in. Generated from configure.in by autoheader. */ + +/* Define to 1 if you have the <dlfcn.h> header file. */ +#undef HAVE_DLFCN_H + +/* Define if FTW_ACTIONRETVAL is supported. */ +#undef HAVE_FTW_ACTIONRETVAL + +/* Define to 1 if you have the <inttypes.h> header file. */ +#undef HAVE_INTTYPES_H + +/* Define to 1 if you have the `elf' library (-lelf). */ +#undef HAVE_LIBELF + +/* Define to 1 if you have the `selinux' library (-lselinux). */ +#undef HAVE_LIBSELINUX + +/* Define to 1 if you have the <memory.h> header file. */ +#undef HAVE_MEMORY_H + +/* Define to 1 if you have the <selinux/selinux.h> header file. */ +#undef HAVE_SELINUX_SELINUX_H + +/* Define to 1 if you have the <stdint.h> header file. */ +#undef HAVE_STDINT_H + +/* Define to 1 if you have the <stdlib.h> header file. */ +#undef HAVE_STDLIB_H + +/* Define to 1 if you have the <strings.h> header file. */ +#undef HAVE_STRINGS_H + +/* Define to 1 if you have the <string.h> header file. */ +#undef HAVE_STRING_H + +/* Define to 1 if you have the <sys/stat.h> header file. */ +#undef HAVE_SYS_STAT_H + +/* Define to 1 if you have the <sys/types.h> header file. */ +#undef HAVE_SYS_TYPES_H + +/* Define to 1 if you have the <unistd.h> header file. */ +#undef HAVE_UNISTD_H + +/* Name of package */ +#undef PACKAGE + +/* Define to the address where bug reports for this package should be sent. */ +#undef PACKAGE_BUGREPORT + +/* Define to the full name of this package. */ +#undef PACKAGE_NAME + +/* Define to the full name and version of this package. */ +#undef PACKAGE_STRING + +/* Define to the one symbol short name of this package. */ +#undef PACKAGE_TARNAME + +/* Define to the version of this package. */ +#undef PACKAGE_VERSION + +/* Define to 1 if you have the ANSI C header files. */ +#undef STDC_HEADERS + +/* Version number of package */ +#undef VERSION + +/* Number of bits in a file offset, on hosts where this is settable. */ +#undef _FILE_OFFSET_BITS + +/* Define for large files, on AIX-style hosts. */ +#undef _LARGE_FILES diff --git a/trunk/config.sub b/trunk/config.sub new file mode 100755 index 0000000..1dea9b7 --- /dev/null +++ b/trunk/config.sub @@ -0,0 +1,1470 @@ +#! /bin/sh +# Configuration validation subroutine script. +# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, +# 2000, 2001, 2002 Free Software Foundation, Inc. + +timestamp='2002-09-05' + +# This file is (in principle) common to ALL GNU software. +# The presence of a machine in this file suggests that SOME GNU software +# can handle that machine. It does not imply ALL GNU software can. +# +# This file is free software; you can 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., 59 Temple Place - Suite 330, +# Boston, MA 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Please send patches to <config-patches@gnu.org>. Submit a context +# diff and a properly formatted ChangeLog entry. +# +# Configuration subroutine to validate and canonicalize a configuration type. +# Supply the specified configuration type as an argument. +# If it is invalid, we print an error message on stderr and exit with code 1. +# Otherwise, we print the canonical config type on stdout and succeed. + +# This file is supposed to be the same for all GNU packages +# and recognize all the CPU types, system types and aliases +# that are meaningful with *any* GNU software. +# Each package is responsible for reporting which valid configurations +# it does not support. The user should be able to distinguish +# a failure to support a valid configuration from a meaningless +# configuration. + +# The goal of this file is to map all the various variations of a given +# machine specification into a single specification in the form: +# CPU_TYPE-MANUFACTURER-OPERATING_SYSTEM +# or in some cases, the newer four-part form: +# CPU_TYPE-MANUFACTURER-KERNEL-OPERATING_SYSTEM +# It is wrong to echo any other type of specification. + +me=`echo "$0" | sed -e 's,.*/,,'` + +usage="\ +Usage: $0 [OPTION] CPU-MFR-OPSYS + $0 [OPTION] ALIAS + +Canonicalize a configuration name. + +Operation modes: + -h, --help print this help, then exit + -t, --time-stamp print date of last modification, then exit + -v, --version print version number, then exit + +Report bugs and patches to <config-patches@gnu.org>." + +version="\ +GNU config.sub ($timestamp) + +Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. + +This is free software; see the source for copying conditions. There is NO +warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." + +help=" +Try \`$me --help' for more information." + +# Parse command line +while test $# -gt 0 ; do + case $1 in + --time-stamp | --time* | -t ) + echo "$timestamp" ; exit 0 ;; + --version | -v ) + echo "$version" ; exit 0 ;; + --help | --h* | -h ) + echo "$usage"; exit 0 ;; + -- ) # Stop option processing + shift; break ;; + - ) # Use stdin as input. + break ;; + -* ) + echo "$me: invalid option $1$help" + exit 1 ;; + + *local*) + # First pass through any local machine types. + echo $1 + exit 0;; + + * ) + break ;; + esac +done + +case $# in + 0) echo "$me: missing argument$help" >&2 + exit 1;; + 1) ;; + *) echo "$me: too many arguments$help" >&2 + exit 1;; +esac + +# Separate what the user gave into CPU-COMPANY and OS or KERNEL-OS (if any). +# Here we must recognize all the valid KERNEL-OS combinations. +maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'` +case $maybe_os in + nto-qnx* | linux-gnu* | freebsd*-gnu* | storm-chaos* | os2-emx* | windows32-* | rtmk-nova*) + os=-$maybe_os + basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'` + ;; + *) + basic_machine=`echo $1 | sed 's/-[^-]*$//'` + if [ $basic_machine != $1 ] + then os=`echo $1 | sed 's/.*-/-/'` + else os=; fi + ;; +esac + +### Let's recognize common machines as not being operating systems so +### that things like config.sub decstation-3100 work. We also +### recognize some manufacturers as not being operating systems, so we +### can provide default operating systems below. +case $os in + -sun*os*) + # Prevent following clause from handling this invalid input. + ;; + -dec* | -mips* | -sequent* | -encore* | -pc532* | -sgi* | -sony* | \ + -att* | -7300* | -3300* | -delta* | -motorola* | -sun[234]* | \ + -unicom* | -ibm* | -next | -hp | -isi* | -apollo | -altos* | \ + -convergent* | -ncr* | -news | -32* | -3600* | -3100* | -hitachi* |\ + -c[123]* | -convex* | -sun | -crds | -omron* | -dg | -ultra | -tti* | \ + -harris | -dolphin | -highlevel | -gould | -cbm | -ns | -masscomp | \ + -apple | -axis) + os= + basic_machine=$1 + ;; + -sim | -cisco | -oki | -wec | -winbond) + os= + basic_machine=$1 + ;; + -scout) + ;; + -wrs) + os=-vxworks + basic_machine=$1 + ;; + -chorusos*) + os=-chorusos + basic_machine=$1 + ;; + -chorusrdb) + os=-chorusrdb + basic_machine=$1 + ;; + -hiux*) + os=-hiuxwe2 + ;; + -sco5) + os=-sco3.2v5 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco4) + os=-sco3.2v4 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2.[4-9]*) + os=`echo $os | sed -e 's/sco3.2./sco3.2v/'` + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco3.2v[4-9]*) + # Don't forget version if it is 3.2v4 or newer. + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -sco*) + os=-sco3.2v2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -udk*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -isc) + os=-isc2.2 + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -clix*) + basic_machine=clipper-intergraph + ;; + -isc*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-pc/'` + ;; + -lynx*) + os=-lynxos + ;; + -ptx*) + basic_machine=`echo $1 | sed -e 's/86-.*/86-sequent/'` + ;; + -windowsnt*) + os=`echo $os | sed -e 's/windowsnt/winnt/'` + ;; + -psos*) + os=-psos + ;; + -mint | -mint[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; +esac + +# Decode aliases for certain CPU-COMPANY combinations. +case $basic_machine in + # Recognize the basic CPU types without company name. + # Some are omitted here because they have special meanings below. + 1750a | 580 \ + | a29k \ + | alpha | alphaev[4-8] | alphaev56 | alphaev6[78] | alphapca5[67] \ + | alpha64 | alpha64ev[4-8] | alpha64ev56 | alpha64ev6[78] | alpha64pca5[67] \ + | arc | arm | arm[bl]e | arme[lb] | armv[2345] | armv[345][lb] | avr \ + | clipper \ + | d10v | d30v | dlx | dsp16xx \ + | fr30 | frv \ + | h8300 | h8500 | hppa | hppa1.[01] | hppa2.0 | hppa2.0[nw] | hppa64 \ + | i370 | i860 | i960 | ia64 \ + | ip2k \ + | m32r | m68000 | m68k | m88k | mcore \ + | mips | mipsbe | mipseb | mipsel | mipsle \ + | mips16 \ + | mips64 | mips64el \ + | mips64vr | mips64vrel \ + | mips64orion | mips64orionel \ + | mips64vr4100 | mips64vr4100el \ + | mips64vr4300 | mips64vr4300el \ + | mips64vr5000 | mips64vr5000el \ + | mipsisa32 | mipsisa32el \ + | mipsisa64 | mipsisa64el \ + | mipsisa64sb1 | mipsisa64sb1el \ + | mipsisa64sr71k | mipsisa64sr71kel \ + | mipstx39 | mipstx39el \ + | mn10200 | mn10300 \ + | ns16k | ns32k \ + | openrisc | or32 \ + | pdp10 | pdp11 | pj | pjl \ + | powerpc | powerpc64 | powerpc64le | powerpcle | ppcbe \ + | pyramid \ + | sh | sh[1234] | sh3e | sh[34]eb | shbe | shle | sh[1234]le | sh3ele \ + | sh64 | sh64le \ + | sparc | sparc64 | sparc86x | sparclet | sparclite | sparcv9 | sparcv9b \ + | strongarm \ + | tahoe | thumb | tic80 | tron \ + | v850 | v850e \ + | we32k \ + | x86 | xscale | xstormy16 | xtensa \ + | z8k) + basic_machine=$basic_machine-unknown + ;; + m6811 | m68hc11 | m6812 | m68hc12) + # Motorola 68HC11/12. + basic_machine=$basic_machine-unknown + os=-none + ;; + m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k) + ;; + + # We use `pc' rather than `unknown' + # because (1) that's what they normally are, and + # (2) the word "unknown" tends to confuse beginning users. + i*86 | x86_64) + basic_machine=$basic_machine-pc + ;; + # Object if more than one company name word. + *-*-*) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; + # Recognize the basic CPU types with company name. + 580-* \ + | a29k-* \ + | alpha-* | alphaev[4-8]-* | alphaev56-* | alphaev6[78]-* \ + | alpha64-* | alpha64ev[4-8]-* | alpha64ev56-* | alpha64ev6[78]-* \ + | alphapca5[67]-* | alpha64pca5[67]-* | arc-* \ + | arm-* | armbe-* | armle-* | armeb-* | armv*-* \ + | avr-* \ + | bs2000-* \ + | c[123]* | c30-* | [cjt]90-* | c4x-* | c54x-* \ + | clipper-* | cydra-* \ + | d10v-* | d30v-* | dlx-* \ + | elxsi-* \ + | f30[01]-* | f700-* | fr30-* | frv-* | fx80-* \ + | h8300-* | h8500-* \ + | hppa-* | hppa1.[01]-* | hppa2.0-* | hppa2.0[nw]-* | hppa64-* \ + | i*86-* | i860-* | i960-* | ia64-* \ + | ip2k-* \ + | m32r-* \ + | m68000-* | m680[012346]0-* | m68360-* | m683?2-* | m68k-* \ + | m88110-* | m88k-* | mcore-* \ + | mips-* | mipsbe-* | mipseb-* | mipsel-* | mipsle-* \ + | mips16-* \ + | mips64-* | mips64el-* \ + | mips64vr-* | mips64vrel-* \ + | mips64orion-* | mips64orionel-* \ + | mips64vr4100-* | mips64vr4100el-* \ + | mips64vr4300-* | mips64vr4300el-* \ + | mips64vr5000-* | mips64vr5000el-* \ + | mipsisa32-* | mipsisa32el-* \ + | mipsisa64-* | mipsisa64el-* \ + | mipsisa64sb1-* | mipsisa64sb1el-* \ + | mipsisa64sr71k-* | mipsisa64sr71kel-* \ + | mipstx39 | mipstx39el \ + | none-* | np1-* | ns16k-* | ns32k-* \ + | orion-* \ + | pdp10-* | pdp11-* | pj-* | pjl-* | pn-* | power-* \ + | powerpc-* | powerpc64-* | powerpc64le-* | powerpcle-* | ppcbe-* \ + | pyramid-* \ + | romp-* | rs6000-* \ + | sh-* | sh[1234]-* | sh3e-* | sh[34]eb-* | shbe-* \ + | shle-* | sh[1234]le-* | sh3ele-* | sh64-* | sh64le-* \ + | sparc-* | sparc64-* | sparc86x-* | sparclet-* | sparclite-* \ + | sparcv9-* | sparcv9b-* | strongarm-* | sv1-* | sx?-* \ + | tahoe-* | thumb-* | tic30-* | tic4x-* | tic54x-* | tic80-* | tron-* \ + | v850-* | v850e-* | vax-* \ + | we32k-* \ + | x86-* | x86_64-* | xps100-* | xscale-* | xstormy16-* \ + | xtensa-* \ + | ymp-* \ + | z8k-*) + ;; + # Recognize the various machine names and aliases which stand + # for a CPU type and a company and sometimes even an OS. + 386bsd) + basic_machine=i386-unknown + os=-bsd + ;; + 3b1 | 7300 | 7300-att | att-7300 | pc7300 | safari | unixpc) + basic_machine=m68000-att + ;; + 3b*) + basic_machine=we32k-att + ;; + a29khif) + basic_machine=a29k-amd + os=-udi + ;; + adobe68k) + basic_machine=m68010-adobe + os=-scout + ;; + alliant | fx80) + basic_machine=fx80-alliant + ;; + altos | altos3068) + basic_machine=m68k-altos + ;; + am29k) + basic_machine=a29k-none + os=-bsd + ;; + amdahl) + basic_machine=580-amdahl + os=-sysv + ;; + amiga | amiga-*) + basic_machine=m68k-unknown + ;; + amigaos | amigados) + basic_machine=m68k-unknown + os=-amigaos + ;; + amigaunix | amix) + basic_machine=m68k-unknown + os=-sysv4 + ;; + apollo68) + basic_machine=m68k-apollo + os=-sysv + ;; + apollo68bsd) + basic_machine=m68k-apollo + os=-bsd + ;; + aux) + basic_machine=m68k-apple + os=-aux + ;; + balance) + basic_machine=ns32k-sequent + os=-dynix + ;; + c90) + basic_machine=c90-cray + os=-unicos + ;; + convex-c1) + basic_machine=c1-convex + os=-bsd + ;; + convex-c2) + basic_machine=c2-convex + os=-bsd + ;; + convex-c32) + basic_machine=c32-convex + os=-bsd + ;; + convex-c34) + basic_machine=c34-convex + os=-bsd + ;; + convex-c38) + basic_machine=c38-convex + os=-bsd + ;; + cray | j90) + basic_machine=j90-cray + os=-unicos + ;; + crds | unos) + basic_machine=m68k-crds + ;; + cris | cris-* | etrax*) + basic_machine=cris-axis + ;; + da30 | da30-*) + basic_machine=m68k-da30 + ;; + decstation | decstation-3100 | pmax | pmax-* | pmin | dec3100 | decstatn) + basic_machine=mips-dec + ;; + decsystem10* | dec10*) + basic_machine=pdp10-dec + os=-tops10 + ;; + decsystem20* | dec20*) + basic_machine=pdp10-dec + os=-tops20 + ;; + delta | 3300 | motorola-3300 | motorola-delta \ + | 3300-motorola | delta-motorola) + basic_machine=m68k-motorola + ;; + delta88) + basic_machine=m88k-motorola + os=-sysv3 + ;; + dpx20 | dpx20-*) + basic_machine=rs6000-bull + os=-bosx + ;; + dpx2* | dpx2*-bull) + basic_machine=m68k-bull + os=-sysv3 + ;; + ebmon29k) + basic_machine=a29k-amd + os=-ebmon + ;; + elxsi) + basic_machine=elxsi-elxsi + os=-bsd + ;; + encore | umax | mmax) + basic_machine=ns32k-encore + ;; + es1800 | OSE68k | ose68k | ose | OSE) + basic_machine=m68k-ericsson + os=-ose + ;; + fx2800) + basic_machine=i860-alliant + ;; + genix) + basic_machine=ns32k-ns + ;; + gmicro) + basic_machine=tron-gmicro + os=-sysv + ;; + go32) + basic_machine=i386-pc + os=-go32 + ;; + h3050r* | hiux*) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + h8300hms) + basic_machine=h8300-hitachi + os=-hms + ;; + h8300xray) + basic_machine=h8300-hitachi + os=-xray + ;; + h8500hms) + basic_machine=h8500-hitachi + os=-hms + ;; + harris) + basic_machine=m88k-harris + os=-sysv3 + ;; + hp300-*) + basic_machine=m68k-hp + ;; + hp300bsd) + basic_machine=m68k-hp + os=-bsd + ;; + hp300hpux) + basic_machine=m68k-hp + os=-hpux + ;; + hp3k9[0-9][0-9] | hp9[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k2[0-9][0-9] | hp9k31[0-9]) + basic_machine=m68000-hp + ;; + hp9k3[2-9][0-9]) + basic_machine=m68k-hp + ;; + hp9k6[0-9][0-9] | hp6[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hp9k7[0-79][0-9] | hp7[0-79][0-9]) + basic_machine=hppa1.1-hp + ;; + hp9k78[0-9] | hp78[0-9]) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[67]1 | hp8[67]1 | hp9k80[24] | hp80[24] | hp9k8[78]9 | hp8[78]9 | hp9k893 | hp893) + # FIXME: really hppa2.0-hp + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][13679] | hp8[0-9][13679]) + basic_machine=hppa1.1-hp + ;; + hp9k8[0-9][0-9] | hp8[0-9][0-9]) + basic_machine=hppa1.0-hp + ;; + hppa-next) + os=-nextstep3 + ;; + hppaosf) + basic_machine=hppa1.1-hp + os=-osf + ;; + hppro) + basic_machine=hppa1.1-hp + os=-proelf + ;; + i370-ibm* | ibm*) + basic_machine=i370-ibm + ;; +# I'm not sure what "Sysv32" means. Should this be sysv3.2? + i*86v32) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv32 + ;; + i*86v4*) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv4 + ;; + i*86v) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-sysv + ;; + i*86sol2) + basic_machine=`echo $1 | sed -e 's/86.*/86-pc/'` + os=-solaris2 + ;; + i386mach) + basic_machine=i386-mach + os=-mach + ;; + i386-vsta | vsta) + basic_machine=i386-unknown + os=-vsta + ;; + iris | iris4d) + basic_machine=mips-sgi + case $os in + -irix*) + ;; + *) + os=-irix4 + ;; + esac + ;; + isi68 | isi) + basic_machine=m68k-isi + os=-sysv + ;; + m88k-omron*) + basic_machine=m88k-omron + ;; + magnum | m3230) + basic_machine=mips-mips + os=-sysv + ;; + merlin) + basic_machine=ns32k-utek + os=-sysv + ;; + mingw32) + basic_machine=i386-pc + os=-mingw32 + ;; + miniframe) + basic_machine=m68000-convergent + ;; + *mint | -mint[0-9]* | *MiNT | *MiNT[0-9]*) + basic_machine=m68k-atari + os=-mint + ;; + mips3*-*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'` + ;; + mips3*) + basic_machine=`echo $basic_machine | sed -e 's/mips3/mips64/'`-unknown + ;; + mmix*) + basic_machine=mmix-knuth + os=-mmixware + ;; + monitor) + basic_machine=m68k-rom68k + os=-coff + ;; + morphos) + basic_machine=powerpc-unknown + os=-morphos + ;; + msdos) + basic_machine=i386-pc + os=-msdos + ;; + mvs) + basic_machine=i370-ibm + os=-mvs + ;; + ncr3000) + basic_machine=i486-ncr + os=-sysv4 + ;; + netbsd386) + basic_machine=i386-unknown + os=-netbsd + ;; + netwinder) + basic_machine=armv4l-rebel + os=-linux + ;; + news | news700 | news800 | news900) + basic_machine=m68k-sony + os=-newsos + ;; + news1000) + basic_machine=m68030-sony + os=-newsos + ;; + news-3600 | risc-news) + basic_machine=mips-sony + os=-newsos + ;; + necv70) + basic_machine=v70-nec + os=-sysv + ;; + next | m*-next ) + basic_machine=m68k-next + case $os in + -nextstep* ) + ;; + -ns2*) + os=-nextstep2 + ;; + *) + os=-nextstep3 + ;; + esac + ;; + nh3000) + basic_machine=m68k-harris + os=-cxux + ;; + nh[45]000) + basic_machine=m88k-harris + os=-cxux + ;; + nindy960) + basic_machine=i960-intel + os=-nindy + ;; + mon960) + basic_machine=i960-intel + os=-mon960 + ;; + nonstopux) + basic_machine=mips-compaq + os=-nonstopux + ;; + np1) + basic_machine=np1-gould + ;; + nsr-tandem) + basic_machine=nsr-tandem + ;; + op50n-* | op60c-*) + basic_machine=hppa1.1-oki + os=-proelf + ;; + or32 | or32-*) + basic_machine=or32-unknown + os=-coff + ;; + OSE68000 | ose68000) + basic_machine=m68000-ericsson + os=-ose + ;; + os68k) + basic_machine=m68k-none + os=-os68k + ;; + pa-hitachi) + basic_machine=hppa1.1-hitachi + os=-hiuxwe2 + ;; + paragon) + basic_machine=i860-intel + os=-osf + ;; + pbd) + basic_machine=sparc-tti + ;; + pbb) + basic_machine=m68k-tti + ;; + pc532 | pc532-*) + basic_machine=ns32k-pc532 + ;; + pentium | p5 | k5 | k6 | nexgen | viac3) + basic_machine=i586-pc + ;; + pentiumpro | p6 | 6x86 | athlon | athlon_*) + basic_machine=i686-pc + ;; + pentiumii | pentium2) + basic_machine=i686-pc + ;; + pentium-* | p5-* | k5-* | k6-* | nexgen-* | viac3-*) + basic_machine=i586-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumpro-* | p6-* | 6x86-* | athlon-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pentiumii-* | pentium2-*) + basic_machine=i686-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + pn) + basic_machine=pn-gould + ;; + power) basic_machine=power-ibm + ;; + ppc) basic_machine=powerpc-unknown + ;; + ppc-*) basic_machine=powerpc-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppcle | powerpclittle | ppc-le | powerpc-little) + basic_machine=powerpcle-unknown + ;; + ppcle-* | powerpclittle-*) + basic_machine=powerpcle-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64) basic_machine=powerpc64-unknown + ;; + ppc64-*) basic_machine=powerpc64-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ppc64le | powerpc64little | ppc64-le | powerpc64-little) + basic_machine=powerpc64le-unknown + ;; + ppc64le-* | powerpc64little-*) + basic_machine=powerpc64le-`echo $basic_machine | sed 's/^[^-]*-//'` + ;; + ps2) + basic_machine=i386-ibm + ;; + pw32) + basic_machine=i586-unknown + os=-pw32 + ;; + rom68k) + basic_machine=m68k-rom68k + os=-coff + ;; + rm[46]00) + basic_machine=mips-siemens + ;; + rtpc | rtpc-*) + basic_machine=romp-ibm + ;; + s390 | s390-*) + basic_machine=s390-ibm + ;; + s390x | s390x-*) + basic_machine=s390x-ibm + ;; + sa29200) + basic_machine=a29k-amd + os=-udi + ;; + sb1) + basic_machine=mipsisa64sb1-unknown + ;; + sb1el) + basic_machine=mipsisa64sb1el-unknown + ;; + sequent) + basic_machine=i386-sequent + ;; + sh) + basic_machine=sh-hitachi + os=-hms + ;; + sparclite-wrs | simso-wrs) + basic_machine=sparclite-wrs + os=-vxworks + ;; + sps7) + basic_machine=m68k-bull + os=-sysv2 + ;; + spur) + basic_machine=spur-unknown + ;; + st2000) + basic_machine=m68k-tandem + ;; + stratus) + basic_machine=i860-stratus + os=-sysv4 + ;; + sun2) + basic_machine=m68000-sun + ;; + sun2os3) + basic_machine=m68000-sun + os=-sunos3 + ;; + sun2os4) + basic_machine=m68000-sun + os=-sunos4 + ;; + sun3os3) + basic_machine=m68k-sun + os=-sunos3 + ;; + sun3os4) + basic_machine=m68k-sun + os=-sunos4 + ;; + sun4os3) + basic_machine=sparc-sun + os=-sunos3 + ;; + sun4os4) + basic_machine=sparc-sun + os=-sunos4 + ;; + sun4sol2) + basic_machine=sparc-sun + os=-solaris2 + ;; + sun3 | sun3-*) + basic_machine=m68k-sun + ;; + sun4) + basic_machine=sparc-sun + ;; + sun386 | sun386i | roadrunner) + basic_machine=i386-sun + ;; + sv1) + basic_machine=sv1-cray + os=-unicos + ;; + symmetry) + basic_machine=i386-sequent + os=-dynix + ;; + t3d) + basic_machine=alpha-cray + os=-unicos + ;; + t3e) + basic_machine=alphaev5-cray + os=-unicos + ;; + t90) + basic_machine=t90-cray + os=-unicos + ;; + tic4x | c4x*) + basic_machine=tic4x-unknown + os=-coff + ;; + tic54x | c54x*) + basic_machine=tic54x-unknown + os=-coff + ;; + tx39) + basic_machine=mipstx39-unknown + ;; + tx39el) + basic_machine=mipstx39el-unknown + ;; + toad1) + basic_machine=pdp10-xkl + os=-tops20 + ;; + tower | tower-32) + basic_machine=m68k-ncr + ;; + udi29k) + basic_machine=a29k-amd + os=-udi + ;; + ultra3) + basic_machine=a29k-nyu + os=-sym1 + ;; + v810 | necv810) + basic_machine=v810-nec + os=-none + ;; + vaxv) + basic_machine=vax-dec + os=-sysv + ;; + vms) + basic_machine=vax-dec + os=-vms + ;; + vpp*|vx|vx-*) + basic_machine=f301-fujitsu + ;; + vxworks960) + basic_machine=i960-wrs + os=-vxworks + ;; + vxworks68) + basic_machine=m68k-wrs + os=-vxworks + ;; + vxworks29k) + basic_machine=a29k-wrs + os=-vxworks + ;; + w65*) + basic_machine=w65-wdc + os=-none + ;; + w89k-*) + basic_machine=hppa1.1-winbond + os=-proelf + ;; + windows32) + basic_machine=i386-pc + os=-windows32-msvcrt + ;; + xps | xps100) + basic_machine=xps100-honeywell + ;; + ymp) + basic_machine=ymp-cray + os=-unicos + ;; + z8k-*-coff) + basic_machine=z8k-unknown + os=-sim + ;; + none) + basic_machine=none-none + os=-none + ;; + +# Here we handle the default manufacturer of certain CPU types. It is in +# some cases the only manufacturer, in others, it is the most popular. + w89k) + basic_machine=hppa1.1-winbond + ;; + op50n) + basic_machine=hppa1.1-oki + ;; + op60c) + basic_machine=hppa1.1-oki + ;; + romp) + basic_machine=romp-ibm + ;; + rs6000) + basic_machine=rs6000-ibm + ;; + vax) + basic_machine=vax-dec + ;; + pdp10) + # there are many clones, so DEC is not a safe bet + basic_machine=pdp10-unknown + ;; + pdp11) + basic_machine=pdp11-dec + ;; + we32k) + basic_machine=we32k-att + ;; + sh3 | sh4 | sh3eb | sh4eb | sh[1234]le | sh3ele) + basic_machine=sh-unknown + ;; + sh64) + basic_machine=sh64-unknown + ;; + sparc | sparcv9 | sparcv9b) + basic_machine=sparc-sun + ;; + cydra) + basic_machine=cydra-cydrome + ;; + orion) + basic_machine=orion-highlevel + ;; + orion105) + basic_machine=clipper-highlevel + ;; + mac | mpw | mac-mpw) + basic_machine=m68k-apple + ;; + pmac | pmac-mpw) + basic_machine=powerpc-apple + ;; + *-unknown) + # Make sure to match an already-canonicalized machine name. + ;; + *) + echo Invalid configuration \`$1\': machine \`$basic_machine\' not recognized 1>&2 + exit 1 + ;; +esac + +# Here we canonicalize certain aliases for manufacturers. +case $basic_machine in + *-digital*) + basic_machine=`echo $basic_machine | sed 's/digital.*/dec/'` + ;; + *-commodore*) + basic_machine=`echo $basic_machine | sed 's/commodore.*/cbm/'` + ;; + *) + ;; +esac + +# Decode manufacturer-specific aliases for certain operating systems. + +if [ x"$os" != x"" ] +then +case $os in + # First match some system type aliases + # that might get confused with valid system types. + # -solaris* is a basic system type, with this one exception. + -solaris1 | -solaris1.*) + os=`echo $os | sed -e 's|solaris1|sunos4|'` + ;; + -solaris) + os=-solaris2 + ;; + -svr4*) + os=-sysv4 + ;; + -unixware*) + os=-sysv4.2uw + ;; + -gnu/linux*) + os=`echo $os | sed -e 's|gnu/linux|linux-gnu|'` + ;; + # First accept the basic system types. + # The portable systems comes first. + # Each alternative MUST END IN A *, to match a version number. + # -sysv* is not here because it comes later, after sysvr4. + -gnu* | -bsd* | -mach* | -minix* | -genix* | -ultrix* | -irix* \ + | -*vms* | -sco* | -esix* | -isc* | -aix* | -sunos | -sunos[34]*\ + | -hpux* | -unos* | -osf* | -luna* | -dgux* | -solaris* | -sym* \ + | -amigaos* | -amigados* | -msdos* | -newsos* | -unicos* | -aof* \ + | -aos* \ + | -nindy* | -vxsim* | -vxworks* | -ebmon* | -hms* | -mvs* \ + | -clix* | -riscos* | -uniplus* | -iris* | -rtu* | -xenix* \ + | -hiux* | -386bsd* | -netbsd* | -openbsd* | -freebsd* | -riscix* \ + | -lynxos* | -bosx* | -nextstep* | -cxux* | -aout* | -elf* | -oabi* \ + | -ptx* | -coff* | -ecoff* | -winnt* | -domain* | -vsta* \ + | -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \ + | -chorusos* | -chorusrdb* \ + | -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \ + | -mingw32* | -linux-gnu* | -uxpv* | -beos* | -mpeix* | -udk* \ + | -interix* | -uwin* | -rhapsody* | -darwin* | -opened* \ + | -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \ + | -storm-chaos* | -tops10* | -tenex* | -tops20* | -its* \ + | -os2* | -vos* | -palmos* | -uclinux* | -nucleus* \ + | -morphos* | -superux* | -rtmk* | -rtmk-nova* | -windiss* | -powermax*) + # Remember, each alternative MUST END IN *, to match a version number. + ;; + -qnx*) + case $basic_machine in + x86-* | i*86-*) + ;; + *) + os=-nto$os + ;; + esac + ;; + -nto*) + os=-nto-qnx + ;; + -sim | -es1800* | -hms* | -xray | -os68k* | -none* | -v88r* \ + | -windows* | -osx | -abug | -netware* | -os9* | -beos* \ + | -macos* | -mpw* | -magic* | -mmixware* | -mon960* | -lnews*) + ;; + -mac*) + os=`echo $os | sed -e 's|mac|macos|'` + ;; + -linux*) + os=`echo $os | sed -e 's|linux|linux-gnu|'` + ;; + -sunos5*) + os=`echo $os | sed -e 's|sunos5|solaris2|'` + ;; + -sunos6*) + os=`echo $os | sed -e 's|sunos6|solaris3|'` + ;; + -opened*) + os=-openedition + ;; + -wince*) + os=-wince + ;; + -osfrose*) + os=-osfrose + ;; + -osf*) + os=-osf + ;; + -utek*) + os=-bsd + ;; + -dynix*) + os=-bsd + ;; + -acis*) + os=-aos + ;; + -atheos*) + os=-atheos + ;; + -386bsd) + os=-bsd + ;; + -ctix* | -uts*) + os=-sysv + ;; + -nova*) + os=-rtmk-nova + ;; + -ns2 ) + os=-nextstep2 + ;; + -nsk*) + os=-nsk + ;; + # Preserve the version number of sinix5. + -sinix5.*) + os=`echo $os | sed -e 's|sinix|sysv|'` + ;; + -sinix*) + os=-sysv4 + ;; + -triton*) + os=-sysv3 + ;; + -oss*) + os=-sysv3 + ;; + -svr4) + os=-sysv4 + ;; + -svr3) + os=-sysv3 + ;; + -sysvr4) + os=-sysv4 + ;; + # This must come after -sysvr4. + -sysv*) + ;; + -ose*) + os=-ose + ;; + -es1800*) + os=-ose + ;; + -xenix) + os=-xenix + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + os=-mint + ;; + -none) + ;; + *) + # Get rid of the `-' at the beginning of $os. + os=`echo $os | sed 's/[^-]*-//'` + echo Invalid configuration \`$1\': system \`$os\' not recognized 1>&2 + exit 1 + ;; +esac +else + +# Here we handle the default operating systems that come with various machines. +# The value should be what the vendor currently ships out the door with their +# machine or put another way, the most popular os provided with the machine. + +# Note that if you're going to try to match "-MANUFACTURER" here (say, +# "-sun"), then you have to tell the case statement up towards the top +# that MANUFACTURER isn't an operating system. Otherwise, code above +# will signal an error saying that MANUFACTURER isn't an operating +# system, and we'll never get to this point. + +case $basic_machine in + *-acorn) + os=-riscix1.2 + ;; + arm*-rebel) + os=-linux + ;; + arm*-semi) + os=-aout + ;; + # This must come before the *-dec entry. + pdp10-*) + os=-tops20 + ;; + pdp11-*) + os=-none + ;; + *-dec | vax-*) + os=-ultrix4.2 + ;; + m68*-apollo) + os=-domain + ;; + i386-sun) + os=-sunos4.0.2 + ;; + m68000-sun) + os=-sunos3 + # This also exists in the configure program, but was not the + # default. + # os=-sunos4 + ;; + m68*-cisco) + os=-aout + ;; + mips*-cisco) + os=-elf + ;; + mips*-*) + os=-elf + ;; + or32-*) + os=-coff + ;; + *-tti) # must be before sparc entry or we get the wrong os. + os=-sysv3 + ;; + sparc-* | *-sun) + os=-sunos4.1.1 + ;; + *-be) + os=-beos + ;; + *-ibm) + os=-aix + ;; + *-wec) + os=-proelf + ;; + *-winbond) + os=-proelf + ;; + *-oki) + os=-proelf + ;; + *-hp) + os=-hpux + ;; + *-hitachi) + os=-hiux + ;; + i860-* | *-att | *-ncr | *-altos | *-motorola | *-convergent) + os=-sysv + ;; + *-cbm) + os=-amigaos + ;; + *-dg) + os=-dgux + ;; + *-dolphin) + os=-sysv3 + ;; + m68k-ccur) + os=-rtu + ;; + m88k-omron*) + os=-luna + ;; + *-next ) + os=-nextstep + ;; + *-sequent) + os=-ptx + ;; + *-crds) + os=-unos + ;; + *-ns) + os=-genix + ;; + i370-*) + os=-mvs + ;; + *-next) + os=-nextstep3 + ;; + *-gould) + os=-sysv + ;; + *-highlevel) + os=-bsd + ;; + *-encore) + os=-bsd + ;; + *-sgi) + os=-irix + ;; + *-siemens) + os=-sysv4 + ;; + *-masscomp) + os=-rtu + ;; + f30[01]-fujitsu | f700-fujitsu) + os=-uxpv + ;; + *-rom68k) + os=-coff + ;; + *-*bug) + os=-coff + ;; + *-apple) + os=-macos + ;; + *-atari*) + os=-mint + ;; + *) + os=-none + ;; +esac +fi + +# Here we handle the case where we know the os, and the CPU type, but not the +# manufacturer. We pick the logical manufacturer. +vendor=unknown +case $basic_machine in + *-unknown) + case $os in + -riscix*) + vendor=acorn + ;; + -sunos*) + vendor=sun + ;; + -aix*) + vendor=ibm + ;; + -beos*) + vendor=be + ;; + -hpux*) + vendor=hp + ;; + -mpeix*) + vendor=hp + ;; + -hiux*) + vendor=hitachi + ;; + -unos*) + vendor=crds + ;; + -dgux*) + vendor=dg + ;; + -luna*) + vendor=omron + ;; + -genix*) + vendor=ns + ;; + -mvs* | -opened*) + vendor=ibm + ;; + -ptx*) + vendor=sequent + ;; + -vxsim* | -vxworks* | -windiss*) + vendor=wrs + ;; + -aux*) + vendor=apple + ;; + -hms*) + vendor=hitachi + ;; + -mpw* | -macos*) + vendor=apple + ;; + -*mint | -mint[0-9]* | -*MiNT | -MiNT[0-9]*) + vendor=atari + ;; + -vos*) + vendor=stratus + ;; + esac + basic_machine=`echo $basic_machine | sed "s/unknown/$vendor/"` + ;; +esac + +echo $basic_machine$os +exit 0 + +# Local variables: +# eval: (add-hook 'write-file-hooks 'time-stamp) +# time-stamp-start: "timestamp='" +# time-stamp-format: "%:y-%02m-%02d" +# time-stamp-end: "'" +# End: diff --git a/trunk/configure b/trunk/configure new file mode 100755 index 0000000..9f2a746 --- /dev/null +++ b/trunk/configure @@ -0,0 +1,20851 @@ +#! /bin/sh +# Guess values for system-dependent variables and create Makefiles. +# Generated by GNU Autoconf 2.57. +# +# Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This configure script is free software; the Free Software Foundation +# gives unlimited permission to copy, distribute and modify it. +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2 + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2 + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + + + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} + +case X$ECHO in +X*--fallback-echo) + # Remove one level of quotation (which was required for Make). + ECHO=`echo "$ECHO" | sed 's,\\\\\$\\$0,'$0','` + ;; +esac + +echo=${ECHO-echo} +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t' ; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit 0 +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +if test -z "$ECHO"; then +if test "X${echo_test_string+set}" != Xset; then +# find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null + then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + : +else + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for dir in $PATH /usr/ucb; do + IFS="$lt_save_ifs" + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$lt_save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`(print -r "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running configure again with it. + ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf %s\n' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + echo_testing_string=`($echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + # Cool, printf works + : + elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && + test "X$echo_testing_string" = 'X\t' && + echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && + test "X$echo_testing_string" = "X$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null + then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi +fi + +# Copy echo and quote the copy suitably for passing to libtool from +# the Makefile, instead of quoting the original, which is used later. +ECHO=$echo +if test "X$ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" +fi + + + + +tagnames=`echo "$tagnames,CXX" | sed 's/^,//'` + +tagnames=`echo "$tagnames,F77" | sed 's/^,//'` + +# Name of the host. +# hostname on some systems (SVR3.2, Linux) returns a bogus exit status, +# so uname gets run too. +ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q` + +exec 6>&1 + +# +# Initializations. +# +ac_default_prefix=/usr/local +ac_config_libobj_dir=. +cross_compiling=no +subdirs= +MFLAGS= +MAKEFLAGS= +SHELL=${CONFIG_SHELL-/bin/sh} + +# Maximum number of lines to put in a shell here document. +# This variable seems obsolete. It should probably be removed, and +# only ac_max_sed_lines should be used. +: ${ac_max_here_lines=38} + +# Identity of this package. +PACKAGE_NAME= +PACKAGE_TARNAME= +PACKAGE_VERSION= +PACKAGE_STRING= +PACKAGE_BUGREPORT= + +ac_unique_file="src/prelink.c" +# Factoring default headers for most tests. +ac_includes_default="\ +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif +#if HAVE_SYS_STAT_H +# include <sys/stat.h> +#endif +#if STDC_HEADERS +# include <stdlib.h> +# include <stddef.h> +#else +# if HAVE_STDLIB_H +# include <stdlib.h> +# endif +#endif +#if HAVE_STRING_H +# if !STDC_HEADERS && HAVE_MEMORY_H +# include <memory.h> +# endif +# include <string.h> +#endif +#if HAVE_STRINGS_H +# include <strings.h> +#endif +#if HAVE_INTTYPES_H +# include <inttypes.h> +#else +# if HAVE_STDINT_H +# include <stdint.h> +# endif +#endif +#if HAVE_UNISTD_H +# include <unistd.h> +#endif" + +ac_subst_vars='SHELL PATH_SEPARATOR PACKAGE_NAME PACKAGE_TARNAME PACKAGE_VERSION PACKAGE_STRING PACKAGE_BUGREPORT exec_prefix prefix program_transform_name bindir sbindir libexecdir datadir sysconfdir sharedstatedir localstatedir libdir includedir oldincludedir infodir mandir build_alias host_alias target_alias DEFS ECHO_C ECHO_N ECHO_T LIBS build build_cpu build_vendor build_os host host_cpu host_vendor host_os INSTALL_PROGRAM INSTALL_SCRIPT INSTALL_DATA PACKAGE VERSION ACLOCAL AUTOCONF AUTOMAKE AUTOHEADER MAKEINFO AMTAR install_sh STRIP ac_ct_STRIP INSTALL_STRIP_PROGRAM AWK SET_MAKE CC CFLAGS LDFLAGS CPPFLAGS ac_ct_CC EXEEXT OBJEXT DEPDIR am__include am__quote AMDEP_TRUE AMDEP_FALSE AMDEPBACKSLASH CCDEPMODE CXX CXXFLAGS ac_ct_CXX CXXDEPMODE CPP EGREP LN_S ECHO AR ac_ct_AR RANLIB ac_ct_RANLIB CXXCPP F77 FFLAGS ac_ct_F77 LIBTOOL GELFINCLUDE LIBGELF LIBOBJS LTLIBOBJS' +ac_subst_files='' + +# Initialize some variables set by options. +ac_init_help= +ac_init_version=false +# The variables have the same names as the options, with +# dashes changed to underlines. +cache_file=/dev/null +exec_prefix=NONE +no_create= +no_recursion= +prefix=NONE +program_prefix=NONE +program_suffix=NONE +program_transform_name=s,x,x, +silent= +site= +srcdir= +verbose= +x_includes=NONE +x_libraries=NONE + +# Installation directory options. +# These are left unexpanded so users can "make install exec_prefix=/foo" +# and all the variables that are supposed to be based on exec_prefix +# by default will actually change. +# Use braces instead of parens because sh, perl, etc. also accept them. +bindir='${exec_prefix}/bin' +sbindir='${exec_prefix}/sbin' +libexecdir='${exec_prefix}/libexec' +datadir='${prefix}/share' +sysconfdir='${prefix}/etc' +sharedstatedir='${prefix}/com' +localstatedir='${prefix}/var' +libdir='${exec_prefix}/lib' +includedir='${prefix}/include' +oldincludedir='/usr/include' +infodir='${prefix}/info' +mandir='${prefix}/man' + +ac_prev= +for ac_option +do + # If the previous option needs an argument, assign it. + if test -n "$ac_prev"; then + eval "$ac_prev=\$ac_option" + ac_prev= + continue + fi + + ac_optarg=`expr "x$ac_option" : 'x[^=]*=\(.*\)'` + + # Accept the important Cygnus configure options, so we can diagnose typos. + + case $ac_option in + + -bindir | --bindir | --bindi | --bind | --bin | --bi) + ac_prev=bindir ;; + -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*) + bindir=$ac_optarg ;; + + -build | --build | --buil | --bui | --bu) + ac_prev=build_alias ;; + -build=* | --build=* | --buil=* | --bui=* | --bu=*) + build_alias=$ac_optarg ;; + + -cache-file | --cache-file | --cache-fil | --cache-fi \ + | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c) + ac_prev=cache_file ;; + -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \ + | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*) + cache_file=$ac_optarg ;; + + --config-cache | -C) + cache_file=config.cache ;; + + -datadir | --datadir | --datadi | --datad | --data | --dat | --da) + ac_prev=datadir ;; + -datadir=* | --datadir=* | --datadi=* | --datad=* | --data=* | --dat=* \ + | --da=*) + datadir=$ac_optarg ;; + + -disable-* | --disable-*) + ac_feature=`expr "x$ac_option" : 'x-*disable-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + eval "enable_$ac_feature=no" ;; + + -enable-* | --enable-*) + ac_feature=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_feature" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid feature name: $ac_feature" >&2 + { (exit 1); exit 1; }; } + ac_feature=`echo $ac_feature | sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "enable_$ac_feature='$ac_optarg'" ;; + + -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \ + | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \ + | --exec | --exe | --ex) + ac_prev=exec_prefix ;; + -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \ + | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \ + | --exec=* | --exe=* | --ex=*) + exec_prefix=$ac_optarg ;; + + -gas | --gas | --ga | --g) + # Obsolete; use --with-gas. + with_gas=yes ;; + + -help | --help | --hel | --he | -h) + ac_init_help=long ;; + -help=r* | --help=r* | --hel=r* | --he=r* | -hr*) + ac_init_help=recursive ;; + -help=s* | --help=s* | --hel=s* | --he=s* | -hs*) + ac_init_help=short ;; + + -host | --host | --hos | --ho) + ac_prev=host_alias ;; + -host=* | --host=* | --hos=* | --ho=*) + host_alias=$ac_optarg ;; + + -includedir | --includedir | --includedi | --included | --include \ + | --includ | --inclu | --incl | --inc) + ac_prev=includedir ;; + -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \ + | --includ=* | --inclu=* | --incl=* | --inc=*) + includedir=$ac_optarg ;; + + -infodir | --infodir | --infodi | --infod | --info | --inf) + ac_prev=infodir ;; + -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*) + infodir=$ac_optarg ;; + + -libdir | --libdir | --libdi | --libd) + ac_prev=libdir ;; + -libdir=* | --libdir=* | --libdi=* | --libd=*) + libdir=$ac_optarg ;; + + -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \ + | --libexe | --libex | --libe) + ac_prev=libexecdir ;; + -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \ + | --libexe=* | --libex=* | --libe=*) + libexecdir=$ac_optarg ;; + + -localstatedir | --localstatedir | --localstatedi | --localstated \ + | --localstate | --localstat | --localsta | --localst \ + | --locals | --local | --loca | --loc | --lo) + ac_prev=localstatedir ;; + -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \ + | --localstate=* | --localstat=* | --localsta=* | --localst=* \ + | --locals=* | --local=* | --loca=* | --loc=* | --lo=*) + localstatedir=$ac_optarg ;; + + -mandir | --mandir | --mandi | --mand | --man | --ma | --m) + ac_prev=mandir ;; + -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*) + mandir=$ac_optarg ;; + + -nfp | --nfp | --nf) + # Obsolete; use --without-fp. + with_fp=no ;; + + -no-create | --no-create | --no-creat | --no-crea | --no-cre \ + | --no-cr | --no-c | -n) + no_create=yes ;; + + -no-recursion | --no-recursion | --no-recursio | --no-recursi \ + | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r) + no_recursion=yes ;; + + -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \ + | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \ + | --oldin | --oldi | --old | --ol | --o) + ac_prev=oldincludedir ;; + -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \ + | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \ + | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*) + oldincludedir=$ac_optarg ;; + + -prefix | --prefix | --prefi | --pref | --pre | --pr | --p) + ac_prev=prefix ;; + -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*) + prefix=$ac_optarg ;; + + -program-prefix | --program-prefix | --program-prefi | --program-pref \ + | --program-pre | --program-pr | --program-p) + ac_prev=program_prefix ;; + -program-prefix=* | --program-prefix=* | --program-prefi=* \ + | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*) + program_prefix=$ac_optarg ;; + + -program-suffix | --program-suffix | --program-suffi | --program-suff \ + | --program-suf | --program-su | --program-s) + ac_prev=program_suffix ;; + -program-suffix=* | --program-suffix=* | --program-suffi=* \ + | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*) + program_suffix=$ac_optarg ;; + + -program-transform-name | --program-transform-name \ + | --program-transform-nam | --program-transform-na \ + | --program-transform-n | --program-transform- \ + | --program-transform | --program-transfor \ + | --program-transfo | --program-transf \ + | --program-trans | --program-tran \ + | --progr-tra | --program-tr | --program-t) + ac_prev=program_transform_name ;; + -program-transform-name=* | --program-transform-name=* \ + | --program-transform-nam=* | --program-transform-na=* \ + | --program-transform-n=* | --program-transform-=* \ + | --program-transform=* | --program-transfor=* \ + | --program-transfo=* | --program-transf=* \ + | --program-trans=* | --program-tran=* \ + | --progr-tra=* | --program-tr=* | --program-t=*) + program_transform_name=$ac_optarg ;; + + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + silent=yes ;; + + -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) + ac_prev=sbindir ;; + -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ + | --sbi=* | --sb=*) + sbindir=$ac_optarg ;; + + -sharedstatedir | --sharedstatedir | --sharedstatedi \ + | --sharedstated | --sharedstate | --sharedstat | --sharedsta \ + | --sharedst | --shareds | --shared | --share | --shar \ + | --sha | --sh) + ac_prev=sharedstatedir ;; + -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \ + | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \ + | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \ + | --sha=* | --sh=*) + sharedstatedir=$ac_optarg ;; + + -site | --site | --sit) + ac_prev=site ;; + -site=* | --site=* | --sit=*) + site=$ac_optarg ;; + + -srcdir | --srcdir | --srcdi | --srcd | --src | --sr) + ac_prev=srcdir ;; + -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*) + srcdir=$ac_optarg ;; + + -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \ + | --syscon | --sysco | --sysc | --sys | --sy) + ac_prev=sysconfdir ;; + -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \ + | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*) + sysconfdir=$ac_optarg ;; + + -target | --target | --targe | --targ | --tar | --ta | --t) + ac_prev=target_alias ;; + -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*) + target_alias=$ac_optarg ;; + + -v | -verbose | --verbose | --verbos | --verbo | --verb) + verbose=yes ;; + + -version | --version | --versio | --versi | --vers | -V) + ac_init_version=: ;; + + -with-* | --with-*) + ac_package=`expr "x$ac_option" : 'x-*with-\([^=]*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package| sed 's/-/_/g'` + case $ac_option in + *=*) ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"`;; + *) ac_optarg=yes ;; + esac + eval "with_$ac_package='$ac_optarg'" ;; + + -without-* | --without-*) + ac_package=`expr "x$ac_option" : 'x-*without-\(.*\)'` + # Reject names that are not valid shell variable names. + expr "x$ac_package" : ".*[^-_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid package name: $ac_package" >&2 + { (exit 1); exit 1; }; } + ac_package=`echo $ac_package | sed 's/-/_/g'` + eval "with_$ac_package=no" ;; + + --x) + # Obsolete; use --with-x. + with_x=yes ;; + + -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \ + | --x-incl | --x-inc | --x-in | --x-i) + ac_prev=x_includes ;; + -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \ + | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*) + x_includes=$ac_optarg ;; + + -x-libraries | --x-libraries | --x-librarie | --x-librari \ + | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l) + ac_prev=x_libraries ;; + -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \ + | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*) + x_libraries=$ac_optarg ;; + + -*) { echo "$as_me: error: unrecognized option: $ac_option +Try \`$0 --help' for more information." >&2 + { (exit 1); exit 1; }; } + ;; + + *=*) + ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='` + # Reject names that are not valid shell variable names. + expr "x$ac_envvar" : ".*[^_$as_cr_alnum]" >/dev/null && + { echo "$as_me: error: invalid variable name: $ac_envvar" >&2 + { (exit 1); exit 1; }; } + ac_optarg=`echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` + eval "$ac_envvar='$ac_optarg'" + export $ac_envvar ;; + + *) + # FIXME: should be removed in autoconf 3.0. + echo "$as_me: WARNING: you should use --build, --host, --target" >&2 + expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null && + echo "$as_me: WARNING: invalid host type: $ac_option" >&2 + : ${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option} + ;; + + esac +done + +if test -n "$ac_prev"; then + ac_option=--`echo $ac_prev | sed 's/_/-/g'` + { echo "$as_me: error: missing argument to $ac_option" >&2 + { (exit 1); exit 1; }; } +fi + +# Be sure to have absolute paths. +for ac_var in exec_prefix prefix +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* | NONE | '' ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# Be sure to have absolute paths. +for ac_var in bindir sbindir libexecdir datadir sysconfdir sharedstatedir \ + localstatedir libdir includedir oldincludedir infodir mandir +do + eval ac_val=$`echo $ac_var` + case $ac_val in + [\\/$]* | ?:[\\/]* ) ;; + *) { echo "$as_me: error: expected an absolute directory name for --$ac_var: $ac_val" >&2 + { (exit 1); exit 1; }; };; + esac +done + +# There might be people who depend on the old broken behavior: `$host' +# used to hold the argument of --host etc. +# FIXME: To remove some day. +build=$build_alias +host=$host_alias +target=$target_alias + +# FIXME: To remove some day. +if test "x$host_alias" != x; then + if test "x$build_alias" = x; then + cross_compiling=maybe + echo "$as_me: WARNING: If you wanted to set the --build type, don't use --host. + If a cross compiler is detected then cross compile mode will be used." >&2 + elif test "x$build_alias" != "x$host_alias"; then + cross_compiling=yes + fi +fi + +ac_tool_prefix= +test -n "$host_alias" && ac_tool_prefix=$host_alias- + +test "$silent" = yes && exec 6>/dev/null + + +# Find the source files, if location was not specified. +if test -z "$srcdir"; then + ac_srcdir_defaulted=yes + # Try the directory containing this script, then its parent. + ac_confdir=`(dirname "$0") 2>/dev/null || +$as_expr X"$0" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$0" : 'X\(//\)[^/]' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$0" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + srcdir=$ac_confdir + if test ! -r $srcdir/$ac_unique_file; then + srcdir=.. + fi +else + ac_srcdir_defaulted=no +fi +if test ! -r $srcdir/$ac_unique_file; then + if test "$ac_srcdir_defaulted" = yes; then + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $ac_confdir or .." >&2 + { (exit 1); exit 1; }; } + else + { echo "$as_me: error: cannot find sources ($ac_unique_file) in $srcdir" >&2 + { (exit 1); exit 1; }; } + fi +fi +(cd $srcdir && test -r ./$ac_unique_file) 2>/dev/null || + { echo "$as_me: error: sources are in $srcdir, but \`cd $srcdir' does not work" >&2 + { (exit 1); exit 1; }; } +srcdir=`echo "$srcdir" | sed 's%\([^\\/]\)[\\/]*$%\1%'` +ac_env_build_alias_set=${build_alias+set} +ac_env_build_alias_value=$build_alias +ac_cv_env_build_alias_set=${build_alias+set} +ac_cv_env_build_alias_value=$build_alias +ac_env_host_alias_set=${host_alias+set} +ac_env_host_alias_value=$host_alias +ac_cv_env_host_alias_set=${host_alias+set} +ac_cv_env_host_alias_value=$host_alias +ac_env_target_alias_set=${target_alias+set} +ac_env_target_alias_value=$target_alias +ac_cv_env_target_alias_set=${target_alias+set} +ac_cv_env_target_alias_value=$target_alias +ac_env_CC_set=${CC+set} +ac_env_CC_value=$CC +ac_cv_env_CC_set=${CC+set} +ac_cv_env_CC_value=$CC +ac_env_CFLAGS_set=${CFLAGS+set} +ac_env_CFLAGS_value=$CFLAGS +ac_cv_env_CFLAGS_set=${CFLAGS+set} +ac_cv_env_CFLAGS_value=$CFLAGS +ac_env_LDFLAGS_set=${LDFLAGS+set} +ac_env_LDFLAGS_value=$LDFLAGS +ac_cv_env_LDFLAGS_set=${LDFLAGS+set} +ac_cv_env_LDFLAGS_value=$LDFLAGS +ac_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_env_CPPFLAGS_value=$CPPFLAGS +ac_cv_env_CPPFLAGS_set=${CPPFLAGS+set} +ac_cv_env_CPPFLAGS_value=$CPPFLAGS +ac_env_CXX_set=${CXX+set} +ac_env_CXX_value=$CXX +ac_cv_env_CXX_set=${CXX+set} +ac_cv_env_CXX_value=$CXX +ac_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_env_CXXFLAGS_value=$CXXFLAGS +ac_cv_env_CXXFLAGS_set=${CXXFLAGS+set} +ac_cv_env_CXXFLAGS_value=$CXXFLAGS +ac_env_CPP_set=${CPP+set} +ac_env_CPP_value=$CPP +ac_cv_env_CPP_set=${CPP+set} +ac_cv_env_CPP_value=$CPP +ac_env_CXXCPP_set=${CXXCPP+set} +ac_env_CXXCPP_value=$CXXCPP +ac_cv_env_CXXCPP_set=${CXXCPP+set} +ac_cv_env_CXXCPP_value=$CXXCPP +ac_env_F77_set=${F77+set} +ac_env_F77_value=$F77 +ac_cv_env_F77_set=${F77+set} +ac_cv_env_F77_value=$F77 +ac_env_FFLAGS_set=${FFLAGS+set} +ac_env_FFLAGS_value=$FFLAGS +ac_cv_env_FFLAGS_set=${FFLAGS+set} +ac_cv_env_FFLAGS_value=$FFLAGS + +# +# Report the --help message. +# +if test "$ac_init_help" = "long"; then + # Omit some internal or obsolete options to make the list less imposing. + # This message is too long to be a string in the A/UX 3.1 sh. + cat <<_ACEOF +\`configure' configures this package to adapt to many kinds of systems. + +Usage: $0 [OPTION]... [VAR=VALUE]... + +To assign environment variables (e.g., CC, CFLAGS...), specify them as +VAR=VALUE. See below for descriptions of some of the useful variables. + +Defaults for the options are specified in brackets. + +Configuration: + -h, --help display this help and exit + --help=short display options specific to this package + --help=recursive display the short help of all the included packages + -V, --version display version information and exit + -q, --quiet, --silent do not print \`checking...' messages + --cache-file=FILE cache test results in FILE [disabled] + -C, --config-cache alias for \`--cache-file=config.cache' + -n, --no-create do not create output files + --srcdir=DIR find the sources in DIR [configure dir or \`..'] + +_ACEOF + + cat <<_ACEOF +Installation directories: + --prefix=PREFIX install architecture-independent files in PREFIX + [$ac_default_prefix] + --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX + [PREFIX] + +By default, \`make install' will install all the files in +\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify +an installation prefix other than \`$ac_default_prefix' using \`--prefix', +for instance \`--prefix=\$HOME'. + +For better control, use the options below. + +Fine tuning of the installation directories: + --bindir=DIR user executables [EPREFIX/bin] + --sbindir=DIR system admin executables [EPREFIX/sbin] + --libexecdir=DIR program executables [EPREFIX/libexec] + --datadir=DIR read-only architecture-independent data [PREFIX/share] + --sysconfdir=DIR read-only single-machine data [PREFIX/etc] + --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] + --localstatedir=DIR modifiable single-machine data [PREFIX/var] + --libdir=DIR object code libraries [EPREFIX/lib] + --includedir=DIR C header files [PREFIX/include] + --oldincludedir=DIR C header files for non-gcc [/usr/include] + --infodir=DIR info documentation [PREFIX/info] + --mandir=DIR man documentation [PREFIX/man] +_ACEOF + + cat <<\_ACEOF + +Program names: + --program-prefix=PREFIX prepend PREFIX to installed program names + --program-suffix=SUFFIX append SUFFIX to installed program names + --program-transform-name=PROGRAM run sed PROGRAM on installed program names + +System types: + --build=BUILD configure for building on BUILD [guessed] + --host=HOST cross-compile to build programs to run on HOST [BUILD] +_ACEOF +fi + +if test -n "$ac_init_help"; then + + cat <<\_ACEOF + +Optional Features: + --disable-FEATURE do not include FEATURE (same as --enable-FEATURE=no) + --enable-FEATURE[=ARG] include FEATURE [ARG=yes] + --disable-dependency-tracking Speeds up one-time builds + --enable-dependency-tracking Do not reject slow dependency extractors + --enable-shared[=PKGS] + build shared libraries [default=yes] + --enable-static[=PKGS] + build static libraries [default=yes] + --enable-fast-install[=PKGS] + optimize for fast installation [default=yes] + --disable-libtool-lock avoid locking (might break parallel builds) + --disable-64-bit only support 32-bit ELF + --disable-largefile omit support for large files + +Optional Packages: + --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] + --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no) + --with-gnu-ld assume the C compiler uses GNU ld [default=no] + --with-pic try to use only PIC/non-PIC objects [default=use + both] + --with-tags[=TAGS] + include additional configurations [automatic] + +Some influential environment variables: + CC C compiler command + CFLAGS C compiler flags + LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a + nonstandard directory <lib dir> + CPPFLAGS C/C++ preprocessor flags, e.g. -I<include dir> if you have + headers in a nonstandard directory <include dir> + CXX C++ compiler command + CXXFLAGS C++ compiler flags + CPP C preprocessor + CXXCPP C++ preprocessor + F77 Fortran 77 compiler command + FFLAGS Fortran 77 compiler flags + +Use these variables to override the choices made by `configure' or to help +it to find libraries and programs with nonstandard names/locations. + +_ACEOF +fi + +if test "$ac_init_help" = "recursive"; then + # If there are subdirs, report their specific --help. + ac_popdir=`pwd` + for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue + test -d $ac_dir || continue + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + cd $ac_dir + # Check for guested configure; otherwise get Cygnus style configure. + if test -f $ac_srcdir/configure.gnu; then + echo + $SHELL $ac_srcdir/configure.gnu --help=recursive + elif test -f $ac_srcdir/configure; then + echo + $SHELL $ac_srcdir/configure --help=recursive + elif test -f $ac_srcdir/configure.ac || + test -f $ac_srcdir/configure.in; then + echo + $ac_configure --help + else + echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2 + fi + cd $ac_popdir + done +fi + +test -n "$ac_init_help" && exit 0 +if $ac_init_version; then + cat <<\_ACEOF + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001, 2002 +Free Software Foundation, Inc. +This configure script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it. +_ACEOF + exit 0 +fi +exec 5>config.log +cat >&5 <<_ACEOF +This file contains any messages produced by compilers while +running configure, to aid debugging if configure makes a mistake. + +It was created by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + $ $0 $@ + +_ACEOF +{ +cat <<_ASUNAME +## --------- ## +## Platform. ## +## --------- ## + +hostname = `(hostname || uname -n) 2>/dev/null | sed 1q` +uname -m = `(uname -m) 2>/dev/null || echo unknown` +uname -r = `(uname -r) 2>/dev/null || echo unknown` +uname -s = `(uname -s) 2>/dev/null || echo unknown` +uname -v = `(uname -v) 2>/dev/null || echo unknown` + +/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown` +/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown` + +/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown` +/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown` +/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown` +hostinfo = `(hostinfo) 2>/dev/null || echo unknown` +/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown` +/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown` +/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown` + +_ASUNAME + +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + echo "PATH: $as_dir" +done + +} >&5 + +cat >&5 <<_ACEOF + + +## ----------- ## +## Core tests. ## +## ----------- ## + +_ACEOF + + +# Keep a trace of the command line. +# Strip out --no-create and --no-recursion so they do not pile up. +# Strip out --silent because we don't want to record it for future runs. +# Also quote any args containing shell meta-characters. +# Make two passes to allow for proper duplicate-argument suppression. +ac_configure_args= +ac_configure_args0= +ac_configure_args1= +ac_sep= +ac_must_keep_next=false +for ac_pass in 1 2 +do + for ac_arg + do + case $ac_arg in + -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil) + continue ;; + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=`echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;; + esac + case $ac_pass in + 1) ac_configure_args0="$ac_configure_args0 '$ac_arg'" ;; + 2) + ac_configure_args1="$ac_configure_args1 '$ac_arg'" + if test $ac_must_keep_next = true; then + ac_must_keep_next=false # Got value, back to normal. + else + case $ac_arg in + *=* | --config-cache | -C | -disable-* | --disable-* \ + | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \ + | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \ + | -with-* | --with-* | -without-* | --without-* | --x) + case "$ac_configure_args0 " in + "$ac_configure_args1"*" '$ac_arg' "* ) continue ;; + esac + ;; + -* ) ac_must_keep_next=true ;; + esac + fi + ac_configure_args="$ac_configure_args$ac_sep'$ac_arg'" + # Get rid of the leading space. + ac_sep=" " + ;; + esac + done +done +$as_unset ac_configure_args0 || test "${ac_configure_args0+set}" != set || { ac_configure_args0=; export ac_configure_args0; } +$as_unset ac_configure_args1 || test "${ac_configure_args1+set}" != set || { ac_configure_args1=; export ac_configure_args1; } + +# When interrupted or exit'd, cleanup temporary files, and complete +# config.log. We remove comments because anyway the quotes in there +# would cause problems or look ugly. +# WARNING: Be sure not to use single quotes in there, as some shells, +# such as our DU 5.0 friend, will then `close' the trap. +trap 'exit_status=$? + # Save into config.log some information that might help in debugging. + { + echo + + cat <<\_ASBOX +## ---------------- ## +## Cache variables. ## +## ---------------- ## +_ASBOX + echo + # The following way of writing the cache mishandles newlines in values, +{ + (set) 2>&1 | + case `(ac_space='"'"' '"'"'; set | grep ac_space) 2>&1` in + *ac_space=\ *) + sed -n \ + "s/'"'"'/'"'"'\\\\'"'"''"'"'/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='"'"'\\2'"'"'/p" + ;; + *) + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} + echo + + cat <<\_ASBOX +## ----------------- ## +## Output variables. ## +## ----------------- ## +_ASBOX + echo + for ac_var in $ac_subst_vars + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + + if test -n "$ac_subst_files"; then + cat <<\_ASBOX +## ------------- ## +## Output files. ## +## ------------- ## +_ASBOX + echo + for ac_var in $ac_subst_files + do + eval ac_val=$`echo $ac_var` + echo "$ac_var='"'"'$ac_val'"'"'" + done | sort + echo + fi + + if test -s confdefs.h; then + cat <<\_ASBOX +## ----------- ## +## confdefs.h. ## +## ----------- ## +_ASBOX + echo + sed "/^$/d" confdefs.h | sort + echo + fi + test "$ac_signal" != 0 && + echo "$as_me: caught signal $ac_signal" + echo "$as_me: exit $exit_status" + } >&5 + rm -f core core.* *.core && + rm -rf conftest* confdefs* conf$$* $ac_clean_files && + exit $exit_status + ' 0 +for ac_signal in 1 2 13 15; do + trap 'ac_signal='$ac_signal'; { (exit 1); exit 1; }' $ac_signal +done +ac_signal=0 + +# confdefs.h avoids OS command line length limits that DEFS can exceed. +rm -rf conftest* confdefs.h +# AIX cpp loses on an empty file, so make sure it contains at least a newline. +echo >confdefs.h + +# Predefined preprocessor variables. + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_NAME "$PACKAGE_NAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_TARNAME "$PACKAGE_TARNAME" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_VERSION "$PACKAGE_VERSION" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_STRING "$PACKAGE_STRING" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT" +_ACEOF + + +# Let the site file select an alternate cache file if it wants to. +# Prefer explicitly selected file to automatically selected ones. +if test -z "$CONFIG_SITE"; then + if test "x$prefix" != xNONE; then + CONFIG_SITE="$prefix/share/config.site $prefix/etc/config.site" + else + CONFIG_SITE="$ac_default_prefix/share/config.site $ac_default_prefix/etc/config.site" + fi +fi +for ac_site_file in $CONFIG_SITE; do + if test -r "$ac_site_file"; then + { echo "$as_me:$LINENO: loading site script $ac_site_file" >&5 +echo "$as_me: loading site script $ac_site_file" >&6;} + sed 's/^/| /' "$ac_site_file" >&5 + . "$ac_site_file" + fi +done + +if test -r "$cache_file"; then + # Some versions of bash will fail to source /dev/null (special + # files actually), so we avoid doing that. + if test -f "$cache_file"; then + { echo "$as_me:$LINENO: loading cache $cache_file" >&5 +echo "$as_me: loading cache $cache_file" >&6;} + case $cache_file in + [\\/]* | ?:[\\/]* ) . $cache_file;; + *) . ./$cache_file;; + esac + fi +else + { echo "$as_me:$LINENO: creating cache $cache_file" >&5 +echo "$as_me: creating cache $cache_file" >&6;} + >$cache_file +fi + +# Check that the precious variables saved in the cache have kept the same +# value. +ac_cache_corrupted=false +for ac_var in `(set) 2>&1 | + sed -n 's/^ac_env_\([a-zA-Z_0-9]*\)_set=.*/\1/p'`; do + eval ac_old_set=\$ac_cv_env_${ac_var}_set + eval ac_new_set=\$ac_env_${ac_var}_set + eval ac_old_val="\$ac_cv_env_${ac_var}_value" + eval ac_new_val="\$ac_env_${ac_var}_value" + case $ac_old_set,$ac_new_set in + set,) + { echo "$as_me:$LINENO: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,set) + { echo "$as_me:$LINENO: error: \`$ac_var' was not set in the previous run" >&5 +echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;} + ac_cache_corrupted=: ;; + ,);; + *) + if test "x$ac_old_val" != "x$ac_new_val"; then + { echo "$as_me:$LINENO: error: \`$ac_var' has changed since the previous run:" >&5 +echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;} + { echo "$as_me:$LINENO: former value: $ac_old_val" >&5 +echo "$as_me: former value: $ac_old_val" >&2;} + { echo "$as_me:$LINENO: current value: $ac_new_val" >&5 +echo "$as_me: current value: $ac_new_val" >&2;} + ac_cache_corrupted=: + fi;; + esac + # Pass precious variables to config.status. + if test "$ac_new_set" = set; then + case $ac_new_val in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?\"\']*) + ac_arg=$ac_var=`echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;; + *) ac_arg=$ac_var=$ac_new_val ;; + esac + case " $ac_configure_args " in + *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy. + *) ac_configure_args="$ac_configure_args '$ac_arg'" ;; + esac + fi +done +if $ac_cache_corrupted; then + { echo "$as_me:$LINENO: error: changes in the environment can compromise the build" >&5 +echo "$as_me: error: changes in the environment can compromise the build" >&2;} + { { echo "$as_me:$LINENO: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&5 +echo "$as_me: error: run \`make distclean' and/or \`rm $cache_file' and start over" >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + + + + + + + + + + + + + + +# Add the stamp file to the list of files AC keeps track of, +# along with our hook. + ac_config_headers="$ac_config_headers config.h" + + + + ac_aux_dir= +for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/install-sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install-sh -c" + break + elif test -f $ac_dir/install.sh; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/install.sh -c" + break + elif test -f $ac_dir/shtool; then + ac_aux_dir=$ac_dir + ac_install_sh="$ac_aux_dir/shtool install -c" + break + fi +done +if test -z "$ac_aux_dir"; then + { { echo "$as_me:$LINENO: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&5 +echo "$as_me: error: cannot find install-sh or install.sh in $srcdir $srcdir/.. $srcdir/../.." >&2;} + { (exit 1); exit 1; }; } +fi +ac_config_guess="$SHELL $ac_aux_dir/config.guess" +ac_config_sub="$SHELL $ac_aux_dir/config.sub" +ac_configure="$SHELL $ac_aux_dir/configure" # This should be Cygnus configure. + +# Make sure we can run config.sub. +$ac_config_sub sun4 >/dev/null 2>&1 || + { { echo "$as_me:$LINENO: error: cannot run $ac_config_sub" >&5 +echo "$as_me: error: cannot run $ac_config_sub" >&2;} + { (exit 1); exit 1; }; } + +echo "$as_me:$LINENO: checking build system type" >&5 +echo $ECHO_N "checking build system type... $ECHO_C" >&6 +if test "${ac_cv_build+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_build_alias=$build_alias +test -z "$ac_cv_build_alias" && + ac_cv_build_alias=`$ac_config_guess` +test -z "$ac_cv_build_alias" && + { { echo "$as_me:$LINENO: error: cannot guess build type; you must specify one" >&5 +echo "$as_me: error: cannot guess build type; you must specify one" >&2;} + { (exit 1); exit 1; }; } +ac_cv_build=`$ac_config_sub $ac_cv_build_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_build_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_build_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_build" >&5 +echo "${ECHO_T}$ac_cv_build" >&6 +build=$ac_cv_build +build_cpu=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +build_vendor=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +build_os=`echo $ac_cv_build | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + +echo "$as_me:$LINENO: checking host system type" >&5 +echo $ECHO_N "checking host system type... $ECHO_C" >&6 +if test "${ac_cv_host+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_host_alias=$host_alias +test -z "$ac_cv_host_alias" && + ac_cv_host_alias=$ac_cv_build_alias +ac_cv_host=`$ac_config_sub $ac_cv_host_alias` || + { { echo "$as_me:$LINENO: error: $ac_config_sub $ac_cv_host_alias failed" >&5 +echo "$as_me: error: $ac_config_sub $ac_cv_host_alias failed" >&2;} + { (exit 1); exit 1; }; } + +fi +echo "$as_me:$LINENO: result: $ac_cv_host" >&5 +echo "${ECHO_T}$ac_cv_host" >&6 +host=$ac_cv_host +host_cpu=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $ac_cv_host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + + + +am__api_version="1.6" +# Find a good install program. We prefer a C program (faster), +# so one script is as good as another. But avoid the broken or +# incompatible versions: +# SysV /etc/install, /usr/sbin/install +# SunOS /usr/etc/install +# IRIX /sbin/install +# AIX /bin/install +# AmigaOS /C/install, which installs bootblocks on floppy discs +# AIX 4 /usr/bin/installbsd, which doesn't work without a -g flag +# AFS /usr/afsws/bin/install, which mishandles nonexistent args +# SVR4 /usr/ucb/install, which tries to use the nonexistent group "staff" +# ./install, which can be erroneously created by make from ./install.sh. +echo "$as_me:$LINENO: checking for a BSD-compatible install" >&5 +echo $ECHO_N "checking for a BSD-compatible install... $ECHO_C" >&6 +if test -z "$INSTALL"; then +if test "${ac_cv_path_install+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + # Account for people who put trailing slashes in PATH elements. +case $as_dir/ in + ./ | .// | /cC/* | \ + /etc/* | /usr/sbin/* | /usr/etc/* | /sbin/* | /usr/afsws/bin/* | \ + /usr/ucb/* ) ;; + *) + # OSF1 and SCO ODT 3.0 have their own names for install. + # Don't use installbsd from OSF since it installs stuff as root + # by default. + for ac_prog in ginstall scoinst install; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_prog$ac_exec_ext"; then + if test $ac_prog = install && + grep dspmsg "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # AIX install. It has an incompatible calling convention. + : + elif test $ac_prog = install && + grep pwplus "$as_dir/$ac_prog$ac_exec_ext" >/dev/null 2>&1; then + # program-specific install script used by HP pwplus--don't use. + : + else + ac_cv_path_install="$as_dir/$ac_prog$ac_exec_ext -c" + break 3 + fi + fi + done + done + ;; +esac +done + + +fi + if test "${ac_cv_path_install+set}" = set; then + INSTALL=$ac_cv_path_install + else + # As a last resort, use the slow shell script. We don't cache a + # path for INSTALL within a source directory, because that will + # break other packages using the cache if that directory is + # removed, or if the path is relative. + INSTALL=$ac_install_sh + fi +fi +echo "$as_me:$LINENO: result: $INSTALL" >&5 +echo "${ECHO_T}$INSTALL" >&6 + +# Use test -z because SunOS4 sh mishandles braces in ${var-val}. +# It thinks the first close brace ends the variable substitution. +test -z "$INSTALL_PROGRAM" && INSTALL_PROGRAM='${INSTALL}' + +test -z "$INSTALL_SCRIPT" && INSTALL_SCRIPT='${INSTALL}' + +test -z "$INSTALL_DATA" && INSTALL_DATA='${INSTALL} -m 644' + +echo "$as_me:$LINENO: checking whether build environment is sane" >&5 +echo $ECHO_N "checking whether build environment is sane... $ECHO_C" >&6 +# Just in case +sleep 1 +echo timestamp > conftest.file +# Do `set' in a subshell so we don't clobber the current shell's +# arguments. Must try -L first in case configure is actually a +# symlink; some systems play weird games with the mod time of symlinks +# (eg FreeBSD returns the mod time of the symlink's containing +# directory). +if ( + set X `ls -Lt $srcdir/configure conftest.file 2> /dev/null` + if test "$*" = "X"; then + # -L didn't work. + set X `ls -t $srcdir/configure conftest.file` + fi + rm -f conftest.file + if test "$*" != "X $srcdir/configure conftest.file" \ + && test "$*" != "X conftest.file $srcdir/configure"; then + + # If neither matched, then we have a broken ls. This can happen + # if, for instance, CONFIG_SHELL is bash and it inherits a + # broken ls alias from the environment. This has actually + # happened. Such a system could not be considered "sane". + { { echo "$as_me:$LINENO: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&5 +echo "$as_me: error: ls -t appears to fail. Make sure there is not a broken +alias in your environment" >&2;} + { (exit 1); exit 1; }; } + fi + + test "$2" = conftest.file + ) +then + # Ok. + : +else + { { echo "$as_me:$LINENO: error: newly created file is older than distributed files! +Check your system clock" >&5 +echo "$as_me: error: newly created file is older than distributed files! +Check your system clock" >&2;} + { (exit 1); exit 1; }; } +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +test "$program_prefix" != NONE && + program_transform_name="s,^,$program_prefix,;$program_transform_name" +# Use a double $ so make ignores it. +test "$program_suffix" != NONE && + program_transform_name="s,\$,$program_suffix,;$program_transform_name" +# Double any \ or $. echo might interpret backslashes. +# By default was `s,x,x', remove it if useless. +cat <<\_ACEOF >conftest.sed +s/[\\$]/&&/g;s/;s,x,x,$// +_ACEOF +program_transform_name=`echo $program_transform_name | sed -f conftest.sed` +rm conftest.sed + + +# expand $ac_aux_dir to an absolute path +am_aux_dir=`cd $ac_aux_dir && pwd` + +test x"${MISSING+set}" = xset || MISSING="\${SHELL} $am_aux_dir/missing" +# Use eval to expand $SHELL +if eval "$MISSING --run true"; then + am_missing_run="$MISSING --run " +else + am_missing_run= + { echo "$as_me:$LINENO: WARNING: \`missing' script is too old or missing" >&5 +echo "$as_me: WARNING: \`missing' script is too old or missing" >&2;} +fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AWK+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AWK="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + echo "$as_me:$LINENO: result: $AWK" >&5 +echo "${ECHO_T}$AWK" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$AWK" && break +done + +echo "$as_me:$LINENO: checking whether ${MAKE-make} sets \$(MAKE)" >&5 +echo $ECHO_N "checking whether ${MAKE-make} sets \$(MAKE)... $ECHO_C" >&6 +set dummy ${MAKE-make}; ac_make=`echo "$2" | sed 'y,./+-,__p_,'` +if eval "test \"\${ac_cv_prog_make_${ac_make}_set+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.make <<\_ACEOF +all: + @echo 'ac_maketemp="$(MAKE)"' +_ACEOF +# GNU make sometimes prints "make[1]: Entering...", which would confuse us. +eval `${MAKE-make} -f conftest.make 2>/dev/null | grep temp=` +if test -n "$ac_maketemp"; then + eval ac_cv_prog_make_${ac_make}_set=yes +else + eval ac_cv_prog_make_${ac_make}_set=no +fi +rm -f conftest.make +fi +if eval "test \"`echo '$ac_cv_prog_make_'${ac_make}_set`\" = yes"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + SET_MAKE= +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + SET_MAKE="MAKE=${MAKE-make}" +fi + + # test to see if srcdir already configured +if test "`cd $srcdir && pwd`" != "`pwd`" && + test -f $srcdir/config.status; then + { { echo "$as_me:$LINENO: error: source directory already configured; run \"make distclean\" there first" >&5 +echo "$as_me: error: source directory already configured; run \"make distclean\" there first" >&2;} + { (exit 1); exit 1; }; } +fi + +# Define the identity of the package. + PACKAGE=prelink + VERSION=0.0 + + +cat >>confdefs.h <<_ACEOF +#define PACKAGE "$PACKAGE" +_ACEOF + + +cat >>confdefs.h <<_ACEOF +#define VERSION "$VERSION" +_ACEOF + +# Some tools Automake needs. + +ACLOCAL=${ACLOCAL-"${am_missing_run}aclocal-${am__api_version}"} + + +AUTOCONF=${AUTOCONF-"${am_missing_run}autoconf"} + + +AUTOMAKE=${AUTOMAKE-"${am_missing_run}automake-${am__api_version}"} + + +AUTOHEADER=${AUTOHEADER-"${am_missing_run}autoheader"} + + +MAKEINFO=${MAKEINFO-"${am_missing_run}makeinfo"} + + +AMTAR=${AMTAR-"${am_missing_run}tar"} + +install_sh=${install_sh-"$am_aux_dir/install-sh"} + +# Installed binaries are usually stripped using `strip' when the user +# run `make install-strip'. However `strip' might not be the right +# tool to use in cross-compilation environments, therefore Automake +# will honor the `STRIP' environment variable to overrule this program. +if test "$cross_compiling" != no; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + +fi +INSTALL_STRIP_PROGRAM="\${SHELL} \$(install_sh) -c -s" + +# We need awk for the "check" target. The system "awk" is bad on +# some platforms. + + + + +ALL_LINGUAS= + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args. +set dummy ${ac_tool_prefix}gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "gcc", so it can be a program name with args. +set dummy gcc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="gcc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args. +set dummy ${ac_tool_prefix}cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="${ac_tool_prefix}cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_CC"; then + ac_ct_CC=$CC + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + CC=$ac_ct_CC +else + CC="$ac_cv_prog_CC" +fi + +fi +if test -z "$CC"; then + # Extract the first word of "cc", so it can be a program name with args. +set dummy cc; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else + ac_prog_rejected=no +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then + ac_prog_rejected=yes + continue + fi + ac_cv_prog_CC="cc" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +if test $ac_prog_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $ac_cv_prog_CC + shift + if test $# != 0; then + # We chose a different compiler from the bogus one. + # However, it has the same basename, so the bogon will be chosen + # first if we set CC to just the basename; use the full file name. + shift + ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@" + fi +fi +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$CC"; then + if test -n "$ac_tool_prefix"; then + for ac_prog in cl + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CC"; then + ac_cv_prog_CC="$CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CC="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CC=$ac_cv_prog_CC +if test -n "$CC"; then + echo "$as_me:$LINENO: result: $CC" >&5 +echo "${ECHO_T}$CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CC" && break + done +fi +if test -z "$CC"; then + ac_ct_CC=$CC + for ac_prog in cl +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CC"; then + ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CC="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CC=$ac_cv_prog_ac_ct_CC +if test -n "$ac_ct_CC"; then + echo "$as_me:$LINENO: result: $ac_ct_CC" >&5 +echo "${ECHO_T}$ac_ct_CC" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CC" && break +done + + CC=$ac_ct_CC +fi + +fi + + +test -z "$CC" && { { echo "$as_me:$LINENO: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&5 +echo "$as_me: error: no acceptable C compiler found in \$PATH +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files a.out a.exe b.out" +# Try to create an executable without -o first, disregard a.out. +# It will help us diagnose broken compilers, and finding out an intuition +# of exeext. +echo "$as_me:$LINENO: checking for C compiler default output" >&5 +echo $ECHO_N "checking for C compiler default output... $ECHO_C" >&6 +ac_link_default=`echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'` +if { (eval echo "$as_me:$LINENO: \"$ac_link_default\"") >&5 + (eval $ac_link_default) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Find the output, starting from the most likely. This scheme is +# not robust to junk in `.', hence go to wildcards (a.*) only as a last +# resort. + +# Be careful to initialize this variable, since it used to be cached. +# Otherwise an old cache value of `no' led to `EXEEXT = no' in a Makefile. +ac_cv_exeext= +# b.out is created by i960 compilers. +for ac_file in a_out.exe a.exe conftest.exe a.out conftest a.* conftest.* b.out +do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) + ;; + conftest.$ac_ext ) + # This is the source file. + ;; + [ab].out ) + # We found the default executable, but exeext='' is most + # certainly right. + break;; + *.* ) + ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + # FIXME: I believe we export ac_cv_exeext for Libtool, + # but it would be cool to find out if it's true. Does anybody + # maintain Libtool? --akim. + export ac_cv_exeext + break;; + * ) + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: C compiler cannot create executables +See \`config.log' for more details." >&5 +echo "$as_me: error: C compiler cannot create executables +See \`config.log' for more details." >&2;} + { (exit 77); exit 77; }; } +fi + +ac_exeext=$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_file" >&5 +echo "${ECHO_T}$ac_file" >&6 + +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether the C compiler works" >&5 +echo $ECHO_N "checking whether the C compiler works... $ECHO_C" >&6 +# FIXME: These cross compiler hacks should be removed for Autoconf 3.0 +# If not cross compiling, check that we can run a simple program. +if test "$cross_compiling" != yes; then + if { ac_try='./$ac_file' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + cross_compiling=no + else + if test "$cross_compiling" = maybe; then + cross_compiling=yes + else + { { echo "$as_me:$LINENO: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot run C compiled programs. +If you meant to cross compile, use \`--host'. +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } + fi + fi +fi +echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + +rm -f a.out a.exe conftest$ac_cv_exeext b.out +ac_clean_files=$ac_clean_files_save +# Check the compiler produces executables we can run. If not, either +# the compiler is broken, or we cross compile. +echo "$as_me:$LINENO: checking whether we are cross compiling" >&5 +echo $ECHO_N "checking whether we are cross compiling... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $cross_compiling" >&5 +echo "${ECHO_T}$cross_compiling" >&6 + +echo "$as_me:$LINENO: checking for suffix of executables" >&5 +echo $ECHO_N "checking for suffix of executables... $ECHO_C" >&6 +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # If both `conftest.exe' and `conftest' are `present' (well, observable) +# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will +# work properly (i.e., refer to `conftest.exe'), while it won't with +# `rm'. +for ac_file in conftest.exe conftest conftest.*; do + test -f "$ac_file" || continue + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.o | *.obj ) ;; + *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'` + export ac_cv_exeext + break;; + * ) break;; + esac +done +else + { { echo "$as_me:$LINENO: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of executables: cannot compile and link +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest$ac_cv_exeext +echo "$as_me:$LINENO: result: $ac_cv_exeext" >&5 +echo "${ECHO_T}$ac_cv_exeext" >&6 + +rm -f conftest.$ac_ext +EXEEXT=$ac_cv_exeext +ac_exeext=$EXEEXT +echo "$as_me:$LINENO: checking for suffix of object files" >&5 +echo $ECHO_N "checking for suffix of object files... $ECHO_C" >&6 +if test "${ac_cv_objext+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.o conftest.obj +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + for ac_file in `(ls conftest.o conftest.obj; ls conftest.*) 2>/dev/null`; do + case $ac_file in + *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg ) ;; + *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'` + break;; + esac +done +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +{ { echo "$as_me:$LINENO: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&5 +echo "$as_me: error: cannot compute suffix of object files: cannot compile +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +rm -f conftest.$ac_cv_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_objext" >&5 +echo "${ECHO_T}$ac_cv_objext" >&6 +OBJEXT=$ac_cv_objext +ac_objext=$OBJEXT +echo "$as_me:$LINENO: checking whether we are using the GNU C compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C compiler... $ECHO_C" >&6 +if test "${ac_cv_c_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_c_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_c_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_c_compiler_gnu" >&6 +GCC=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CFLAGS=${CFLAGS+set} +ac_save_CFLAGS=$CFLAGS +CFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CC accepts -g" >&5 +echo $ECHO_N "checking whether $CC accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cc_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cc_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_g" >&6 +if test "$ac_test_CFLAGS" = set; then + CFLAGS=$ac_save_CFLAGS +elif test $ac_cv_prog_cc_g = yes; then + if test "$GCC" = yes; then + CFLAGS="-g -O2" + else + CFLAGS="-g" + fi +else + if test "$GCC" = yes; then + CFLAGS="-O2" + else + CFLAGS= + fi +fi +echo "$as_me:$LINENO: checking for $CC option to accept ANSI C" >&5 +echo $ECHO_N "checking for $CC option to accept ANSI C... $ECHO_C" >&6 +if test "${ac_cv_prog_cc_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_prog_cc_stdc=no +ac_save_CC=$CC +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdarg.h> +#include <stdio.h> +#include <sys/types.h> +#include <sys/stat.h> +/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */ +struct buf { int x; }; +FILE * (*rcsopen) (struct buf *, struct stat *, int); +static char *e (p, i) + char **p; + int i; +{ + return p[i]; +} +static char *f (char * (*g) (char **, int), char **p, ...) +{ + char *s; + va_list v; + va_start (v,p); + s = g (p, va_arg (v,int)); + va_end (v); + return s; +} +int test (int i, double x); +struct s1 {int (*f) (int a);}; +struct s2 {int (*f) (double a);}; +int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int); +int argc; +char **argv; +int +main () +{ +return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1]; + ; + return 0; +} +_ACEOF +# Don't try gcc -ansi; that turns off useful extensions and +# breaks some systems' header files. +# AIX -qlanglvl=ansi +# Ultrix and OSF/1 -std1 +# HP-UX 10.20 and later -Ae +# HP-UX older versions -Aa -D_HPUX_SOURCE +# SVR4 -Xc -D__EXTENSIONS__ +for ac_arg in "" -qlanglvl=ansi -std1 -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__" +do + CC="$ac_save_CC $ac_arg" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cc_stdc=$ac_arg +break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext +done +rm -f conftest.$ac_ext conftest.$ac_objext +CC=$ac_save_CC + +fi + +case "x$ac_cv_prog_cc_stdc" in + x|xno) + echo "$as_me:$LINENO: result: none needed" >&5 +echo "${ECHO_T}none needed" >&6 ;; + *) + echo "$as_me:$LINENO: result: $ac_cv_prog_cc_stdc" >&5 +echo "${ECHO_T}$ac_cv_prog_cc_stdc" >&6 + CC="$CC $ac_cv_prog_cc_stdc" ;; +esac + +# Some people use a C++ compiler to compile C. Since we use `exit', +# in C++ we need to declare it. In case someone uses the same compiler +# for both compiling C and C++ we need to have the C++ compiler decide +# the declaration of exit, since it's the most demanding environment. +cat >conftest.$ac_ext <<_ACEOF +#ifndef __cplusplus + choke me +#endif +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + for ac_declaration in \ + ''\ + '#include <stdlib.h>' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +rm -f .deps 2>/dev/null +mkdir .deps 2>/dev/null +if test -d .deps; then + DEPDIR=.deps +else + # MS-DOS does not allow filenames that begin with a dot. + DEPDIR=_deps +fi +rmdir .deps 2>/dev/null + + + ac_config_commands="$ac_config_commands depfiles" + + +am_make=${MAKE-make} +cat > confinc << 'END' +doit: + @echo done +END +# If we don't find an include directive, just comment out the code. +echo "$as_me:$LINENO: checking for style of include used by $am_make" >&5 +echo $ECHO_N "checking for style of include used by $am_make... $ECHO_C" >&6 +am__include="#" +am__quote= +_am_result=none +# First try GNU make style include. +echo "include confinc" > confmf +# We grep out `Entering directory' and `Leaving directory' +# messages which can occur if `w' ends up in MAKEFLAGS. +# In particular we don't look at `^make:' because GNU make might +# be invoked under some other name (usually "gmake"), in which +# case it prints its new name instead of `make'. +if test "`$am_make -s -f confmf 2> /dev/null | fgrep -v 'ing directory'`" = "done"; then + am__include=include + am__quote= + _am_result=GNU +fi +# Now try BSD make style include. +if test "$am__include" = "#"; then + echo '.include "confinc"' > confmf + if test "`$am_make -s -f confmf 2> /dev/null`" = "done"; then + am__include=.include + am__quote="\"" + _am_result=BSD + fi +fi + + +echo "$as_me:$LINENO: result: $_am_result" >&5 +echo "${ECHO_T}$_am_result" >&6 +rm -f confinc confmf + +# Check whether --enable-dependency-tracking or --disable-dependency-tracking was given. +if test "${enable_dependency_tracking+set}" = set; then + enableval="$enable_dependency_tracking" + +fi; +if test "x$enable_dependency_tracking" != xno; then + am_depcomp="$ac_aux_dir/depcomp" + AMDEPBACKSLASH='\' +fi + + +if test "x$enable_dependency_tracking" != xno; then + AMDEP_TRUE= + AMDEP_FALSE='#' +else + AMDEP_TRUE='#' + AMDEP_FALSE= +fi + + + + +depcc="$CC" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CC_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CC_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CC_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CC_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CC_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CC_dependencies_compiler_type" >&6 +CCDEPMODE=depmode=$am_cv_CC_dependencies_compiler_type + + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$CXX"; then + ac_cv_prog_CXX="$CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_CXX="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +CXX=$ac_cv_prog_CXX +if test -n "$CXX"; then + echo "$as_me:$LINENO: result: $CXX" >&5 +echo "${ECHO_T}$CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$CXX" && break + done +fi +if test -z "$CXX"; then + ac_ct_CXX=$CXX + for ac_prog in $CCC g++ c++ gpp aCC CC cxx cc++ cl FCC KCC RCC xlC_r xlC +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_CXX"; then + ac_cv_prog_ac_ct_CXX="$ac_ct_CXX" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_CXX="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_CXX=$ac_cv_prog_ac_ct_CXX +if test -n "$ac_ct_CXX"; then + echo "$as_me:$LINENO: result: $ac_ct_CXX" >&5 +echo "${ECHO_T}$ac_ct_CXX" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_CXX" && break +done +test -n "$ac_ct_CXX" || ac_ct_CXX="g++" + + CXX=$ac_ct_CXX +fi + + +# Provide some information about the compiler. +echo "$as_me:$LINENO:" \ + "checking for C++ compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +echo "$as_me:$LINENO: checking whether we are using the GNU C++ compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU C++ compiler... $ECHO_C" >&6 +if test "${ac_cv_cxx_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ +#ifndef __GNUC__ + choke me +#endif + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_cxx_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_cxx_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_cxx_compiler_gnu" >&6 +GXX=`test $ac_compiler_gnu = yes && echo yes` +ac_test_CXXFLAGS=${CXXFLAGS+set} +ac_save_CXXFLAGS=$CXXFLAGS +CXXFLAGS="-g" +echo "$as_me:$LINENO: checking whether $CXX accepts -g" >&5 +echo $ECHO_N "checking whether $CXX accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_cxx_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_cxx_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_cxx_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_cxx_g" >&5 +echo "${ECHO_T}$ac_cv_prog_cxx_g" >&6 +if test "$ac_test_CXXFLAGS" = set; then + CXXFLAGS=$ac_save_CXXFLAGS +elif test $ac_cv_prog_cxx_g = yes; then + if test "$GXX" = yes; then + CXXFLAGS="-g -O2" + else + CXXFLAGS="-g" + fi +else + if test "$GXX" = yes; then + CXXFLAGS="-O2" + else + CXXFLAGS= + fi +fi +for ac_declaration in \ + ''\ + '#include <stdlib.h>' \ + 'extern "C" void std::exit (int) throw (); using std::exit;' \ + 'extern "C" void std::exit (int); using std::exit;' \ + 'extern "C" void exit (int) throw ();' \ + 'extern "C" void exit (int);' \ + 'void exit (int);' +do + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +continue +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_declaration +int +main () +{ +exit (42); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext +done +rm -f conftest* +if test -n "$ac_declaration"; then + echo '#ifdef __cplusplus' >>confdefs.h + echo $ac_declaration >>confdefs.h + echo '#endif' >>confdefs.h +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +depcc="$CXX" am_compiler_list= + +echo "$as_me:$LINENO: checking dependency style of $depcc" >&5 +echo $ECHO_N "checking dependency style of $depcc... $ECHO_C" >&6 +if test "${am_cv_CXX_dependencies_compiler_type+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$AMDEP_TRUE" && test -f "$am_depcomp"; then + # We make a subdir and do the tests there. Otherwise we can end up + # making bogus files that we don't know about and never remove. For + # instance it was reported that on HP-UX the gcc test will end up + # making a dummy file named `D' -- because `-MD' means `put the output + # in D'. + mkdir conftest.dir + # Copy depcomp to subdir because otherwise we won't find it if we're + # using a relative directory. + cp "$am_depcomp" conftest.dir + cd conftest.dir + + am_cv_CXX_dependencies_compiler_type=none + if test "$am_compiler_list" = ""; then + am_compiler_list=`sed -n 's/^#*\([a-zA-Z0-9]*\))$/\1/p' < ./depcomp` + fi + for depmode in $am_compiler_list; do + # We need to recreate these files for each test, as the compiler may + # overwrite some of them when testing with obscure command lines. + # This happens at least with the AIX C compiler. + echo '#include "conftest.h"' > conftest.c + echo 'int i;' > conftest.h + echo "${am__include} ${am__quote}conftest.Po${am__quote}" > confmf + + case $depmode in + nosideeffect) + # after this tag, mechanisms are not by side-effect, so they'll + # only be used when explicitly requested + if test "x$enable_dependency_tracking" = xyes; then + continue + else + break + fi + ;; + none) break ;; + esac + # We check with `-c' and `-o' for the sake of the "dashmstdout" + # mode. It turns out that the SunPro C++ compiler does not properly + # handle `-M -o', and we need to detect this. + if depmode=$depmode \ + source=conftest.c object=conftest.o \ + depfile=conftest.Po tmpdepfile=conftest.TPo \ + $SHELL ./depcomp $depcc -c conftest.c -o conftest.o >/dev/null 2>&1 && + grep conftest.h conftest.Po > /dev/null 2>&1 && + ${MAKE-make} -s -f confmf > /dev/null 2>&1; then + am_cv_CXX_dependencies_compiler_type=$depmode + break + fi + done + + cd .. + rm -rf conftest.dir +else + am_cv_CXX_dependencies_compiler_type=none +fi + +fi +echo "$as_me:$LINENO: result: $am_cv_CXX_dependencies_compiler_type" >&5 +echo "${ECHO_T}$am_cv_CXX_dependencies_compiler_type" >&6 +CXXDEPMODE=depmode=$am_cv_CXX_dependencies_compiler_type + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C preprocessor" >&5 +echo $ECHO_N "checking how to run the C preprocessor... $ECHO_C" >&6 +# On Suns, sometimes $CPP names a directory. +if test -n "$CPP" && test -d "$CPP"; then + CPP= +fi +if test -z "$CPP"; then + if test "${ac_cv_prog_CPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CPP needs to be expanded + for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp" + do + ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CPP=$CPP + +fi + CPP=$ac_cv_prog_CPP +else + ac_cv_prog_CPP=$CPP +fi +echo "$as_me:$LINENO: result: $CPP" >&5 +echo "${ECHO_T}$CPP" >&6 +ac_preproc_ok=false +for ac_c_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C preprocessor \"$CPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +echo "$as_me:$LINENO: checking for egrep" >&5 +echo $ECHO_N "checking for egrep... $ECHO_C" >&6 +if test "${ac_cv_prog_egrep+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if echo a | (grep -E '(a|b)') >/dev/null 2>&1 + then ac_cv_prog_egrep='grep -E' + else ac_cv_prog_egrep='egrep' + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_egrep" >&5 +echo "${ECHO_T}$ac_cv_prog_egrep" >&6 + EGREP=$ac_cv_prog_egrep + + +if test $ac_cv_c_compiler_gnu = yes; then + echo "$as_me:$LINENO: checking whether $CC needs -traditional" >&5 +echo $ECHO_N "checking whether $CC needs -traditional... $ECHO_C" >&6 +if test "${ac_cv_prog_gcc_traditional+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_pattern="Autoconf.*'x'" + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sgtty.h> +Autoconf TIOCGETP +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then + ac_cv_prog_gcc_traditional=yes +else + ac_cv_prog_gcc_traditional=no +fi +rm -f conftest* + + + if test $ac_cv_prog_gcc_traditional = no; then + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <termio.h> +Autoconf TCGETA +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "$ac_pattern" >/dev/null 2>&1; then + ac_cv_prog_gcc_traditional=yes +fi +rm -f conftest* + + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_gcc_traditional" >&5 +echo "${ECHO_T}$ac_cv_prog_gcc_traditional" >&6 + if test $ac_cv_prog_gcc_traditional = yes; then + CC="$CC -traditional" + fi +fi + +# Check whether --enable-shared or --disable-shared was given. +if test "${enable_shared+set}" = set; then + enableval="$enable_shared" + p=${PACKAGE-default} + case $enableval in + yes) enable_shared=yes ;; + no) enable_shared=no ;; + *) + enable_shared=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_shared=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_shared=yes +fi; + +# Check whether --enable-static or --disable-static was given. +if test "${enable_static+set}" = set; then + enableval="$enable_static" + p=${PACKAGE-default} + case $enableval in + yes) enable_static=yes ;; + no) enable_static=no ;; + *) + enable_static=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_static=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_static=yes +fi; + +# Check whether --enable-fast-install or --disable-fast-install was given. +if test "${enable_fast_install+set}" = set; then + enableval="$enable_fast_install" + p=${PACKAGE-default} + case $enableval in + yes) enable_fast_install=yes ;; + no) enable_fast_install=no ;; + *) + enable_fast_install=no + # Look at the argument we got. We use all the common list separators. + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for pkg in $enableval; do + IFS="$lt_save_ifs" + if test "X$pkg" = "X$p"; then + enable_fast_install=yes + fi + done + IFS="$lt_save_ifs" + ;; + esac +else + enable_fast_install=yes +fi; + +echo "$as_me:$LINENO: checking for a sed that does not truncate output" >&5 +echo $ECHO_N "checking for a sed that does not truncate output... $ECHO_C" >&6 +if test "${lt_cv_path_SED+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Loop through the user's path and test for sed and gsed. +# Then use that list of sed's as ones to test for truncation. +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for lt_ac_prog in sed gsed; do + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$lt_ac_prog$ac_exec_ext"; then + lt_ac_sed_list="$lt_ac_sed_list $as_dir/$lt_ac_prog$ac_exec_ext" + fi + done + done +done +lt_ac_max=0 +lt_ac_count=0 +# Add /usr/xpg4/bin/sed as it is typically found on Solaris +# along with /bin/sed that truncates output. +for lt_ac_sed in $lt_ac_sed_list /usr/xpg4/bin/sed; do + test ! -f $lt_ac_sed && break + cat /dev/null > conftest.in + lt_ac_count=0 + echo $ECHO_N "0123456789$ECHO_C" >conftest.in + # Check for GNU sed and select it if it is found. + if "$lt_ac_sed" --version 2>&1 < /dev/null | grep 'GNU' > /dev/null; then + lt_cv_path_SED=$lt_ac_sed + break + fi + while true; do + cat conftest.in conftest.in >conftest.tmp + mv conftest.tmp conftest.in + cp conftest.in conftest.nl + echo >>conftest.nl + $lt_ac_sed -e 's/a$//' < conftest.nl >conftest.out || break + cmp -s conftest.out conftest.nl || break + # 10000 chars as input seems more than enough + test $lt_ac_count -gt 10 && break + lt_ac_count=`expr $lt_ac_count + 1` + if test $lt_ac_count -gt $lt_ac_max; then + lt_ac_max=$lt_ac_count + lt_cv_path_SED=$lt_ac_sed + fi + done +done +SED=$lt_cv_path_SED + +fi + +echo "$as_me:$LINENO: result: $SED" >&5 +echo "${ECHO_T}$SED" >&6 + + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi; +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 +with_gnu_ld=$lt_cv_prog_gnu_ld + + +echo "$as_me:$LINENO: checking for $LD option to reload object files" >&5 +echo $ECHO_N "checking for $LD option to reload object files... $ECHO_C" >&6 +if test "${lt_cv_ld_reload_flag+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_ld_reload_flag='-r' +fi +echo "$as_me:$LINENO: result: $lt_cv_ld_reload_flag" >&5 +echo "${ECHO_T}$lt_cv_ld_reload_flag" >&6 +reload_flag=$lt_cv_ld_reload_flag +case $reload_flag in +"" | " "*) ;; +*) reload_flag=" $reload_flag" ;; +esac +reload_cmds='$LD$reload_flag -o $output$reload_objs' + +echo "$as_me:$LINENO: checking for BSD-compatible nm" >&5 +echo $ECHO_N "checking for BSD-compatible nm... $ECHO_C" >&6 +if test "${lt_cv_path_NM+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$NM"; then + # Let the user override the test. + lt_cv_path_NM="$NM" +else + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH /usr/ccs/bin /usr/ucb /bin; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + tmp_nm="$ac_dir/${ac_tool_prefix}nm" + if test -f "$tmp_nm" || test -f "$tmp_nm$ac_exeext" ; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + # Tru64's nm complains that /dev/null is an invalid object file + case `"$tmp_nm" -B /dev/null 2>&1 | sed '1q'` in + */dev/null* | *'Invalid file or object type'*) + lt_cv_path_NM="$tmp_nm -B" + break + ;; + *) + case `"$tmp_nm" -p /dev/null 2>&1 | sed '1q'` in + */dev/null*) + lt_cv_path_NM="$tmp_nm -p" + break + ;; + *) + lt_cv_path_NM=${lt_cv_path_NM="$tmp_nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + ;; + esac + esac + fi + done + IFS="$lt_save_ifs" + test -z "$lt_cv_path_NM" && lt_cv_path_NM=nm +fi +fi +echo "$as_me:$LINENO: result: $lt_cv_path_NM" >&5 +echo "${ECHO_T}$lt_cv_path_NM" >&6 +NM="$lt_cv_path_NM" + +echo "$as_me:$LINENO: checking whether ln -s works" >&5 +echo $ECHO_N "checking whether ln -s works... $ECHO_C" >&6 +LN_S=$as_ln_s +if test "$LN_S" = "ln -s"; then + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else + echo "$as_me:$LINENO: result: no, using $LN_S" >&5 +echo "${ECHO_T}no, using $LN_S" >&6 +fi + +echo "$as_me:$LINENO: checking how to recognise dependent libraries" >&5 +echo $ECHO_N "checking how to recognise dependent libraries... $ECHO_C" >&6 +if test "${lt_cv_deplibs_check_method+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_file_magic_cmd='$MAGIC_CMD' +lt_cv_file_magic_test_file= +lt_cv_deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [[regex]]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given extended regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. + +case $host_os in +aix4* | aix5*) + lt_cv_deplibs_check_method=pass_all + ;; + +beos*) + lt_cv_deplibs_check_method=pass_all + ;; + +bsdi4*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + lt_cv_file_magic_cmd='/usr/bin/file -L' + lt_cv_file_magic_test_file=/shlib/libc.so + ;; + +cygwin* | mingw* | pw32*) + # win32_libid is a shell function defined in ltmain.sh + lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' + lt_cv_file_magic_cmd='win32_libid' + ;; + +darwin* | rhapsody*) + # this will be overwritten by pass_all, but leave it in just in case + lt_cv_deplibs_check_method='file_magic Mach-O dynamically linked shared library' + lt_cv_file_magic_cmd='/usr/bin/file -L' + case "$host_os" in + rhapsody* | darwin1.[012]) + lt_cv_file_magic_test_file=`/System/Library/Frameworks/System.framework/System` + ;; + *) # Darwin 1.3 on + lt_cv_file_magic_test_file='/usr/lib/libSystem.dylib' + ;; + esac + lt_cv_deplibs_check_method=pass_all + ;; + +freebsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + case $host_cpu in + i*86 ) + # Not sure whether the presence of OpenBSD here was a mistake. + # Let's accept both of them until this is cleared up. + lt_cv_deplibs_check_method='file_magic (FreeBSD|OpenBSD)/i[3-9]86 (compact )?demand paged shared library' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + ;; + esac + else + lt_cv_deplibs_check_method=pass_all + fi + ;; + +gnu*) + lt_cv_deplibs_check_method=pass_all + ;; + +hpux10.20* | hpux11*) + lt_cv_file_magic_cmd=/usr/bin/file + case "$host_cpu" in + ia64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - IA64' + lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so + ;; + hppa*64*) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl + ;; + *) + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + irix5* | nonstopux*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case $LD in + *-32|*"-32 ") libmagic=32-bit;; + *-n32|*"-n32 ") libmagic=N32;; + *-64|*"-64 ") libmagic=64-bit;; + *) libmagic=never-match;; + esac + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method="file_magic ELF ${libmagic} MSB mips-[1234] dynamic lib MIPS - version 1" + ;; + esac + lt_cv_file_magic_test_file=`echo /lib${libsuff}/libc.so*` + lt_cv_deplibs_check_method=pass_all + ;; + +# This must be Linux ELF. +linux*) + case $host_cpu in + alpha* | hppa* | i*86 | ia64* | m68* | mips | mipsel | powerpc* | sparc* | s390* | sh* | x86_64*) + lt_cv_deplibs_check_method=pass_all ;; + *) + # glibc up to 2.1.1 does not perform some relocations on ARM + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' ;; + esac + lt_cv_file_magic_test_file=`echo /lib/libc.so* /lib/libc-*.so` + ;; + +netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ > /dev/null; then + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so\.[0-9]+\.[0-9]+|_pic\.a)$' + else + lt_cv_deplibs_check_method='match_pattern /lib[^/]+(\.so|_pic\.a)$' + fi + ;; + +newos6*) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (executable|dynamic lib)' + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=/usr/lib/libnls.so + ;; + +nto-qnx) + lt_cv_deplibs_check_method=unknown + ;; + +openbsd*) + lt_cv_file_magic_cmd=/usr/bin/file + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so.*` + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + else + lt_cv_deplibs_check_method='file_magic OpenBSD.* shared library' + fi + ;; + +osf3* | osf4* | osf5*) + # this will be overridden with pass_all, but let us keep it just in case + lt_cv_deplibs_check_method='file_magic COFF format alpha shared library' + lt_cv_file_magic_test_file=/shlib/libc.so + lt_cv_deplibs_check_method=pass_all + ;; + +sco3.2v5*) + lt_cv_deplibs_check_method=pass_all + ;; + +solaris*) + lt_cv_deplibs_check_method=pass_all + lt_cv_file_magic_test_file=/lib/libc.so + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + case $host_vendor in + motorola) + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + lt_cv_file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + ncr) + lt_cv_deplibs_check_method=pass_all + ;; + sequent) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + sni) + lt_cv_file_magic_cmd='/bin/file' + lt_cv_deplibs_check_method="file_magic ELF [0-9][0-9]*-bit [LM]SB dynamic lib" + lt_cv_file_magic_test_file=/lib/libc.so + ;; + siemens) + lt_cv_deplibs_check_method=pass_all + ;; + esac + ;; + +sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7* | sysv4*uw2*) + lt_cv_deplibs_check_method=pass_all + ;; +esac + +fi +echo "$as_me:$LINENO: result: $lt_cv_deplibs_check_method" >&5 +echo "${ECHO_T}$lt_cv_deplibs_check_method" >&6 +file_magic_cmd=$lt_cv_file_magic_cmd +deplibs_check_method=$lt_cv_deplibs_check_method +test -z "$deplibs_check_method" && deplibs_check_method=unknown + + + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + +fi; +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + +# Some flags need to be propagated to the compiler or linker for good +# libtool support. +case $host in +ia64-*-hpux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *ELF-32*) + HPUX_IA64_MODE="32" + ;; + *ELF-64*) + HPUX_IA64_MODE="64" + ;; + esac + fi + rm -rf conftest* + ;; +*-*-irix6*) + # Find out which ABI we are using. + echo '#line 4167 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + if test "$lt_cv_prog_gnu_ld" = yes; then + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -melf32bsmip" + ;; + *N32*) + LD="${LD-ld} -melf32bmipn32" + ;; + *64-bit*) + LD="${LD-ld} -melf64bmip" + ;; + esac + else + case `/usr/bin/file conftest.$ac_objext` in + *32-bit*) + LD="${LD-ld} -32" + ;; + *N32*) + LD="${LD-ld} -n32" + ;; + *64-bit*) + LD="${LD-ld} -64" + ;; + esac + fi + fi + rm -rf conftest* + ;; + +x86_64-*linux*|ppc*-*linux*|powerpc*-*linux*|s390*-*linux*|sparc*-*linux*) + # Find out which ABI we are using. + echo 'int i;' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case "`/usr/bin/file conftest.o`" in + *32-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_i386" + ;; + ppc64-*linux*) + LD="${LD-ld} -m elf32ppclinux" + ;; + s390x-*linux*) + LD="${LD-ld} -m elf_s390" + ;; + sparc64-*linux*) + LD="${LD-ld} -m elf32_sparc" + ;; + esac + ;; + *64-bit*) + case $host in + x86_64-*linux*) + LD="${LD-ld} -m elf_x86_64" + ;; + ppc*-*linux*|powerpc*-*linux*) + LD="${LD-ld} -m elf64ppc" + ;; + s390*-*linux*) + LD="${LD-ld} -m elf64_s390" + ;; + sparc*-*linux*) + LD="${LD-ld} -m elf64_sparc" + ;; + esac + ;; + esac + fi + rm -rf conftest* + ;; + +*-*-sco3.2v5*) + # On SCO OpenServer 5, we need -belf to get full-featured binaries. + SAVE_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -belf" + echo "$as_me:$LINENO: checking whether the C compiler needs -belf" >&5 +echo $ECHO_N "checking whether the C compiler needs -belf... $ECHO_C" >&6 +if test "${lt_cv_cc_needs_belf+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + lt_cv_cc_needs_belf=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +lt_cv_cc_needs_belf=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $lt_cv_cc_needs_belf" >&5 +echo "${ECHO_T}$lt_cv_cc_needs_belf" >&6 + if test x"$lt_cv_cc_needs_belf" != x"yes"; then + # this is probably gcc 2.8.0, egcs 1.0 or newer; no need for -belf + CFLAGS="$SAVE_CFLAGS" + fi + ;; + +esac + +need_locks="$enable_libtool_lock" + + +echo "$as_me:$LINENO: checking for ANSI C header files" >&5 +echo $ECHO_N "checking for ANSI C header files... $ECHO_C" >&6 +if test "${ac_cv_header_stdc+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <float.h> + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_header_stdc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_header_stdc=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +if test $ac_cv_header_stdc = yes; then + # SunOS 4.x string.h does not declare mem*, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <string.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "memchr" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <stdlib.h> + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "free" >/dev/null 2>&1; then + : +else + ac_cv_header_stdc=no +fi +rm -f conftest* + +fi + +if test $ac_cv_header_stdc = yes; then + # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi. + if test "$cross_compiling" = yes; then + : +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ctype.h> +#if ((' ' & 0x0FF) == 0x020) +# define ISLOWER(c) ('a' <= (c) && (c) <= 'z') +# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c)) +#else +# define ISLOWER(c) \ + (('a' <= (c) && (c) <= 'i') \ + || ('j' <= (c) && (c) <= 'r') \ + || ('s' <= (c) && (c) <= 'z')) +# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c)) +#endif + +#define XOR(e, f) (((e) && !(f)) || (!(e) && (f))) +int +main () +{ + int i; + for (i = 0; i < 256; i++) + if (XOR (islower (i), ISLOWER (i)) + || toupper (i) != TOUPPER (i)) + exit(2); + exit (0); +} +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +ac_cv_header_stdc=no +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi +fi +fi +echo "$as_me:$LINENO: result: $ac_cv_header_stdc" >&5 +echo "${ECHO_T}$ac_cv_header_stdc" >&6 +if test $ac_cv_header_stdc = yes; then + +cat >>confdefs.h <<\_ACEOF +#define STDC_HEADERS 1 +_ACEOF + +fi + +# On IRIX 5.3, sys/types and inttypes.h are conflicting. + + + + + + + + + +for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \ + inttypes.h stdint.h unistd.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default + +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + eval "$as_ac_Header=yes" +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +eval "$as_ac_Header=no" +fi +rm -f conftest.$ac_objext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + + +for ac_header in dlfcn.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu +echo "$as_me:$LINENO: checking how to run the C++ preprocessor" >&5 +echo $ECHO_N "checking how to run the C++ preprocessor... $ECHO_C" >&6 +if test -z "$CXXCPP"; then + if test "${ac_cv_prog_CXXCPP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # Double quotes because CXXCPP needs to be expanded + for CXXCPP in "$CXX -E" "/lib/cpp" + do + ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + break +fi + + done + ac_cv_prog_CXXCPP=$CXXCPP + +fi + CXXCPP=$ac_cv_prog_CXXCPP +else + ac_cv_prog_CXXCPP=$CXXCPP +fi +echo "$as_me:$LINENO: result: $CXXCPP" >&5 +echo "${ECHO_T}$CXXCPP" >&6 +ac_preproc_ok=false +for ac_cxx_preproc_warn_flag in '' yes +do + # Use a header file that comes with gcc, so configuring glibc + # with a fresh cross-compiler works. + # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + # <limits.h> exists even on freestanding compilers. + # On the NeXT, cc -E runs the code through the compiler's parser, + # not just through cpp. "Syntax error" is here to catch this case. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif + Syntax error +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + : +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Broken: fails on valid input. +continue +fi +rm -f conftest.err conftest.$ac_ext + + # OK, works on sane cases. Now check whether non-existent headers + # can be detected and how. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <ac_nonexistent.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_cxx_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + # Broken: success on invalid input. +continue +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + # Passes both tests. +ac_preproc_ok=: +break +fi +rm -f conftest.err conftest.$ac_ext + +done +# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped. +rm -f conftest.err conftest.$ac_ext +if $ac_preproc_ok; then + : +else + { { echo "$as_me:$LINENO: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&5 +echo "$as_me: error: C++ preprocessor \"$CXXCPP\" fails sanity check +See \`config.log' for more details." >&2;} + { (exit 1); exit 1; }; } +fi + +ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu +if test -n "$ac_tool_prefix"; then + for ac_prog in g77 f77 xlf frt pgf77 fl32 af77 fort77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95 + do + # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. +set dummy $ac_tool_prefix$ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$F77"; then + ac_cv_prog_F77="$F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_F77="$ac_tool_prefix$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +F77=$ac_cv_prog_F77 +if test -n "$F77"; then + echo "$as_me:$LINENO: result: $F77" >&5 +echo "${ECHO_T}$F77" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$F77" && break + done +fi +if test -z "$F77"; then + ac_ct_F77=$F77 + for ac_prog in g77 f77 xlf frt pgf77 fl32 af77 fort77 f90 xlf90 pgf90 epcf90 f95 fort xlf95 lf95 g95 +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_F77"; then + ac_cv_prog_ac_ct_F77="$ac_ct_F77" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_F77="$ac_prog" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +ac_ct_F77=$ac_cv_prog_ac_ct_F77 +if test -n "$ac_ct_F77"; then + echo "$as_me:$LINENO: result: $ac_ct_F77" >&5 +echo "${ECHO_T}$ac_ct_F77" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + test -n "$ac_ct_F77" && break +done + + F77=$ac_ct_F77 +fi + + +# Provide some information about the compiler. +echo "$as_me:5007:" \ + "checking for Fortran 77 compiler version" >&5 +ac_compiler=`set X $ac_compile; echo $2` +{ (eval echo "$as_me:$LINENO: \"$ac_compiler --version </dev/null >&5\"") >&5 + (eval $ac_compiler --version </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -v </dev/null >&5\"") >&5 + (eval $ac_compiler -v </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } +{ (eval echo "$as_me:$LINENO: \"$ac_compiler -V </dev/null >&5\"") >&5 + (eval $ac_compiler -V </dev/null >&5) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + +# If we don't use `.F' as extension, the preprocessor is not run on the +# input file. +ac_save_ext=$ac_ext +ac_ext=F +echo "$as_me:$LINENO: checking whether we are using the GNU Fortran 77 compiler" >&5 +echo $ECHO_N "checking whether we are using the GNU Fortran 77 compiler... $ECHO_C" >&6 +if test "${ac_cv_f77_compiler_gnu+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF + program main +#ifndef __GNUC__ + choke me +#endif + + end +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_compiler_gnu=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_compiler_gnu=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +ac_cv_f77_compiler_gnu=$ac_compiler_gnu + +fi +echo "$as_me:$LINENO: result: $ac_cv_f77_compiler_gnu" >&5 +echo "${ECHO_T}$ac_cv_f77_compiler_gnu" >&6 +ac_ext=$ac_save_ext +G77=`test $ac_compiler_gnu = yes && echo yes` +ac_test_FFLAGS=${FFLAGS+set} +ac_save_FFLAGS=$FFLAGS +FFLAGS= +echo "$as_me:$LINENO: checking whether $F77 accepts -g" >&5 +echo $ECHO_N "checking whether $F77 accepts -g... $ECHO_C" >&6 +if test "${ac_cv_prog_f77_g+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + FFLAGS=-g +cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_prog_f77_g=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_prog_f77_g=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext + +fi +echo "$as_me:$LINENO: result: $ac_cv_prog_f77_g" >&5 +echo "${ECHO_T}$ac_cv_prog_f77_g" >&6 +if test "$ac_test_FFLAGS" = set; then + FFLAGS=$ac_save_FFLAGS +elif test $ac_cv_prog_f77_g = yes; then + if test "$G77" = yes; then + FFLAGS="-g -O2" + else + FFLAGS="-g" + fi +else + if test "$G77" = yes; then + FFLAGS="-O2" + else + FFLAGS= + fi +fi +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + +# Autoconf 2.13's AC_OBJEXT and AC_EXEEXT macros only works for C compilers! + +# find the maximum length of command line arguments +echo "$as_me:$LINENO: checking the maximum length of command line arguments" >&5 +echo $ECHO_N "checking the maximum length of command line arguments... $ECHO_C" >&6 +if test "${lt_cv_sys_max_cmd_len+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + i=0 + testring="ABCD" + + case $build_os in + msdosdjgpp*) + # On DJGPP, this test can blow up pretty badly due to problems in libc + # (any single argument exceeding 2000 bytes causes a buffer overrun + # during glob expansion). Even if it were fixed, the result of this + # check would be larger than it should be. + lt_cv_sys_max_cmd_len=12288; # 12K is about right + ;; + + gnu*) + # Under GNU Hurd, this test is not required because there is + # no limit to the length of command line arguments. + # Libtool will interpret -1 as no limit whatsoever + lt_cv_sys_max_cmd_len=-1; + ;; + + cygwin* | mingw*) + # On Win9x/ME, this test blows up -- it succeeds, but takes + # about 5 minutes as the teststring grows exponentially. + # Worse, since 9x/ME are not pre-emptively multitasking, + # you end up with a "frozen" computer, even though with patience + # the test eventually succeeds (with a max line length of 256k). + # Instead, let's just punt: use the minimum linelength reported by + # all of the supported platforms: 8192 (on NT/2K/XP). + lt_cv_sys_max_cmd_len=8192; + ;; + + *) + # If test is not a shell built-in, we'll probably end up computing a + # maximum length that is only half of the actual maximum length, but + # we can't tell. + while (test "X"`$CONFIG_SHELL $0 --fallback-echo "X$testring" 2>/dev/null` \ + = "XX$testring") >/dev/null 2>&1 && + new_result=`expr "X$testring" : ".*" 2>&1` && + lt_cv_sys_max_cmd_len=$new_result && + test $i != 17 # 1/2 MB should be enough + do + i=`expr $i + 1` + testring=$testring$testring + done + testring= + # Add a significant safety factor because C++ compilers can tack on massive + # amounts of additional arguments before passing them to the linker. + # It appears as though 1/2 is a usable value. + lt_cv_sys_max_cmd_len=`expr $lt_cv_sys_max_cmd_len \/ 2` + ;; + esac + +fi + +if test -n $lt_cv_sys_max_cmd_len ; then + echo "$as_me:$LINENO: result: $lt_cv_sys_max_cmd_len" >&5 +echo "${ECHO_T}$lt_cv_sys_max_cmd_len" >&6 +else + echo "$as_me:$LINENO: result: none" >&5 +echo "${ECHO_T}none" >&6 +fi + + + + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo "$as_me:$LINENO: checking command to parse $NM output from $compiler object" >&5 +echo $ECHO_N "checking command to parse $NM output from $compiler object... $ECHO_C" >&6 +if test "${lt_cv_sys_global_symbol_pipe+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern int \1;/p'" + +# Transform an extracted symbol line into symbol name and symbol address +lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + +# Define system-specific variables. +case $host_os in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw* | pw32*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + if test "$host_cpu" = ia64; then + symcode='[ABCDEGRST]' + fi + lt_cv_sys_global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern int \1();/p' -e 's/^$symcode* .* \(.*\)$/extern char \1;/p'" + lt_cv_sys_global_symbol_to_c_name_address="sed -n -e 's/^: \([^ ]*\) $/ {\\\"\1\\\", (lt_ptr) 0},/p' -e 's/^$symcode* \([^ ]*\) \([^ ]*\)$/ {\"\2\", (lt_ptr) \&\2},/p'" + ;; +irix* | nonstopux*) + symcode='[BCDEGRST]' + ;; +osf*) + symcode='[BCDEGQRST]' + ;; +solaris* | sysv5*) + symcode='[BDRT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# Handle CRLF in mingw tool chain +opt_cr= +case $build_os in +mingw*) + opt_cr=`echo 'x\{0,1\}' | tr x '\015'` # option cr in regexp + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +case `$NM -V 2>&1` in +*GNU* | *'with BFD'*) + symcode='[ABCDGIRSTW]' ;; +esac + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + lt_cv_sys_global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode$symcode*\)[ ][ ]*\($ac_symprfx\)$sympat$opt_cr$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + + rm -f conftest* + cat > conftest.$ac_ext <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +int main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Now try to grab the symbols. + nlist=conftest.nm + if { (eval echo "$as_me:$LINENO: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\"") >&5 + (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s "$nlist"; then + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if grep ' nm_test_var$' "$nlist" >/dev/null; then + if grep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.$ac_ext +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$lt_cv_sys_global_symbol_to_cdecl"' < "$nlist" | grep -v main >> conftest.$ac_ext' + + cat <<EOF >> conftest.$ac_ext +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + $SED "s/^$symcode$symcode* \(.*\) \(.*\)$/ {\"\2\", (lt_ptr_t) \&\2},/" < "$nlist" | grep -v main >> conftest.$ac_ext + cat <<\EOF >> conftest.$ac_ext + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$ac_objext conftstm.$ac_objext + lt_save_LIBS="$LIBS" + lt_save_CFLAGS="$CFLAGS" + LIBS="conftstm.$ac_objext" + CFLAGS="$CFLAGS$lt_prog_compiler_no_builtin_flag" + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext}; then + pipe_works=yes + fi + LIBS="$lt_save_LIBS" + CFLAGS="$lt_save_CFLAGS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $lt_cv_sys_global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + fi + rm -f conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + lt_cv_sys_global_symbol_pipe= + fi +done + +fi + +if test -z "$lt_cv_sys_global_symbol_pipe"; then + lt_cv_sys_global_symbol_to_cdecl= +fi +if test -z "$lt_cv_sys_global_symbol_pipe$lt_cv_sys_global_symbol_to_cdecl"; then + echo "$as_me:$LINENO: result: failed" >&5 +echo "${ECHO_T}failed" >&6 +else + echo "$as_me:$LINENO: result: ok" >&5 +echo "${ECHO_T}ok" >&6 +fi + +echo "$as_me:$LINENO: checking for objdir" >&5 +echo $ECHO_N "checking for objdir... $ECHO_C" >&6 +if test "${lt_cv_objdir+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + lt_cv_objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + lt_cv_objdir=_libs +fi +rmdir .libs 2>/dev/null +fi +echo "$as_me:$LINENO: result: $lt_cv_objdir" >&5 +echo "${ECHO_T}$lt_cv_objdir" >&6 +objdir=$lt_cv_objdir + + + + + +case $host_os in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +# Constants: +rm="rm -f" + +# Global variables: +default_ofile=libtool +can_build_shared=yes + +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +libext=a +ltmain="$ac_aux_dir/ltmain.sh" +ofile="$default_ofile" +with_gnu_ld="$lt_cv_prog_gnu_ld" + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ar", so it can be a program name with args. +set dummy ${ac_tool_prefix}ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$AR"; then + ac_cv_prog_AR="$AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_AR="${ac_tool_prefix}ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +AR=$ac_cv_prog_AR +if test -n "$AR"; then + echo "$as_me:$LINENO: result: $AR" >&5 +echo "${ECHO_T}$AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_AR"; then + ac_ct_AR=$AR + # Extract the first word of "ar", so it can be a program name with args. +set dummy ar; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_AR+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_AR"; then + ac_cv_prog_ac_ct_AR="$ac_ct_AR" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_AR="ar" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_AR" && ac_cv_prog_ac_ct_AR="false" +fi +fi +ac_ct_AR=$ac_cv_prog_ac_ct_AR +if test -n "$ac_ct_AR"; then + echo "$as_me:$LINENO: result: $ac_ct_AR" >&5 +echo "${ECHO_T}$ac_ct_AR" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + AR=$ac_ct_AR +else + AR="$ac_cv_prog_AR" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args. +set dummy ${ac_tool_prefix}ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$RANLIB"; then + ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +RANLIB=$ac_cv_prog_RANLIB +if test -n "$RANLIB"; then + echo "$as_me:$LINENO: result: $RANLIB" >&5 +echo "${ECHO_T}$RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_RANLIB"; then + ac_ct_RANLIB=$RANLIB + # Extract the first word of "ranlib", so it can be a program name with args. +set dummy ranlib; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_RANLIB+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_RANLIB"; then + ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_RANLIB="ranlib" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_RANLIB" && ac_cv_prog_ac_ct_RANLIB=":" +fi +fi +ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB +if test -n "$ac_ct_RANLIB"; then + echo "$as_me:$LINENO: result: $ac_ct_RANLIB" >&5 +echo "${ECHO_T}$ac_ct_RANLIB" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + RANLIB=$ac_ct_RANLIB +else + RANLIB="$ac_cv_prog_RANLIB" +fi + +if test -n "$ac_tool_prefix"; then + # Extract the first word of "${ac_tool_prefix}strip", so it can be a program name with args. +set dummy ${ac_tool_prefix}strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$STRIP"; then + ac_cv_prog_STRIP="$STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_STRIP="${ac_tool_prefix}strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + +fi +fi +STRIP=$ac_cv_prog_STRIP +if test -n "$STRIP"; then + echo "$as_me:$LINENO: result: $STRIP" >&5 +echo "${ECHO_T}$STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +fi +if test -z "$ac_cv_prog_STRIP"; then + ac_ct_STRIP=$STRIP + # Extract the first word of "strip", so it can be a program name with args. +set dummy strip; ac_word=$2 +echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6 +if test "${ac_cv_prog_ac_ct_STRIP+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -n "$ac_ct_STRIP"; then + ac_cv_prog_ac_ct_STRIP="$ac_ct_STRIP" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if $as_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_ac_ct_STRIP="strip" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done + + test -z "$ac_cv_prog_ac_ct_STRIP" && ac_cv_prog_ac_ct_STRIP=":" +fi +fi +ac_ct_STRIP=$ac_cv_prog_ac_ct_STRIP +if test -n "$ac_ct_STRIP"; then + echo "$as_me:$LINENO: result: $ac_ct_STRIP" >&5 +echo "${ECHO_T}$ac_ct_STRIP" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + STRIP=$ac_ct_STRIP +else + STRIP="$ac_cv_prog_STRIP" +fi + + +old_CC="$CC" +old_CFLAGS="$CFLAGS" + +# Set sane defaults for various variables +test -z "$AR" && AR=ar +test -z "$AR_FLAGS" && AR_FLAGS=cru +test -z "$AS" && AS=as +test -z "$CC" && CC=cc +test -z "$LTCC" && LTCC=$CC +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$LD" && LD=ld +test -z "$LN_S" && LN_S="ln -s" +test -z "$MAGIC_CMD" && MAGIC_CMD=file +test -z "$NM" && NM=nm +test -z "$SED" && SED=sed +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$RANLIB" && RANLIB=: +test -z "$STRIP" && STRIP=: +test -z "$ac_objext" && ac_objext=o + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR $AR_FLAGS $oldlib$oldobjs$old_deplibs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +if test -n "$RANLIB"; then + case $host_os in + openbsd*) + old_postinstall_cmds="\$RANLIB -t \$oldlib~$old_postinstall_cmds" + ;; + *) + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" + ;; + esac + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" +fi + +# Only perform the check for file, if the check method requires it +case $deplibs_check_method in +file_magic*) + if test "$file_magic_cmd" = '$MAGIC_CMD'; then + echo "$as_me:$LINENO: checking for ${ac_tool_prefix}file" >&5 +echo $ECHO_N "checking for ${ac_tool_prefix}file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/${ac_tool_prefix}file; then + lt_cv_path_MAGIC_CMD="$ac_dir/${ac_tool_prefix}file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + +if test -z "$lt_cv_path_MAGIC_CMD"; then + if test -n "$ac_tool_prefix"; then + echo "$as_me:$LINENO: checking for file" >&5 +echo $ECHO_N "checking for file... $ECHO_C" >&6 +if test "${lt_cv_path_MAGIC_CMD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $MAGIC_CMD in +[\\/*] | ?:[\\/]*) + lt_cv_path_MAGIC_CMD="$MAGIC_CMD" # Let the user override the test with a path. + ;; +*) + lt_save_MAGIC_CMD="$MAGIC_CMD" + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + ac_dummy="/usr/bin$PATH_SEPARATOR$PATH" + for ac_dir in $ac_dummy; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/file; then + lt_cv_path_MAGIC_CMD="$ac_dir/file" + if test -n "$file_magic_test_file"; then + case $deplibs_check_method in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + MAGIC_CMD="$lt_cv_path_MAGIC_CMD" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + $EGREP "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac + fi + break + fi + done + IFS="$lt_save_ifs" + MAGIC_CMD="$lt_save_MAGIC_CMD" + ;; +esac +fi + +MAGIC_CMD="$lt_cv_path_MAGIC_CMD" +if test -n "$MAGIC_CMD"; then + echo "$as_me:$LINENO: result: $MAGIC_CMD" >&5 +echo "${ECHO_T}$MAGIC_CMD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + + else + MAGIC_CMD=: + fi +fi + + fi + ;; +esac + +enable_dlopen=no +enable_win32_dll=no + +# Check whether --enable-libtool-lock or --disable-libtool-lock was given. +if test "${enable_libtool_lock+set}" = set; then + enableval="$enable_libtool_lock" + +fi; +test "x$enable_libtool_lock" != xno && enable_libtool_lock=yes + + +# Check whether --with-pic or --without-pic was given. +if test "${with_pic+set}" = set; then + withval="$with_pic" + pic_mode="$withval" +else + pic_mode=default +fi; +test -z "$pic_mode" && pic_mode=default + +# Use C for the default configuration in the libtool script +tagname= +lt_save_CC="$CC" +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + +# Source file extension for C test sources. +ac_ext=c + +# Object file extension for compiled C test sources. +objext=o +objext=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(){return(0);}\n' + + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# +# Check for any special shared library compilation flags. +# +lt_prog_cc_shlib= +if test "$GCC" = no; then + case $host_os in + sco3.2v5*) + lt_prog_cc_shlib='-belf' + ;; + esac +fi +if test -n "$lt_prog_cc_shlib"; then + { echo "$as_me:$LINENO: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&5 +echo "$as_me: WARNING: \`$CC' requires \`$lt_prog_cc_shlib' to build shared libraries" >&2;} + if echo "$old_CC $old_CFLAGS " | grep "[ ]$lt_prog_cc_shlib[ ]" >/dev/null; then : + else + { echo "$as_me:$LINENO: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&5 +echo "$as_me: WARNING: add \`$lt_prog_cc_shlib' to the CC or CFLAGS env variable and reconfigure" >&2;} + lt_cv_prog_cc_can_build_shared=no + fi +fi + + +# +# Check to make sure the static flag actually works. +# +echo "$as_me:$LINENO: checking if $compiler static flag $lt_prog_compiler_static works" >&5 +echo $ECHO_N "checking if $compiler static flag $lt_prog_compiler_static works... $ECHO_C" >&6 +if test "${lt_prog_compiler_static_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_static_works=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS $lt_prog_compiler_static" + printf "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + else + lt_prog_compiler_static_works=yes + fi + fi + $rm conftest* + LDFLAGS="$save_LDFLAGS" + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_static_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_static_works" >&6 + +if test x"$lt_prog_compiler_static_works" = xyes; then + : +else + lt_prog_compiler_static= +fi + + + + +lt_prog_compiler_no_builtin_flag= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag=' -fno-builtin' + + echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:6012: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:6016: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag="$lt_prog_compiler_no_builtin_flag -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl= +lt_prog_compiler_pic= +lt_prog_compiler_static= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + if test "$GCC" = yes; then + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_static='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static='-Bstatic' + else + lt_prog_compiler_static='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + linux*) + case $CC in + icc|ecc) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-static' + ;; + ccc) + lt_prog_compiler_wl='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static='-non_shared' + ;; + + sco3.2v5*) + lt_prog_compiler_pic='-Kpic' + lt_prog_compiler_static='-dn' + ;; + + solaris*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sunos4*) + lt_prog_compiler_wl='-Qoption ld ' + lt_prog_compiler_pic='-PIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_pic='-KPIC' + lt_prog_compiler_static='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic='-Kconform_pic' + lt_prog_compiler_static='-Bstatic' + fi + ;; + + uts4*) + lt_prog_compiler_pic='-pic' + lt_prog_compiler_static='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic"; then + echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:6244: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:6248: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_prog_compiler_pic_works=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works" >&6 + +if test x"$lt_prog_compiler_pic_works" = xyes; then + case $lt_prog_compiler_pic in + "" | " "*) ;; + *) lt_prog_compiler_pic=" $lt_prog_compiler_pic" ;; + esac +else + lt_prog_compiler_pic= + lt_prog_compiler_can_build_shared=no +fi + +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic= + ;; + *) + lt_prog_compiler_pic="$lt_prog_compiler_pic -DPIC" + ;; +esac + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:6311: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:6315: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + lt_cv_prog_compiler_c_o=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag= + enable_shared_with_static_runtimes=no + archive_cmds= + archive_expsym_cmds= + old_archive_From_new_cmds= + old_archive_from_expsyms_cmds= + export_dynamic_flag_spec= + whole_archive_flag_spec= + thread_safe_flag_spec= + hardcode_libdir_flag_spec= + hardcode_libdir_flag_spec_ld= + hardcode_libdir_separator= + hardcode_direct=no + hardcode_minus_L=no + hardcode_shlibpath_var=unsupported + link_all_deplibs=unknown + hardcode_automatic=no + module_cmds= + module_expsym_cmds= + always_export_symbols=no + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=no + enable_shared_with_static_runtimes=yes + export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + archive_expsym_cmds="$tmp_archive_cmds" + fi + else + ld_shlibs=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds='' + hardcode_direct=yes + hardcode_libdir_separator=':' + link_all_deplibs=yes + + if test "$GCC" = yes; then + case $host_os in aix4.012|aix4.012.*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag="-z nodefs" + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag=' ${wl}-bernotok' + allow_undefined_flag=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + always_export_symbols=yes + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec=' ' + archive_cmds_need_lc=yes + # This is similar to how AIX traditionally builds it's shared libraries. + archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + bsdi4*) + export_dynamic_flag_spec=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes=yes + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + archive_cmds_need_lc=no + case "$host_os" in + rhapsody* | darwin1.[012]) + allow_undefined_flag='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && allow_undefined_flag='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='-all_load $convenience' + link_all_deplibs=yes + fi + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + export_dynamic_flag_spec='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld='+b $libdir' + hardcode_libdir_separator=: + hardcode_direct=no + hardcode_shlibpath_var=no + ;; + ia64*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=no + hardcode_shlibpath_var=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + *) + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + export_dynamic_flag_spec='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld='-rpath $libdir' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + link_all_deplibs=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + newsos6) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_shlibpath_var=no + ;; + + openbsd*) + hardcode_direct=yes + hardcode_shlibpath_var=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + export_dynamic_flag_spec='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-R$libdir' + ;; + *) + archive_cmds='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec='-rpath $libdir' + fi + hardcode_libdir_separator=: + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z text' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + link_all_deplibs=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds='$CC -r -o $output$reload_objs' + hardcode_direct=no + ;; + motorola) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + no_undefined_flag='${wl}-z ${wl}text' + if test "$GCC" = yes; then + archive_cmds='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + sysv5*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec= + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs" >&5 +echo "${ECHO_T}$ld_shlibs" >&6 +test "$ld_shlibs" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc=no + else + archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc" >&5 +echo "${ECHO_T}$archive_cmds_need_lc" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var " || \ + test "X$hardcode_automatic"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, )" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action" >&5 +echo "${ECHO_T}$hardcode_action" >&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + ;; + *) + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + esac +fi + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.01* | freebsdelf3.01*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '#line 7676 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +char (*f) () = shl_load; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shl_load; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6 +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +char (*f) () = dlopen; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != dlopen; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6 +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_svld_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dld_link (); +int +main () +{ +dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_dld_link=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 8372 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6 + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 8470 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# Report which librarie types wil actually be built +echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + if test "$host_cpu" != ia64 && test "$aix_use_runtimelinking" = no ; then + test "$enable_shared" = yes && enable_static=no + fi + ;; + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + archive_cmds_need_lc=no + case "$host_os" in + rhapsody* | darwin1.[012]) + allow_undefined_flag='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && allow_undefined_flag='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + output_verbose_link_cmd='echo' + archive_cmds='$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring' + module_cmds='$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + archive_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + module_expsym_cmds='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + hardcode_direct=no + hardcode_automatic=yes + hardcode_shlibpath_var=unsupported + whole_archive_flag_spec='-all_load $convenience' + link_all_deplibs=yes + fi + ;; +esac +echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6 + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler \ + CC \ + LD \ + lt_prog_compiler_wl \ + lt_prog_compiler_pic \ + lt_prog_compiler_static \ + lt_prog_compiler_no_builtin_flag \ + export_dynamic_flag_spec \ + thread_safe_flag_spec \ + whole_archive_flag_spec \ + enable_shared_with_static_runtimes \ + old_archive_cmds \ + old_archive_from_new_cmds \ + predep_objects \ + postdep_objects \ + predeps \ + postdeps \ + compiler_lib_search_path \ + archive_cmds \ + archive_expsym_cmds \ + postinstall_cmds \ + postuninstall_cmds \ + old_archive_from_expsyms_cmds \ + allow_undefined_flag \ + no_undefined_flag \ + export_symbols_cmds \ + hardcode_libdir_flag_spec \ + hardcode_libdir_flag_spec_ld \ + hardcode_libdir_separator \ + hardcode_automatic \ + module_cmds \ + module_expsym_cmds \ + lt_cv_prog_compiler_c_o \ + exclude_expsyms \ + include_expsyms; do + + case $var in + old_archive_cmds | \ + old_archive_from_new_cmds | \ + archive_cmds | \ + archive_expsym_cmds | \ + module_cmds | \ + module_expsym_cmds | \ + old_archive_from_expsyms_cmds | \ + export_symbols_cmds | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="${ofile}T" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + $rm -f "$cfgfile" + { echo "$as_me:$LINENO: creating $ofile" >&5 +echo "$as_me: creating $ofile" >&6;} + + cat <<__EOF__ >> "$cfgfile" +#! $SHELL + +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltmain.sh. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# +# This file is part of GNU Libtool: +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A sed program that does not truncate output. +SED=$lt_SED + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="$SED -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +# The names of the tagged configurations supported by this script. +available_tags= + +# ### BEGIN LIBTOOL CONFIG + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_compiler + +# Is the compiler the GNU C compiler? +with_gcc=$GCC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds +archive_expsym_cmds=$lt_archive_expsym_cmds +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds +module_expsym_cmds=$lt_module_expsym_cmds + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms + +# ### END LIBTOOL CONFIG + +__EOF__ + + + case $host_os in + aix3*) + cat <<\EOF >> "$cfgfile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + sed '$q' "$ltmain" >> "$cfgfile" || (rm -f "$cfgfile"; exit 1) + + mv -f "$cfgfile" "$ofile" || \ + (rm -f "$ofile" && cp "$cfgfile" "$ofile" && rm -f "$cfgfile") + chmod +x "$ofile" + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + +# Check whether --with-tags or --without-tags was given. +if test "${with_tags+set}" = set; then + withval="$with_tags" + tagnames="$withval" +fi; + +if test -f "$ltmain" && test -n "$tagnames"; then + if test ! -f "${ofile}"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not exist" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not exist" >&2;} + fi + + if test -z "$LTCC"; then + eval "`$SHELL ${ofile} --config | grep '^LTCC='`" + if test -z "$LTCC"; then + { echo "$as_me:$LINENO: WARNING: output file \`$ofile' does not look like a libtool script" >&5 +echo "$as_me: WARNING: output file \`$ofile' does not look like a libtool script" >&2;} + else + { echo "$as_me:$LINENO: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&5 +echo "$as_me: WARNING: using \`LTCC=$LTCC', extracted from \`$ofile'" >&2;} + fi + fi + + # Extract list of available tagged configurations in $ofile. + # Note that this assumes the entire list is on one line. + available_tags=`grep "^available_tags=" "${ofile}" | $SED -e 's/available_tags=\(.*$\)/\1/' -e 's/\"//g'` + + lt_save_ifs="$IFS"; IFS="${IFS}$PATH_SEPARATOR," + for tagname in $tagnames; do + IFS="$lt_save_ifs" + # Check whether tagname contains only valid characters + case `$echo "X$tagname" | $Xsed -e 's:[-_ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890,/]::g'` in + "") ;; + *) { { echo "$as_me:$LINENO: error: invalid tag name: $tagname" >&5 +echo "$as_me: error: invalid tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + if grep "^# ### BEGIN LIBTOOL TAG CONFIG: $tagname$" < "${ofile}" > /dev/null + then + { { echo "$as_me:$LINENO: error: tag name \"$tagname\" already exists" >&5 +echo "$as_me: error: tag name \"$tagname\" already exists" >&2;} + { (exit 1); exit 1; }; } + fi + + # Update the list of available tags. + if test -n "$tagname"; then + echo appending configuration tag \"$tagname\" to $ofile + + case $tagname in + CXX) + if test -n "$CXX" && test "X$CXX" != "Xno"; then + ac_ext=cc +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + + + +archive_cmds_need_lc_CXX=no +allow_undefined_flag_CXX= +always_export_symbols_CXX=no +archive_expsym_cmds_CXX= +export_dynamic_flag_spec_CXX= +hardcode_direct_CXX=no +hardcode_libdir_flag_spec_CXX= +hardcode_libdir_flag_spec_ld_CXX= +hardcode_libdir_separator_CXX= +hardcode_minus_L_CXX=no +hardcode_automatic_CXX=no +module_cmds_CXX= +module_expsym_cmds_CXX= +link_all_deplibs_CXX=unknown +old_archive_cmds_CXX=$old_archive_cmds +no_undefined_flag_CXX= +whole_archive_flag_spec_CXX= +enable_shared_with_static_runtimes_CXX=no + +# Dependencies to place before and after the object being linked: +predep_objects_CXX= +postdep_objects_CXX= +predeps_CXX= +postdeps_CXX= +compiler_lib_search_path_CXX= + +# Source file extension for C++ test sources. +ac_ext=cc + +# Object file extension for compiled C++ test sources. +objext=o +objext_CXX=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="int some_variable = 0;\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='int main(int, char *) { return(0); }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC=$CC +lt_save_LD=$LD +lt_save_GCC=$GCC +GCC=$GXX +lt_save_with_gnu_ld=$with_gnu_ld +lt_save_path_LD=$lt_cv_path_LD +if test -n "${lt_cv_prog_gnu_ldcxx+set}"; then + lt_cv_prog_gnu_ld=$lt_cv_prog_gnu_ldcxx +else + unset lt_cv_prog_gnu_ld +fi +if test -n "${lt_cv_path_LDCXX+set}"; then + lt_cv_path_LD=$lt_cv_path_LDCXX +else + unset lt_cv_path_LD +fi +test -z "${LDCXX+set}" || LD=$LDCXX +CC=${CXX-"c++"} +compiler=$CC +compiler_CXX=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +# We don't want -fno-exception wen compiling C++ code, so set the +# no_builtin_flag separately +if test "$GXX" = yes; then + lt_prog_compiler_no_builtin_flag_CXX=' -fno-builtin' +else + lt_prog_compiler_no_builtin_flag_CXX= +fi + +if test "$GXX" = yes; then + # Set up default GNU C++ configuration + + +# Check whether --with-gnu-ld or --without-gnu-ld was given. +if test "${with_gnu_ld+set}" = set; then + withval="$with_gnu_ld" + test "$withval" = no || with_gnu_ld=yes +else + with_gnu_ld=no +fi; +ac_prog=ld +if test "$GCC" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo "$as_me:$LINENO: checking for ld used by $CC" >&5 +echo $ECHO_N "checking for ld used by $CC... $ECHO_C" >&6 + case $host in + *-*-mingw*) + # gcc leaves a trailing carriage return which upsets mingw + ac_prog=`($CC -print-prog-name=ld) 2>&5 | tr -d '\015'` ;; + *) + ac_prog=`($CC -print-prog-name=ld) 2>&5` ;; + esac + case $ac_prog in + # Accept absolute paths. + [\\/]* | ?:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| $SED 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| $SED "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we aren't using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac +elif test "$with_gnu_ld" = yes; then + echo "$as_me:$LINENO: checking for GNU ld" >&5 +echo $ECHO_N "checking for GNU ld... $ECHO_C" >&6 +else + echo "$as_me:$LINENO: checking for non-GNU ld" >&5 +echo $ECHO_N "checking for non-GNU ld... $ECHO_C" >&6 +fi +if test "${lt_cv_path_LD+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test -z "$LD"; then + lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR + for ac_dir in $PATH; do + IFS="$lt_save_ifs" + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + lt_cv_path_LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + case `"$lt_cv_path_LD" -v 2>&1 </dev/null` in + *GNU* | *'with BFD'*) + test "$with_gnu_ld" != no && break + ;; + *) + test "$with_gnu_ld" != yes && break + ;; + esac + fi + done + IFS="$lt_save_ifs" +else + lt_cv_path_LD="$LD" # Let the user override the test with a path. +fi +fi + +LD="$lt_cv_path_LD" +if test -n "$LD"; then + echo "$as_me:$LINENO: result: $LD" >&5 +echo "${ECHO_T}$LD" >&6 +else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi +test -z "$LD" && { { echo "$as_me:$LINENO: error: no acceptable ld found in \$PATH" >&5 +echo "$as_me: error: no acceptable ld found in \$PATH" >&2;} + { (exit 1); exit 1; }; } +echo "$as_me:$LINENO: checking if the linker ($LD) is GNU ld" >&5 +echo $ECHO_N "checking if the linker ($LD) is GNU ld... $ECHO_C" >&6 +if test "${lt_cv_prog_gnu_ld+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + # I'd rather use --version here, but apparently some GNU ld's only accept -v. +case `$LD -v 2>&1 </dev/null` in +*GNU* | *'with BFD'*) + lt_cv_prog_gnu_ld=yes + ;; +*) + lt_cv_prog_gnu_ld=no + ;; +esac +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_gnu_ld" >&5 +echo "${ECHO_T}$lt_cv_prog_gnu_ld" >&6 +with_gnu_ld=$lt_cv_prog_gnu_ld + + + + # Check if GNU C++ uses GNU ld as the underlying linker, since the + # archiving commands below assume that GNU ld is being used. + if test "$with_gnu_ld" = yes; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # If archive_cmds runs LD, not CC, wlarc should be empty + # XXX I think wlarc can be eliminated in ltcf-cxx, but I need to + # investigate it a little bit more. (MM) + wlarc='${wl}' + + # ancient GNU ld didn't support --whole-archive et. al. + if eval "`$CC -print-prog-name=ld` --help 2>&1" | \ + grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_CXX="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_CXX= + fi + else + with_gnu_ld=no + wlarc= + + # A generic and very simple default shared library creation + # command for GNU C++ for the case where it uses the native + # linker, instead of GNU ld. If possible, this setting should + # overridden to take advantage of the native linker features on + # the platform it is being used on. + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $lib' + fi + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + +else + GXX=no + with_gnu_ld=no + wlarc= +fi + +# PORTME: fill in a description of your system's C++ link characteristics +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 +ld_shlibs_CXX=yes +case $host_os in + aix3*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + case $ld_flag in + *-brtl*) + aix_use_runtimelinking=yes + break + ;; + esac + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_CXX='' + hardcode_direct_CXX=yes + hardcode_libdir_separator_CXX=':' + link_all_deplibs_CXX=yes + + if test "$GXX" = yes; then + case $host_os in aix4.012|aix4.012.*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_CXX=yes + else + # We have old collect2 + hardcode_direct_CXX=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_CXX=yes + hardcode_libdir_flag_spec_CXX='-L$libdir' + hardcode_libdir_separator_CXX= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_CXX=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_CXX='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + + archive_expsym_cmds_CXX="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_CXX='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_CXX="-z nodefs" + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_CXX='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_CXX=' ${wl}-bernotok' + allow_undefined_flag_CXX=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + always_export_symbols_CXX=yes + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_CXX=' ' + archive_cmds_need_lc_CXX=yes + # This is similar to how AIX traditionally builds it's shared libraries. + archive_expsym_cmds_CXX="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + chorus*) + case $cc_basename in + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, CXX) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_CXX='-L$libdir' + allow_undefined_flag_CXX=unsupported + always_export_symbols_CXX=no + enable_shared_with_static_runtimes_CXX=yes + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_CXX='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared -nostdlib $output_objdir/$soname.def $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs_CXX=no + fi + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + archive_cmds_need_lc_CXX=no + case "$host_os" in + rhapsody* | darwin1.[012]) + allow_undefined_flag_CXX='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && allow_undefined_flag_CXX='-flat_namespace -undefined suppress' + ;; + esac + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_CXX='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_CXX='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_CXX='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_CXX='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + hardcode_direct_CXX=no + hardcode_automatic_CXX=yes + hardcode_shlibpath_var_CXX=unsupported + whole_archive_flag_spec_CXX='-all_load $convenience' + link_all_deplibs_CXX=yes + fi + ;; + + dgux*) + case $cc_basename in + ec++) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + ghcx) + # Green Hills C++ Compiler + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + freebsd12*) + # C++ shared libraries reported to be fairly broken before switch to ELF + ld_shlibs_CXX=no + ;; + freebsd-elf*) + archive_cmds_need_lc_CXX=no + ;; + freebsd*) + # FreeBSD 3 and later use GNU C++ and GNU ld with standard ELF + # conventions + ld_shlibs_CXX=yes + ;; + gnu*) + ;; + hpux9*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC) + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -b ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | egrep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + archive_cmds_CXX='$rm $output_objdir/$soname~$CC -shared -nostdlib -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + hpux10*|hpux11*) + if test $with_gnu_ld = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld_CXX='+b $libdir' + hardcode_libdir_separator_CXX=: + ;; + ia64*) + hardcode_libdir_flag_spec_CXX='-L$libdir' + ;; + *) + hardcode_libdir_flag_spec_CXX='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_CXX=: + export_dynamic_flag_spec_CXX='${wl}-E' + ;; + esac + fi + case "$host_cpu" in + hppa*64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + ;; + ia64*) + hardcode_direct_CXX=no + hardcode_shlibpath_var_CXX=no + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + *) + hardcode_direct_CXX=yes + hardcode_minus_L_CXX=yes # Not in the search PATH, + # but as the default + # location of the library. + ;; + esac + + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + aCC) + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + archive_cmds_CXX='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | grep "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes; then + if test $with_gnu_ld = no; then + case "$host_cpu" in + ia64*|hppa*64*) + archive_cmds_CXX='$LD -b +h $soname -o $lib $linker_flags $libobjs $deplibs' + ;; + *) + archive_cmds_CXX='$CC -shared -nostdlib -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + ;; + esac + fi + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + irix5* | irix6*) + case $cc_basename in + CC) + # SGI C++ + archive_cmds_CXX='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + # Archives containing C++ object files must be created using + # "CC -ar", where "CC" is the IRIX C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -ar -WR,-u -o $oldlib $oldobjs' + ;; + *) + if test "$GXX" = yes; then + if test "$with_gnu_ld" = no; then + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + archive_cmds_CXX='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` -o $lib' + fi + fi + link_all_deplibs_CXX=yes + ;; + esac + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + ;; + linux*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + archive_expsym_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib ${wl}-retain-symbols-file,$export_symbols; mv \$templib $lib' + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | grep "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + hardcode_libdir_flag_spec_CXX='${wl}--rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + ;; + icpc) + # Intel C++ + with_gnu_ld=yes + archive_cmds_need_lc_CXX=no + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + export_dynamic_flag_spec_CXX='${wl}--export-dynamic' + whole_archive_flag_spec_CXX='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + ;; + cxx) + # Compaq C++ + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $wl$soname -o $lib ${wl}-retain-symbols-file $wl$export_symbols' + + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + esac + ;; + lynxos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + m88k*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + mvs*) + case $cc_basename in + cxx) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_CXX='$LD -Bshareable -o $lib $predep_objects $libobjs $deplibs $postdep_objects $linker_flags' + wlarc= + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_direct_CXX=yes + hardcode_shlibpath_var_CXX=no + fi + # Workaround some broken pre-1.5 toolchains + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep conftest.$objext | $SED -e "s:-lgcc -lc -lgcc::"' + ;; + osf3*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # "CC -Bstatic", where "CC" is the KAI C++ compiler. + old_archive_cmds_CXX='$CC -Bstatic -o $oldlib $oldobjs' + + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx) + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && echo ${wl}-set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + osf4* | osf5*) + case $cc_basename in + KCC) + # Kuck and Associates, Inc. (KAI) C++ Compiler + + # KCC will only create a shared library if the output file + # ends with ".so" (or ".sl" for HP-UX), so rename the library + # to its proper name (with version) after linking. + archive_cmds_CXX='tempext=`echo $shared_ext | $SED -e '\''s/\([^()0-9A-Za-z{}]\)/\\\\\1/g'\''`; templib=`echo $lib | $SED -e "s/\${tempext}\..*/.so/"`; $CC $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags --soname $soname -o \$templib; mv \$templib $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath,$libdir' + hardcode_libdir_separator_CXX=: + + # Archives containing C++ object files must be created using + # the KAI C++ compiler. + old_archive_cmds_CXX='$CC -o $oldlib $oldobjs' + ;; + RCC) + # Rational C++ 2.4.1 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + cxx) + allow_undefined_flag_CXX=' -expect_unresolved \*' + archive_cmds_CXX='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + archive_expsym_cmds_CXX='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ + echo "-hidden">> $lib.exp~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname -Wl,-input -Wl,$lib.exp `test -n "$verstring" && echo -set_version $verstring` -update_registry $objdir/so_locations -o $lib~ + $rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-rpath $libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "ld" | grep -v "ld:"`; templist=`echo $templist | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + ;; + *) + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + allow_undefined_flag_CXX=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_CXX='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + + hardcode_libdir_flag_spec_CXX='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_CXX=: + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep "\-L"' + + else + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + fi + ;; + esac + ;; + psos*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + sco*) + archive_cmds_need_lc_CXX=no + case $cc_basename in + CC) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + lcc) + # Lucid + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + no_undefined_flag_CXX=' -zdefs' + archive_cmds_CXX='$CC -G${allow_undefined_flag} -nolib -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G${allow_undefined_flag} -nolib ${wl}-M ${wl}$lib.exp -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + hardcode_libdir_flag_spec_CXX='-R$libdir' + hardcode_shlibpath_var_CXX=no + case $host_os in + solaris2.0-5 | solaris2.0-5.*) ;; + *) + # The C++ compiler is used as linker so we must use $wl + # flag to pass the commands to the underlying system + # linker. + # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_CXX='${wl}-z ${wl}allextract$convenience ${wl}-z ${wl}defaultextract' + ;; + esac + link_all_deplibs_CXX=yes + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + # + # There doesn't appear to be a way to prevent this compiler from + # explicitly linking system object files so we need to strip them + # from the output so that they don't get included in the library + # dependencies. + output_verbose_link_cmd='templist=`$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep "\-[LR]"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; echo $list' + + # Archives containing C++ object files must be created using + # "CC -xar", where "CC" is the Sun C++ compiler. This is + # necessary to make sure instantiated templates are included + # in the archive. + old_archive_cmds_CXX='$CC -xar -o $oldlib $oldobjs' + ;; + gcx) + # Green Hills C++ Compiler + archive_cmds_CXX='$CC -shared $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + + # The C++ compiler must be used to create the archive. + old_archive_cmds_CXX='$CC $LDFLAGS -archive -o $oldlib $oldobjs' + ;; + *) + # GNU C++ compiler with Solaris linker + if test "$GXX" = yes && test "$with_gnu_ld" = no; then + no_undefined_flag_CXX=' ${wl}-z ${wl}defs' + if $CC --version | grep -v '^2\.7' > /dev/null; then + archive_cmds_CXX='$CC -shared -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -shared $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + else + # g++ 2.7 appears to require `-G' NOT `-shared' on this + # platform. + archive_cmds_CXX='$CC -G -nostdlib $LDFLAGS $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-h $wl$soname -o $lib' + archive_expsym_cmds_CXX='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -G -nostdlib ${wl}-M $wl$lib.exp -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags~$rm $lib.exp' + + # Commands to make compiler produce verbose output that lists + # what "hidden" libraries, object files and flags are used when + # linking a shared library. + output_verbose_link_cmd="$CC -G $CFLAGS -v conftest.$objext 2>&1 | grep \"\-L\"" + fi + + hardcode_libdir_flag_spec_CXX='${wl}-R $wl$libdir' + fi + ;; + esac + ;; + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + archive_cmds_need_lc_CXX=no + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + esac + ;; + vxworks*) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; + *) + # FIXME: insert proper C++ library support + ld_shlibs_CXX=no + ;; +esac +echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6 +test "$ld_shlibs_CXX" = no && can_build_shared=no + +GCC_CXX="$GXX" +LD_CXX="$LD" + + +cat > conftest.$ac_ext <<EOF +class Foo +{ +public: + Foo (void) { a = 0; } +private: + int a; +}; +EOF + +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + # Parse the compiler output and extract the necessary + # objects, libraries and library flags. + + # Sentinel used to keep track of whether or not we are before + # the conftest object file. + pre_test_object_deps_done=no + + # The `*' in the case matches for architectures that use `case' in + # $output_verbose_cmd can trigger glob expansion during the loop + # eval without this substitution. + output_verbose_link_cmd="`$echo \"X$output_verbose_link_cmd\" | $Xsed -e \"$no_glob_subst\"`" + + for p in `eval $output_verbose_link_cmd`; do + case $p in + + -L* | -R* | -l*) + # Some compilers place space between "-{L,R}" and the path. + # Remove the space. + if test $p = "-L" \ + || test $p = "-R"; then + prev=$p + continue + else + prev= + fi + + if test "$pre_test_object_deps_done" = no; then + case $p in + -L* | -R*) + # Internal compiler library paths should come after those + # provided the user. The postdeps already come after the + # user supplied libs so there is no need to process them. + if test -z "$compiler_lib_search_path_CXX"; then + compiler_lib_search_path_CXX="${prev}${p}" + else + compiler_lib_search_path_CXX="${compiler_lib_search_path_CXX} ${prev}${p}" + fi + ;; + # The "-l" case would never come before the object being + # linked, so don't bother handling this case. + esac + else + if test -z "$postdeps_CXX"; then + postdeps_CXX="${prev}${p}" + else + postdeps_CXX="${postdeps_CXX} ${prev}${p}" + fi + fi + ;; + + *.$objext) + # This assumes that the test object file only shows up + # once in the compiler output. + if test "$p" = "conftest.$objext"; then + pre_test_object_deps_done=yes + continue + fi + + if test "$pre_test_object_deps_done" = no; then + if test -z "$predep_objects_CXX"; then + predep_objects_CXX="$p" + else + predep_objects_CXX="$predep_objects_CXX $p" + fi + else + if test -z "$postdep_objects_CXX"; then + postdep_objects_CXX="$p" + else + postdep_objects_CXX="$postdep_objects_CXX $p" + fi + fi + ;; + + *) ;; # Ignore the rest. + + esac + done + + # Clean up. + rm -f a.out a.exe +else + echo "libtool.m4: error: problem compiling CXX test program" +fi + +$rm -f confest.$objext + +case " $postdeps_CXX " in +*" -lc "*) archive_cmds_need_lc_CXX=no ;; +esac + +lt_prog_compiler_wl_CXX= +lt_prog_compiler_pic_CXX= +lt_prog_compiler_static_CXX= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + # C++ specific cases for pic, static, wl, etc. + if test "$GXX" = yes; then + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + fi + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_CXX='-m68020 -resident32 -malways-restore-a4' + ;; + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + mingw* | os2* | pw32*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_CXX='-DDLL_EXPORT' + ;; + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_CXX='-fno-common' + ;; + *djgpp*) + # DJGPP does not support shared libraries at all + lt_prog_compiler_pic_CXX= + ;; + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_CXX=-Kconform_pic + fi + ;; + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + ;; + *) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + esac + else + case $host_os in + aix4* | aix5*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_CXX='-Bstatic' + else + lt_prog_compiler_static_CXX='-bnso -bI:/lib/syscalls.exp' + fi + ;; + chorus*) + case $cc_basename in + cxch68) + # Green Hills C++ Compiler + # _LT_AC_TAGVAR(lt_prog_compiler_static, CXX)="--no_auto_instantiation -u __main -u __premain -u _abort -r $COOL_DIR/lib/libOrb.a $MVME_DIR/lib/CC/libC.a $MVME_DIR/lib/classix/libcx.s.a" + ;; + esac + ;; + dgux*) + case $cc_basename in + ec++) + lt_prog_compiler_pic_CXX='-KPIC' + ;; + ghcx) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + freebsd*) + # FreeBSD uses GNU C++ + ;; + hpux9* | hpux10* | hpux11*) + case $cc_basename in + CC) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + if test "$host_cpu" != ia64; then + lt_prog_compiler_pic_CXX='+Z' + fi + ;; + aCC) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX="${ac_cv_prog_cc_wl}-a ${ac_cv_prog_cc_wl}archive" + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_CXX='+Z' + ;; + esac + ;; + *) + ;; + esac + ;; + irix5* | irix6* | nonstopux*) + case $cc_basename in + CC) + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_static_CXX='-non_shared' + # CC pic flag -KPIC is the default. + ;; + *) + ;; + esac + ;; + linux*) + case $cc_basename in + KCC) + # KAI C++ Compiler + lt_prog_compiler_wl_CXX='--backend -Wl,' + lt_prog_compiler_pic_CXX='-fPIC' + ;; + icpc) + # Intel C++ + lt_prog_compiler_wl_CXX='-Wl,' + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-static' + ;; + cxx) + # Compaq C++ + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + lynxos*) + ;; + m88k*) + ;; + mvs*) + case $cc_basename in + cxx) + lt_prog_compiler_pic_CXX='-W c,exportall' + ;; + *) + ;; + esac + ;; + netbsd*) + ;; + osf3* | osf4* | osf5*) + case $cc_basename in + KCC) + lt_prog_compiler_wl_CXX='--backend -Wl,' + ;; + RCC) + # Rational C++ 2.4.1 + lt_prog_compiler_pic_CXX='-pic' + ;; + cxx) + # Digital/Compaq C++ + lt_prog_compiler_wl_CXX='-Wl,' + # Make sure the PIC flag is empty. It appears that all Alpha + # Linux and Compaq Tru64 Unix objects are PIC. + lt_prog_compiler_pic_CXX= + lt_prog_compiler_static_CXX='-non_shared' + ;; + *) + ;; + esac + ;; + psos*) + ;; + sco*) + case $cc_basename in + CC) + lt_prog_compiler_pic_CXX='-fPIC' + ;; + *) + ;; + esac + ;; + solaris*) + case $cc_basename in + CC) + # Sun C++ 4.2, 5.x and Centerline C++ + lt_prog_compiler_pic_CXX='-KPIC' + lt_prog_compiler_static_CXX='-Bstatic' + lt_prog_compiler_wl_CXX='-Qoption ld ' + ;; + gcx) + # Green Hills C++ Compiler + lt_prog_compiler_pic_CXX='-PIC' + ;; + *) + ;; + esac + ;; + sunos4*) + case $cc_basename in + CC) + # Sun C++ 4.x + lt_prog_compiler_pic_CXX='-pic' + lt_prog_compiler_static_CXX='-Bstatic' + ;; + lcc) + # Lucid + lt_prog_compiler_pic_CXX='-pic' + ;; + *) + ;; + esac + ;; + tandem*) + case $cc_basename in + NCC) + # NonStop-UX NCC 3.20 + lt_prog_compiler_pic_CXX='-KPIC' + ;; + *) + ;; + esac + ;; + unixware*) + ;; + vxworks*) + ;; + *) + lt_prog_compiler_can_build_shared_CXX=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_CXX" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_CXX"; then + echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_CXX works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_CXX=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_CXX -DPIC" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:10602: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:10606: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_prog_compiler_pic_works_CXX=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_CXX" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_CXX" >&6 + +if test x"$lt_prog_compiler_pic_works_CXX" = xyes; then + case $lt_prog_compiler_pic_CXX in + "" | " "*) ;; + *) lt_prog_compiler_pic_CXX=" $lt_prog_compiler_pic_CXX" ;; + esac +else + lt_prog_compiler_pic_CXX= + lt_prog_compiler_can_build_shared_CXX=no +fi + +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_CXX= + ;; + *) + lt_prog_compiler_pic_CXX="$lt_prog_compiler_pic_CXX -DPIC" + ;; +esac + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_CXX+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_CXX=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:10669: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:10673: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + lt_cv_prog_compiler_c_o_CXX=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_CXX" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_CXX" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_CXX" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + case $host_os in + aix4* | aix5*) + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_CXX='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_CXX='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + ;; + pw32*) + export_symbols_cmds_CXX="$ltdll_cmds" + ;; + cygwin* | mingw*) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + ;; + *) + export_symbols_cmds_CXX='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + ;; + esac + +echo "$as_me:$LINENO: result: $ld_shlibs_CXX" >&5 +echo "${ECHO_T}$ld_shlibs_CXX" >&6 +test "$ld_shlibs_CXX" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_CXX" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_CXX=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_CXX in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_CXX + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_CXX + allow_undefined_flag_CXX= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_CXX 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_CXX=no + else + archive_cmds_need_lc_CXX=yes + fi + allow_undefined_flag_CXX=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_CXX" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_CXX" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_CXX= +if test -n "$hardcode_libdir_flag_spec_CXX" || \ + test -n "$runpath_var CXX" || \ + test "X$hardcode_automatic_CXX"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_CXX" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, CXX)" != no && + test "$hardcode_minus_L_CXX" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_CXX=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_CXX=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_CXX=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_CXX" >&5 +echo "${ECHO_T}$hardcode_action_CXX" >&6 + +if test "$hardcode_action_CXX" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + ;; + *) + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + esac +fi + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.01* | freebsdelf3.01*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '#line 11240 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +char (*f) () = shl_load; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shl_load; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6 +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +char (*f) () = dlopen; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != dlopen; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6 +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_svld_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dld_link (); +int +main () +{ +dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_dld_link=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 11936 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6 + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 12034 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_CXX \ + CC_CXX \ + LD_CXX \ + lt_prog_compiler_wl_CXX \ + lt_prog_compiler_pic_CXX \ + lt_prog_compiler_static_CXX \ + lt_prog_compiler_no_builtin_flag_CXX \ + export_dynamic_flag_spec_CXX \ + thread_safe_flag_spec_CXX \ + whole_archive_flag_spec_CXX \ + enable_shared_with_static_runtimes_CXX \ + old_archive_cmds_CXX \ + old_archive_from_new_cmds_CXX \ + predep_objects_CXX \ + postdep_objects_CXX \ + predeps_CXX \ + postdeps_CXX \ + compiler_lib_search_path_CXX \ + archive_cmds_CXX \ + archive_expsym_cmds_CXX \ + postinstall_cmds_CXX \ + postuninstall_cmds_CXX \ + old_archive_from_expsyms_cmds_CXX \ + allow_undefined_flag_CXX \ + no_undefined_flag_CXX \ + export_symbols_cmds_CXX \ + hardcode_libdir_flag_spec_CXX \ + hardcode_libdir_flag_spec_ld_CXX \ + hardcode_libdir_separator_CXX \ + hardcode_automatic_CXX \ + module_cmds_CXX \ + module_expsym_cmds_CXX \ + lt_cv_prog_compiler_c_o_CXX \ + exclude_expsyms_CXX \ + include_expsyms_CXX; do + + case $var in + old_archive_cmds_CXX | \ + old_archive_from_new_cmds_CXX | \ + archive_cmds_CXX | \ + archive_expsym_cmds_CXX | \ + module_cmds_CXX | \ + module_expsym_cmds_CXX | \ + old_archive_from_expsyms_cmds_CXX | \ + export_symbols_cmds_CXX | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_CXX + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_CXX + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_compiler_CXX + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_CXX + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_CXX + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_CXX + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_CXX +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_CXX + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_CXX + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_CXX + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_CXX + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_CXX + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_CXX + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_CXX +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_CXX + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_CXX + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_CXX +archive_expsym_cmds=$lt_archive_expsym_cmds_CXX +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_CXX +module_expsym_cmds=$lt_module_expsym_cmds_CXX + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_CXX + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_CXX + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_CXX + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_CXX + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_CXX + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_CXX + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_CXX + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_CXX + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_CXX + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_CXX + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_CXX + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_CXX + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_CXX + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_CXX + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_CXX + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_CXX" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_CXX + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_CXX + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_CXX + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_CXX + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC=$lt_save_CC +LDCXX=$LD +LD=$lt_save_LD +GCC=$lt_save_GCC +with_gnu_ldcxx=$with_gnu_ld +with_gnu_ld=$lt_save_with_gnu_ld +lt_cv_path_LDCXX=$lt_cv_path_LD +lt_cv_path_LD=$lt_save_path_LD +lt_cv_prog_gnu_ldcxx=$lt_cv_prog_gnu_ld +lt_cv_prog_gnu_ld=$lt_save_with_gnu_ld + + else + tagname="" + fi + ;; + + F77) + if test -n "$F77" && test "X$F77" != "Xno"; then + +ac_ext=f +ac_compile='$F77 -c $FFLAGS conftest.$ac_ext >&5' +ac_link='$F77 -o conftest$ac_exeext $FFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_f77_compiler_gnu + + +archive_cmds_need_lc_F77=no +allow_undefined_flag_F77= +always_export_symbols_F77=no +archive_expsym_cmds_F77= +export_dynamic_flag_spec_F77= +hardcode_direct_F77=no +hardcode_libdir_flag_spec_F77= +hardcode_libdir_flag_spec_ld_F77= +hardcode_libdir_separator_F77= +hardcode_minus_L_F77=no +hardcode_automatic_F77=no +module_cmds_F77= +module_expsym_cmds_F77= +link_all_deplibs_F77=unknown +old_archive_cmds_F77=$old_archive_cmds +no_undefined_flag_F77= +whole_archive_flag_spec_F77= +enable_shared_with_static_runtimes_F77=no + +# Source file extension for f77 test sources. +ac_ext=f + +# Object file extension for compiled f77 test sources. +objext=o +objext_F77=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code=" subroutine t\n return\n end\n" + +# Code to be used in simple link tests +lt_simple_link_test_code=" program t\n end\n" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${F77-"f77"} +compiler=$CC +compiler_F77=$CC +cc_basename=`$echo X"$compiler" | $Xsed -e 's%^.*/%%'` + +echo "$as_me:$LINENO: checking if libtool supports shared libraries" >&5 +echo $ECHO_N "checking if libtool supports shared libraries... $ECHO_C" >&6 +echo "$as_me:$LINENO: result: $can_build_shared" >&5 +echo "${ECHO_T}$can_build_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build shared libraries" >&5 +echo $ECHO_N "checking whether to build shared libraries... $ECHO_C" >&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac +echo "$as_me:$LINENO: result: $enable_shared" >&5 +echo "${ECHO_T}$enable_shared" >&6 + +echo "$as_me:$LINENO: checking whether to build static libraries" >&5 +echo $ECHO_N "checking whether to build static libraries... $ECHO_C" >&6 +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes +echo "$as_me:$LINENO: result: $enable_static" >&5 +echo "${ECHO_T}$enable_static" >&6 + +test "$ld_shlibs_F77" = no && can_build_shared=no + +GCC_F77="$G77" +LD_F77="$LD" + +lt_prog_compiler_wl_F77= +lt_prog_compiler_pic_F77= +lt_prog_compiler_static_F77= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + if test "$GCC" = yes; then + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_static_F77='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_F77='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_F77='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_F77=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_F77=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_F77='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_F77='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_F77='-Bstatic' + else + lt_prog_compiler_static_F77='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_F77='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_F77='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_F77='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_F77='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_F77='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + linux*) + case $CC in + icc|ecc) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-static' + ;; + ccc) + lt_prog_compiler_wl_F77='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_F77='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_F77='-non_shared' + ;; + + sco3.2v5*) + lt_prog_compiler_pic_F77='-Kpic' + lt_prog_compiler_static_F77='-dn' + ;; + + solaris*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sunos4*) + lt_prog_compiler_wl_F77='-Qoption ld ' + lt_prog_compiler_pic_F77='-PIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + lt_prog_compiler_wl_F77='-Wl,' + lt_prog_compiler_pic_F77='-KPIC' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_F77='-Kconform_pic' + lt_prog_compiler_static_F77='-Bstatic' + fi + ;; + + uts4*) + lt_prog_compiler_pic_F77='-pic' + lt_prog_compiler_static_F77='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_F77=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_F77" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_F77"; then + echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_F77 works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_F77=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_F77" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12856: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:12860: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_prog_compiler_pic_works_F77=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_F77" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_F77" >&6 + +if test x"$lt_prog_compiler_pic_works_F77" = xyes; then + case $lt_prog_compiler_pic_F77 in + "" | " "*) ;; + *) lt_prog_compiler_pic_F77=" $lt_prog_compiler_pic_F77" ;; + esac +else + lt_prog_compiler_pic_F77= + lt_prog_compiler_can_build_shared_F77=no +fi + +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_F77= + ;; + *) + lt_prog_compiler_pic_F77="$lt_prog_compiler_pic_F77" + ;; +esac + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_F77+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_F77=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:12923: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:12927: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + lt_cv_prog_compiler_c_o_F77=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_F77" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_F77" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_F77" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag_F77= + enable_shared_with_static_runtimes_F77=no + archive_cmds_F77= + archive_expsym_cmds_F77= + old_archive_From_new_cmds_F77= + old_archive_from_expsyms_cmds_F77= + export_dynamic_flag_spec_F77= + whole_archive_flag_spec_F77= + thread_safe_flag_spec_F77= + hardcode_libdir_flag_spec_F77= + hardcode_libdir_flag_spec_ld_F77= + hardcode_libdir_separator_F77= + hardcode_direct_F77=no + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=unsupported + link_all_deplibs_F77=unknown + hardcode_automatic_F77=no + module_cmds_F77= + module_expsym_cmds_F77= + always_export_symbols_F77=no + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_F77= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_F77="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_F77=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_F77=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_F77=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_F77=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_F77='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, F77) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_F77='-L$libdir' + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=no + enable_shared_with_static_runtimes_F77=yes + export_symbols_cmds_F77='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_F77='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_F77=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + + sunos4*) + archive_cmds_F77='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds_F77="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_F77='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + archive_expsym_cmds_F77="$tmp_archive_cmds" + fi + else + ld_shlibs_F77=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_F77=no + fi + ;; + esac + + if test "$ld_shlibs_F77" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_F77='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_F77='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_F77="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_F77= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_F77=unsupported + always_export_symbols_F77=yes + archive_expsym_cmds_F77='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_F77=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_F77=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_F77='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_F77='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_F77='' + hardcode_direct_F77=yes + hardcode_libdir_separator_F77=':' + link_all_deplibs_F77=yes + + if test "$GCC" = yes; then + case $host_os in aix4.012|aix4.012.*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_F77=yes + else + # We have old collect2 + hardcode_direct_F77=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_F77=yes + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_libdir_separator_F77= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_F77=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_F77='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_F77="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_F77='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_F77="-z nodefs" + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF + program main + + end +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_F77='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_F77=' ${wl}-bernotok' + allow_undefined_flag_F77=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + always_export_symbols_F77=yes + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_F77=' ' + archive_cmds_need_lc_F77=yes + # This is similar to how AIX traditionally builds it's shared libraries. + archive_expsym_cmds_F77="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_F77='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_F77=no + ;; + + bsdi4*) + export_dynamic_flag_spec_F77=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_F77=' ' + allow_undefined_flag_F77=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_F77='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_F77='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_F77='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_F77=yes + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + archive_cmds_need_lc_F77=no + case "$host_os" in + rhapsody* | darwin1.[012]) + allow_undefined_flag_F77='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && allow_undefined_flag_F77='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_F77='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_F77='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_F77='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_F77='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + hardcode_direct_F77=no + hardcode_automatic_F77=yes + hardcode_shlibpath_var_F77=unsupported + whole_archive_flag_spec_F77='-all_load $convenience' + link_all_deplibs_F77=yes + fi + ;; + + dgux*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + freebsd1*) + ld_shlibs_F77=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds_F77='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_F77='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_F77='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds_F77='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_F77='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds_F77='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + archive_cmds_F77='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld_F77='+b $libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + ;; + ia64*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=no + hardcode_shlibpath_var_F77=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + *) + hardcode_libdir_flag_spec_F77='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_direct_F77=yes + export_dynamic_flag_spec_F77='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_F77=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_F77='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_F77='-rpath $libdir' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + link_all_deplibs_F77=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_F77='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + newsos6) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + hardcode_shlibpath_var_F77=no + ;; + + openbsd*) + hardcode_direct_F77=yes + hardcode_shlibpath_var_F77=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + export_dynamic_flag_spec_F77='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_F77='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-R$libdir' + ;; + *) + archive_cmds_F77='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_F77='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_minus_L_F77=yes + allow_undefined_flag_F77=unsupported + archive_cmds_F77='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_F77='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_F77=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_F77=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_F77='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_F77='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_F77=' -expect_unresolved \*' + archive_cmds_F77='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_F77='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_F77='-rpath $libdir' + fi + hardcode_libdir_separator_F77=: + ;; + + sco3.2v5*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag_F77=' -z text' + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_F77='-R$libdir' + hardcode_shlibpath_var_F77=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_F77='-z allextract$convenience -z defaultextract' ;; + esac + link_all_deplibs_F77=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_F77='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_direct_F77=yes + hardcode_minus_L_F77=yes + hardcode_shlibpath_var_F77=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_F77='$CC -r -o $output$reload_objs' + hardcode_direct_F77=no + ;; + motorola) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv4.3*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + export_dynamic_flag_spec_F77='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_F77=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_F77=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds_F77='$LD -G -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_F77=yes + hardcode_minus_L_F77=no + hardcode_shlibpath_var_F77=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + no_undefined_flag_F77='${wl}-z ${wl}text' + if test "$GCC" = yes; then + archive_cmds_F77='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_F77='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_F77=no + ;; + + sysv5*) + no_undefined_flag_F77=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds_F77='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_F77='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec_F77= + hardcode_shlibpath_var_F77=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds_F77='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_F77='-L$libdir' + hardcode_shlibpath_var_F77=no + ;; + + *) + ld_shlibs_F77=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs_F77" >&5 +echo "${ECHO_T}$ld_shlibs_F77" >&6 +test "$ld_shlibs_F77" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_F77" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_F77=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_F77 in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_F77 + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_F77 + allow_undefined_flag_F77= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_F77 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_F77=no + else + archive_cmds_need_lc_F77=yes + fi + allow_undefined_flag_F77=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_F77" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_F77" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_F77= +if test -n "$hardcode_libdir_flag_spec_F77" || \ + test -n "$runpath_var F77" || \ + test "X$hardcode_automatic_F77"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_F77" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, F77)" != no && + test "$hardcode_minus_L_F77" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_F77=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_F77=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_F77=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_F77" >&5 +echo "${ECHO_T}$hardcode_action_F77" >&6 + +if test "$hardcode_action_F77" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + ;; + *) + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + esac +fi + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.01* | freebsdelf3.01*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '#line 14266 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_F77 \ + CC_F77 \ + LD_F77 \ + lt_prog_compiler_wl_F77 \ + lt_prog_compiler_pic_F77 \ + lt_prog_compiler_static_F77 \ + lt_prog_compiler_no_builtin_flag_F77 \ + export_dynamic_flag_spec_F77 \ + thread_safe_flag_spec_F77 \ + whole_archive_flag_spec_F77 \ + enable_shared_with_static_runtimes_F77 \ + old_archive_cmds_F77 \ + old_archive_from_new_cmds_F77 \ + predep_objects_F77 \ + postdep_objects_F77 \ + predeps_F77 \ + postdeps_F77 \ + compiler_lib_search_path_F77 \ + archive_cmds_F77 \ + archive_expsym_cmds_F77 \ + postinstall_cmds_F77 \ + postuninstall_cmds_F77 \ + old_archive_from_expsyms_cmds_F77 \ + allow_undefined_flag_F77 \ + no_undefined_flag_F77 \ + export_symbols_cmds_F77 \ + hardcode_libdir_flag_spec_F77 \ + hardcode_libdir_flag_spec_ld_F77 \ + hardcode_libdir_separator_F77 \ + hardcode_automatic_F77 \ + module_cmds_F77 \ + module_expsym_cmds_F77 \ + lt_cv_prog_compiler_c_o_F77 \ + exclude_expsyms_F77 \ + include_expsyms_F77; do + + case $var in + old_archive_cmds_F77 | \ + old_archive_from_new_cmds_F77 | \ + archive_cmds_F77 | \ + archive_expsym_cmds_F77 | \ + module_cmds_F77 | \ + module_expsym_cmds_F77 | \ + old_archive_from_expsyms_cmds_F77 | \ + export_symbols_cmds_F77 | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_F77 + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_F77 + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_compiler_F77 + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_F77 + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_F77 + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_F77 + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_F77 +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_F77 + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_F77 + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_F77 + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_F77 + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_F77 + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_F77 + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_F77 +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_F77 + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_F77 + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_F77 +archive_expsym_cmds=$lt_archive_expsym_cmds_F77 +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_F77 +module_expsym_cmds=$lt_module_expsym_cmds_F77 + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_F77 + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_F77 + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_F77 + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_F77 + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_F77 + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_F77 + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_F77 + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_F77 + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_F77 + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_F77 + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_F77 + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_F77 + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_F77 + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_F77 + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_F77 + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_F77" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_F77 + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_F77 + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_F77 + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_F77 + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + GCJ) + if test -n "$GCJ" && test "X$GCJ" != "Xno"; then + + + +# Source file extension for Java test sources. +ac_ext=java + +# Object file extension for compiled Java test sources. +objext=o +objext_GCJ=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code="class foo {}\n" + +# Code to be used in simple link tests +lt_simple_link_test_code='public class conftest { public static void main(String argv) {}; }\n' + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${GCJ-"gcj"} +compiler=$CC +compiler_GCJ=$CC + +# GCJ did not exist at the time GCC didn't implicitly link libc in. +archive_cmds_need_lc_GCJ=no + + +lt_prog_compiler_no_builtin_flag_GCJ= + +if test "$GCC" = yes; then + lt_prog_compiler_no_builtin_flag_GCJ=' -fno-builtin' + + echo "$as_me:$LINENO: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 +echo $ECHO_N "checking if $compiler supports -fno-rtti -fno-exceptions... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_rtti_exceptions+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_rtti_exceptions=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="-fno-rtti -fno-exceptions" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:14912: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:14916: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_cv_prog_compiler_rtti_exceptions=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_rtti_exceptions" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_rtti_exceptions" >&6 + +if test x"$lt_cv_prog_compiler_rtti_exceptions" = xyes; then + lt_prog_compiler_no_builtin_flag_GCJ="$lt_prog_compiler_no_builtin_flag_GCJ -fno-rtti -fno-exceptions" +else + : +fi + +fi + +lt_prog_compiler_wl_GCJ= +lt_prog_compiler_pic_GCJ= +lt_prog_compiler_static_GCJ= + +echo "$as_me:$LINENO: checking for $compiler option to produce PIC" >&5 +echo $ECHO_N "checking for $compiler option to produce PIC... $ECHO_C" >&6 + + if test "$GCC" = yes; then + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_static_GCJ='-static' + + case $host_os in + aix*) + # All AIX code is PIC. + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + lt_prog_compiler_pic_GCJ='-m68020 -resident32 -malways-restore-a4' + ;; + + beos* | cygwin* | irix5* | irix6* | nonstopux* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + darwin* | rhapsody*) + # PIC is the default on this platform + # Common symbols not allowed in MH_DYLIB files + lt_prog_compiler_pic_GCJ='-fno-common' + ;; + + msdosdjgpp*) + # Just because we use GCC doesn't mean we suddenly get shared libraries + # on systems that don't support them. + lt_prog_compiler_can_build_shared_GCJ=no + enable_shared=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + lt_prog_compiler_pic_GCJ=-Kconform_pic + fi + ;; + + hpux*) + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + ;; + + *) + lt_prog_compiler_pic_GCJ='-fPIC' + ;; + esac + else + # PORTME Check for flag to pass linker flags through the system compiler. + case $host_os in + aix*) + lt_prog_compiler_wl_GCJ='-Wl,' + if test "$host_cpu" = ia64; then + # AIX 5 now supports IA64 processor + lt_prog_compiler_static_GCJ='-Bstatic' + else + lt_prog_compiler_static_GCJ='-bnso -bI:/lib/syscalls.exp' + fi + ;; + + mingw* | pw32* | os2*) + # This hack is so that the source file can tell whether it is being + # built for inclusion in a dll (and should export symbols for example). + lt_prog_compiler_pic_GCJ='-DDLL_EXPORT' + ;; + + hpux9* | hpux10* | hpux11*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC is the default for IA64 HP-UX and 64-bit HP-UX, but + # not for PA HP-UX. + case "$host_cpu" in + hppa*64*|ia64*) + # +Z the default + ;; + *) + lt_prog_compiler_pic_GCJ='+Z' + ;; + esac + # Is there a better lt_prog_compiler_static that works with the bundled CC? + lt_prog_compiler_static_GCJ='${wl}-a ${wl}archive' + ;; + + irix5* | irix6* | nonstopux*) + lt_prog_compiler_wl_GCJ='-Wl,' + # PIC (with -KPIC) is the default. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + newsos6) + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + linux*) + case $CC in + icc|ecc) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-static' + ;; + ccc) + lt_prog_compiler_wl_GCJ='-Wl,' + # All Alpha code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + esac + ;; + + osf3* | osf4* | osf5*) + lt_prog_compiler_wl_GCJ='-Wl,' + # All OSF/1 code is PIC. + lt_prog_compiler_static_GCJ='-non_shared' + ;; + + sco3.2v5*) + lt_prog_compiler_pic_GCJ='-Kpic' + lt_prog_compiler_static_GCJ='-dn' + ;; + + solaris*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sunos4*) + lt_prog_compiler_wl_GCJ='-Qoption ld ' + lt_prog_compiler_pic_GCJ='-PIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + lt_prog_compiler_wl_GCJ='-Wl,' + lt_prog_compiler_pic_GCJ='-KPIC' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + sysv4*MP*) + if test -d /usr/nec ;then + lt_prog_compiler_pic_GCJ='-Kconform_pic' + lt_prog_compiler_static_GCJ='-Bstatic' + fi + ;; + + uts4*) + lt_prog_compiler_pic_GCJ='-pic' + lt_prog_compiler_static_GCJ='-Bstatic' + ;; + + *) + lt_prog_compiler_can_build_shared_GCJ=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_GCJ" >&6 + +# +# Check to make sure the PIC flag actually works. +# +if test -n "$lt_prog_compiler_pic_GCJ"; then + echo "$as_me:$LINENO: checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works" >&5 +echo $ECHO_N "checking if $compiler PIC flag $lt_prog_compiler_pic_GCJ works... $ECHO_C" >&6 +if test "${lt_prog_compiler_pic_works_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_prog_compiler_pic_works_GCJ=no + ac_outfile=conftest.$ac_objext + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + lt_compiler_flag="$lt_prog_compiler_pic_GCJ" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + # The option is referenced via a variable to avoid confusing sed. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:15144: $lt_compile\"" >&5) + (eval "$lt_compile" 2>conftest.err) + ac_status=$? + cat conftest.err >&5 + echo "$as_me:15148: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s "$ac_outfile"; then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s conftest.err; then + lt_prog_compiler_pic_works_GCJ=yes + fi + fi + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_prog_compiler_pic_works_GCJ" >&5 +echo "${ECHO_T}$lt_prog_compiler_pic_works_GCJ" >&6 + +if test x"$lt_prog_compiler_pic_works_GCJ" = xyes; then + case $lt_prog_compiler_pic_GCJ in + "" | " "*) ;; + *) lt_prog_compiler_pic_GCJ=" $lt_prog_compiler_pic_GCJ" ;; + esac +else + lt_prog_compiler_pic_GCJ= + lt_prog_compiler_can_build_shared_GCJ=no +fi + +fi +case "$host_os" in + # For platforms which do not support PIC, -DPIC is meaningless: + *djgpp*) + lt_prog_compiler_pic_GCJ= + ;; + *) + lt_prog_compiler_pic_GCJ="$lt_prog_compiler_pic_GCJ" + ;; +esac + +echo "$as_me:$LINENO: checking if $compiler supports -c -o file.$ac_objext" >&5 +echo $ECHO_N "checking if $compiler supports -c -o file.$ac_objext... $ECHO_C" >&6 +if test "${lt_cv_prog_compiler_c_o_GCJ+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + lt_cv_prog_compiler_c_o_GCJ=no + $rm -r conftest 2>/dev/null + mkdir conftest + cd conftest + mkdir out + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + # According to Tom Tromey, Ian Lance Taylor reported there are C compilers + # that will create temporary files in the current directory regardless of + # the output directory. Thus, making CWD read-only will cause this test + # to fail, enabling locking or at least warning the user not to do parallel + # builds. + chmod -w . + + lt_compiler_flag="-o out/conftest2.$ac_objext" + # Insert the option either (1) after the last *FLAGS variable, or + # (2) before a word containing "conftest.", or (3) at the end. + # Note that $ac_compile itself does not contain backslashes and begins + # with a dollar sign (not a hyphen), so the echo should work correctly. + lt_compile=`echo "$ac_compile" | $SED \ + -e 's:.*FLAGS}? :&$lt_compiler_flag :; t' \ + -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ + -e 's:$: $lt_compiler_flag:'` + (eval echo "\"\$as_me:15211: $lt_compile\"" >&5) + (eval "$lt_compile" 2>out/conftest.err) + ac_status=$? + cat out/conftest.err >&5 + echo "$as_me:15215: \$? = $ac_status" >&5 + if (exit $ac_status) && test -s out/conftest2.$ac_objext + then + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test ! -s out/conftest.err; then + lt_cv_prog_compiler_c_o_GCJ=yes + fi + fi + chmod u+w . + $rm conftest* out/* + rmdir out + cd .. + rmdir conftest + $rm conftest* + +fi +echo "$as_me:$LINENO: result: $lt_cv_prog_compiler_c_o_GCJ" >&5 +echo "${ECHO_T}$lt_cv_prog_compiler_c_o_GCJ" >&6 + + +hard_links="nottested" +if test "$lt_cv_prog_compiler_c_o_GCJ" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo "$as_me:$LINENO: checking if we can lock with hard links" >&5 +echo $ECHO_N "checking if we can lock with hard links... $ECHO_C" >&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$as_me:$LINENO: result: $hard_links" >&5 +echo "${ECHO_T}$hard_links" >&6 + if test "$hard_links" = no; then + { echo "$as_me:$LINENO: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&5 +echo "$as_me: WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2;} + need_locks=warn + fi +else + need_locks=no +fi + +echo "$as_me:$LINENO: checking whether the $compiler linker ($LD) supports shared libraries" >&5 +echo $ECHO_N "checking whether the $compiler linker ($LD) supports shared libraries... $ECHO_C" >&6 + + runpath_var= + allow_undefined_flag_GCJ= + enable_shared_with_static_runtimes_GCJ=no + archive_cmds_GCJ= + archive_expsym_cmds_GCJ= + old_archive_From_new_cmds_GCJ= + old_archive_from_expsyms_cmds_GCJ= + export_dynamic_flag_spec_GCJ= + whole_archive_flag_spec_GCJ= + thread_safe_flag_spec_GCJ= + hardcode_libdir_flag_spec_GCJ= + hardcode_libdir_flag_spec_ld_GCJ= + hardcode_libdir_separator_GCJ= + hardcode_direct_GCJ=no + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=unsupported + link_all_deplibs_GCJ=unknown + hardcode_automatic_GCJ=no + module_cmds_GCJ= + module_expsym_cmds_GCJ= + always_export_symbols_GCJ=no + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED '\''s/.* //'\'' | sort | uniq > $export_symbols' + # include_expsyms should be a list of space-separated symbols to be *always* + # included in the symbol list + include_expsyms_GCJ= + # exclude_expsyms can be an extended regexp of symbols to exclude + # it will be wrapped by ` (' and `)$', so one must not match beginning or + # end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', + # as well as any symbol that contains `d'. + exclude_expsyms_GCJ="_GLOBAL_OFFSET_TABLE_" + # Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out + # platforms (ab)use it in PIC code, but their linkers get confused if + # the symbol is explicitly referenced. Since portable code cannot + # rely on this symbol name, it's probably fine to never include it in + # preloaded symbol tables. + extract_expsyms_cmds= + + case $host_os in + cygwin* | mingw* | pw32*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$GCC" != yes; then + with_gnu_ld=no + fi + ;; + openbsd*) + with_gnu_ld=no + ;; + esac + + ld_shlibs_GCJ=yes + if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case $host_os in + aix3* | aix4* | aix5*) + # On AIX/PPC, the GNU linker is very broken + if test "$host_cpu" != ia64; then + ld_shlibs_GCJ=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can't use + # them. + ld_shlibs_GCJ=no + ;; + + beos*) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag_GCJ=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds_GCJ='$CC -nostart $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + cygwin* | mingw* | pw32*) + # _LT_AC_TAGVAR(hardcode_libdir_flag_spec, GCJ) is actually meaningless, + # as there is no search path for DLLs. + hardcode_libdir_flag_spec_GCJ='-L$libdir' + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=no + enable_shared_with_static_runtimes_GCJ=yes + export_symbols_cmds_GCJ='$NM $libobjs $convenience | $global_symbol_pipe | $SED -e '\''/^[BCDGS] /s/.* \([^ ]*\)/\1 DATA/'\'' | $SED -e '\''/^[AITW] /s/.* //'\'' | sort | uniq > $export_symbols' + + if $LD --help 2>&1 | grep 'auto-import' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + # If the export-symbols file already is a .def file (1st line + # is EXPORTS), use it as is; otherwise, prepend... + archive_expsym_cmds_GCJ='if test "x`$SED 1q $export_symbols`" = xEXPORTS; then + cp $export_symbols $output_objdir/$soname.def; + else + echo EXPORTS > $output_objdir/$soname.def; + cat $export_symbols >> $output_objdir/$soname.def; + fi~ + $CC -shared $output_objdir/$soname.def $libobjs $deplibs $compiler_flags -o $output_objdir/$soname ${wl}--image-base=0x10000000 ${wl}--out-implib,$lib' + else + ld_shlibs=no + fi + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable $libobjs $deplibs $linker_flags -o $lib' + wlarc= + else + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | grep 'BFD 2\.8' > /dev/null; then + ld_shlibs_GCJ=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + + sunos4*) + archive_cmds_GCJ='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linker_flags' + wlarc= + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + linux*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + tmp_archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_cmds_GCJ="$tmp_archive_cmds" + supports_anon_versioning=no + case `$LD -v 2>/dev/null` in + *\ 01.* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 + *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... + *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... + *\ 2.11.*) ;; # other 2.11 versions + *) supports_anon_versioning=yes ;; + esac + if test $supports_anon_versioning = yes; then + archive_expsym_cmds_GCJ='$echo "{ global:" > $output_objdir/$libname.ver~ +cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ +$echo "local: *; };" >> $output_objdir/$libname.ver~ + $CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-version-script ${wl}$output_objdir/$libname.ver -o $lib' + else + archive_expsym_cmds_GCJ="$tmp_archive_cmds" + fi + else + ld_shlibs_GCJ=no + fi + ;; + + *) + if $LD --help 2>&1 | grep ': supported targets:.* elf' > /dev/null; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs_GCJ=no + fi + ;; + esac + + if test "$ld_shlibs_GCJ" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec_GCJ='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec_GCJ='${wl}--export-dynamic' + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | grep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec_GCJ="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec_GCJ= + fi + fi + else + # PORTME fill in a description of your system's linker (not GNU ld) + case $host_os in + aix3*) + allow_undefined_flag_GCJ=unsupported + always_export_symbols_GCJ=yes + archive_expsym_cmds_GCJ='$LD -o $output_objdir/$soname $libobjs $deplibs $linker_flags -bE:$export_symbols -T512 -H512 -bM:SRE~$AR $AR_FLAGS $lib $output_objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L_GCJ=yes + if test "$GCC" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct_GCJ=unsupported + fi + ;; + + aix4* | aix5*) + if test "$host_cpu" = ia64; then + # On IA64, the linker does run time linking by default, so we don't + # have to do anything special. + aix_use_runtimelinking=no + exp_sym_flag='-Bexport' + no_entry_flag="" + else + # If we're using GNU nm, then we don't want the "-C" option. + # -C means demangle to AIX nm, but means don't demangle with GNU nm + if $NM -V 2>&1 | grep 'GNU' > /dev/null; then + export_symbols_cmds_GCJ='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + else + export_symbols_cmds_GCJ='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$2 == "T") || (\$2 == "D") || (\$2 == "B")) && (substr(\$3,1,1) != ".")) { print \$3 } }'\'' | sort -u > $export_symbols' + fi + aix_use_runtimelinking=no + + # Test if we are trying to use run time linking or normal + # AIX style linking. If -brtl is somewhere in LDFLAGS, we + # need to do runtime linking. + case $host_os in aix4.[23]|aix4.[23].*|aix5*) + for ld_flag in $LDFLAGS; do + if (test $ld_flag = "-brtl" || test $ld_flag = "-Wl,-brtl"); then + aix_use_runtimelinking=yes + break + fi + done + esac + + exp_sym_flag='-bexport' + no_entry_flag='-bnoentry' + fi + + # When large executables or shared objects are built, AIX ld can + # have problems creating the table of contents. If linking a library + # or program results in "error TOC overflow" add -mminimal-toc to + # CXXFLAGS/CFLAGS for g++/gcc. In the cases where that is not + # enough to fix the problem, add -Wl,-bbigtoc to LDFLAGS. + + archive_cmds_GCJ='' + hardcode_direct_GCJ=yes + hardcode_libdir_separator_GCJ=':' + link_all_deplibs_GCJ=yes + + if test "$GCC" = yes; then + case $host_os in aix4.012|aix4.012.*) + # We only want to do this on AIX 4.2 and lower, the check + # below for broken collect2 doesn't work under 4.3+ + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct_GCJ=yes + else + # We have old collect2 + hardcode_direct_GCJ=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L_GCJ=yes + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_libdir_separator_GCJ= + fi + esac + shared_flag='-shared' + else + # not using gcc + if test "$host_cpu" = ia64; then + # VisualAge C++, Version 5.5 for AIX 5L for IA-64, Beta 3 Release + # chokes on -Wl,-G. The following line is correct: + shared_flag='-G' + else + if test "$aix_use_runtimelinking" = yes; then + shared_flag='${wl}-G' + else + shared_flag='${wl}-bM:SRE' + fi + fi + fi + + # It seems that -bexpall does not export symbols beginning with + # underscore (_), so it is better to generate a list of symbols to export. + always_export_symbols_GCJ=yes + if test "$aix_use_runtimelinking" = yes; then + # Warning - without using the other runtime loading flags (-brtl), + # -berok will link without error, but may produce a broken library. + allow_undefined_flag_GCJ='-berok' + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + archive_expsym_cmds_GCJ="\$CC"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then echo "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols $shared_flag" + else + if test "$host_cpu" = ia64; then + hardcode_libdir_flag_spec_GCJ='${wl}-R $libdir:/usr/lib:/lib' + allow_undefined_flag_GCJ="-z nodefs" + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}${allow_undefined_flag} '"\${wl}$no_entry_flag \${wl}$exp_sym_flag:\$export_symbols" + else + # Determine the default libpath from the value encoded in an empty executable. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + +aix_libpath=`dump -H conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'` +# Check for a 64-bit object if we didn't find anything. +if test -z "$aix_libpath"; then aix_libpath=`dump -HX64 conftest$ac_exeext 2>/dev/null | $SED -n -e '/Import File Strings/,/^$/ { /^0/ { s/^0 *\(.*\)$/\1/; p; } +}'`; fi +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi + + hardcode_libdir_flag_spec_GCJ='${wl}-blibpath:$libdir:'"$aix_libpath" + # Warning - without using the other run time loading flags, + # -berok will link without error, but may produce a broken library. + no_undefined_flag_GCJ=' ${wl}-bernotok' + allow_undefined_flag_GCJ=' ${wl}-berok' + # -bexpall does not export symbols beginning with underscore (_) + always_export_symbols_GCJ=yes + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec_GCJ=' ' + archive_cmds_need_lc_GCJ=yes + # This is similar to how AIX traditionally builds it's shared libraries. + archive_expsym_cmds_GCJ="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs $compiler_flags ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' + fi + fi + ;; + + amigaos*) + archive_cmds_GCJ='$rm $output_objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $output_objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $output_objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $output_objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $output_objdir/a2ixlibrary.data~$AR $AR_FLAGS $lib $libobjs~$RANLIB $lib~(cd $output_objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + # see comment about different semantics on the GNU ld section + ld_shlibs_GCJ=no + ;; + + bsdi4*) + export_dynamic_flag_spec_GCJ=-rdynamic + ;; + + cygwin* | mingw* | pw32*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec_GCJ=' ' + allow_undefined_flag_GCJ=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # Tell ltmain to make .dll files, not .so files. + shrext=".dll" + # FIXME: Setting linknames here is a bad hack. + archive_cmds_GCJ='$CC -o $lib $libobjs $compiler_flags `echo "$deplibs" | $SED -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_From_new_cmds_GCJ='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds_GCJ='lib /OUT:$oldlib$oldobjs$old_deplibs' + fix_srcfile_path='`cygpath -w "$srcfile"`' + enable_shared_with_static_runtimes_GCJ=yes + ;; + + darwin* | rhapsody*) + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + archive_cmds_need_lc_GCJ=no + case "$host_os" in + rhapsody* | darwin1.[012]) + allow_undefined_flag_GCJ='-undefined suppress' + ;; + *) # Darwin 1.3 on + test -z ${LD_TWOLEVEL_NAMESPACE} && allow_undefined_flag_GCJ='-flat_namespace -undefined suppress' + ;; + esac + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. Also zsh mangles + # `"' quotes if we put them in here... so don't! + lt_int_apple_cc_single_mod=no + output_verbose_link_cmd='echo' + if $CC -dumpspecs 2>&1 | grep 'single_module' >/dev/null ; then + lt_int_apple_cc_single_mod=yes + fi + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_cmds_GCJ='$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + else + archive_cmds_GCJ='$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring' + fi + module_cmds_GCJ='$CC -bundle ${wl}-bind_at_load $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags' + # Don't fix this by using the ld -exported_symbols_list flag, it doesn't exist in older darwin ld's + if test "X$lt_int_apple_cc_single_mod" = Xyes ; then + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -dynamiclib -single_module $allow_undefined_flag -o $lib $libobjs $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + else + archive_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -r ${wl}-bind_at_load -keep_private_externs -nostdlib -o ${lib}-master.o $libobjs~$CC -dynamiclib $allow_undefined_flag -o $lib ${lib}-master.o $deplibs $compiler_flags -install_name $rpath/$soname $verstring~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + fi + module_expsym_cmds_GCJ='sed -e "s,#.*,," -e "s,^[ ]*,," -e "s,^\(..*\),_&," < $export_symbols > $output_objdir/${libname}-symbols.expsym~$CC -bundle $allow_undefined_flag -o $lib $libobjs $deplibs$compiler_flags~nmedit -s $output_objdir/${libname}-symbols.expsym ${lib}' + hardcode_direct_GCJ=no + hardcode_automatic_GCJ=yes + hardcode_shlibpath_var_GCJ=unsupported + whole_archive_flag_spec_GCJ='-all_load $convenience' + link_all_deplibs_GCJ=yes + fi + ;; + + dgux*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + freebsd1*) + ld_shlibs_GCJ=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds_GCJ='$CC -shared -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + hpux9*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$rm $output_objdir/$soname~$CC -shared -fPIC ${wl}+b ${wl}$install_libdir -o $output_objdir/$soname $libobjs $deplibs $compiler_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + else + archive_cmds_GCJ='$rm $output_objdir/$soname~$LD -b +b $install_libdir -o $output_objdir/$soname $libobjs $deplibs $linker_flags~test $output_objdir/$soname = $lib || mv $output_objdir/$soname $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + ;; + + hpux10* | hpux11*) + if test "$GCC" = yes -a "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds_GCJ='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + ;; + *) + archive_cmds_GCJ='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + ;; + esac + else + case "$host_cpu" in + hppa*64*|ia64*) + archive_cmds_GCJ='$LD -b +h $soname -o $lib $libobjs $deplibs $linker_flags' + ;; + *) + archive_cmds_GCJ='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' + ;; + esac + fi + if test "$with_gnu_ld" = no; then + case "$host_cpu" in + hppa*64*) + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_flag_spec_ld_GCJ='+b $libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + ;; + ia64*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=no + hardcode_shlibpath_var_GCJ=no + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + *) + hardcode_libdir_flag_spec_GCJ='${wl}+b ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_direct_GCJ=yes + export_dynamic_flag_spec_GCJ='${wl}-E' + + # hardcode_minus_L: Not really in the search PATH, + # but as the default location of the library. + hardcode_minus_L_GCJ=yes + ;; + esac + fi + ;; + + irix5* | irix6* | nonstopux*) + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + archive_cmds_GCJ='$LD -shared $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_ld_GCJ='-rpath $libdir' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + link_all_deplibs_GCJ=yes + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' # a.out + else + archive_cmds_GCJ='$LD -shared -o $lib $libobjs $deplibs $linker_flags' # ELF + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + newsos6) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + hardcode_shlibpath_var_GCJ=no + ;; + + openbsd*) + hardcode_direct_GCJ=yes + hardcode_shlibpath_var_GCJ=no + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + export_dynamic_flag_spec_GCJ='${wl}-E' + else + case $host_os in + openbsd[01].* | openbsd2.[0-7] | openbsd2.[0-7].*) + archive_cmds_GCJ='$LD -Bshareable -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-R$libdir' + ;; + *) + archive_cmds_GCJ='$CC -shared $pic_flag -o $lib $libobjs $deplibs $compiler_flags' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath,$libdir' + ;; + esac + fi + ;; + + os2*) + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_minus_L_GCJ=yes + allow_undefined_flag_GCJ=unsupported + archive_cmds_GCJ='$echo "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$echo DATA >> $output_objdir/$libname.def~$echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~$echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + old_archive_From_new_cmds_GCJ='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' + ;; + + osf3*) + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator_GCJ=: + ;; + + osf4* | osf5*) # as osf3* with the addition of -msym flag + if test "$GCC" = yes; then + allow_undefined_flag_GCJ=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds_GCJ='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + hardcode_libdir_flag_spec_GCJ='${wl}-rpath ${wl}$libdir' + else + allow_undefined_flag_GCJ=' -expect_unresolved \*' + archive_cmds_GCJ='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linker_flags -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds_GCJ='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; echo "-hidden">> $lib.exp~ + $LD -shared${allow_undefined_flag} -input $lib.exp $linker_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib~$rm $lib.exp' + + # Both c and cxx compiler support -rpath directly + hardcode_libdir_flag_spec_GCJ='-rpath $libdir' + fi + hardcode_libdir_separator_GCJ=: + ;; + + sco3.2v5*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='${wl}-Bexport' + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag_GCJ=' -z text' + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $CC -shared ${wl}-M ${wl}$lib.exp ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags~$rm $lib.exp' + else + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + fi + hardcode_libdir_flag_spec_GCJ='-R$libdir' + hardcode_shlibpath_var_GCJ=no + case $host_os in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec_GCJ='-z allextract$convenience -z defaultextract' ;; + esac + link_all_deplibs_GCJ=yes + ;; + + sunos4*) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds_GCJ='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linker_flags' + fi + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=yes + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4) + case $host_vendor in + sni) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes # is this really true??? + ;; + siemens) + ## LD is ld it makes a PLAMLIB + ## CC just makes a GrossModule. + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + reload_cmds_GCJ='$CC -r -o $output$reload_objs' + hardcode_direct_GCJ=no + ;; + motorola) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=no #Motorola manual says yes, but my tests say they lie + ;; + esac + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv4.3*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + export_dynamic_flag_spec_GCJ='-Bexport' + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_shlibpath_var_GCJ=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs_GCJ=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds_GCJ='$LD -G -o $lib $libobjs $deplibs $linker_flags' + hardcode_direct_GCJ=yes + hardcode_minus_L_GCJ=no + hardcode_shlibpath_var_GCJ=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + sysv5OpenUNIX8* | sysv5UnixWare7* | sysv5uw[78]* | unixware7*) + no_undefined_flag_GCJ='${wl}-z ${wl}text' + if test "$GCC" = yes; then + archive_cmds_GCJ='$CC -shared ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + else + archive_cmds_GCJ='$CC -G ${wl}-h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var_GCJ=no + ;; + + sysv5*) + no_undefined_flag_GCJ=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds_GCJ='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linker_flags' + archive_expsym_cmds_GCJ='$echo "{ global:" > $lib.exp~cat $export_symbols | $SED -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linker_flags~$rm $lib.exp' + hardcode_libdir_flag_spec_GCJ= + hardcode_shlibpath_var_GCJ=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds_GCJ='$LD -G -h $soname -o $lib $libobjs $deplibs $linker_flags' + hardcode_libdir_flag_spec_GCJ='-L$libdir' + hardcode_shlibpath_var_GCJ=no + ;; + + *) + ld_shlibs_GCJ=no + ;; + esac + fi + +echo "$as_me:$LINENO: result: $ld_shlibs_GCJ" >&5 +echo "${ECHO_T}$ld_shlibs_GCJ" >&6 +test "$ld_shlibs_GCJ" = no && can_build_shared=no + +variables_saved_for_relink="PATH $shlibpath_var $runpath_var" +if test "$GCC" = yes; then + variables_saved_for_relink="$variables_saved_for_relink GCC_EXEC_PREFIX COMPILER_PATH LIBRARY_PATH" +fi + +# +# Do we need to explicitly link libc? +# +case "x$archive_cmds_need_lc_GCJ" in +x|xyes) + # Assume -lc should be added + archive_cmds_need_lc_GCJ=yes + + if test "$enable_shared" = yes && test "$GCC" = yes; then + case $archive_cmds_GCJ in + *'~'*) + # FIXME: we may have to deal with multi-command sequences. + ;; + '$CC '*) + # Test whether the compiler implicitly links with -lc since on some + # systems, -lgcc has to come before -lc. If gcc already passes -lc + # to ld, don't add -lc before -lgcc. + echo "$as_me:$LINENO: checking whether -lc should be explicitly linked in" >&5 +echo $ECHO_N "checking whether -lc should be explicitly linked in... $ECHO_C" >&6 + $rm conftest* + printf "$lt_simple_compile_test_code" > conftest.$ac_ext + + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl_GCJ + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag_GCJ + allow_undefined_flag_GCJ= + if { (eval echo "$as_me:$LINENO: \"$archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1\"") >&5 + (eval $archive_cmds_GCJ 2\>\&1 \| grep \" -lc \" \>/dev/null 2\>\&1) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } + then + archive_cmds_need_lc_GCJ=no + else + archive_cmds_need_lc_GCJ=yes + fi + allow_undefined_flag_GCJ=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $rm conftest* + echo "$as_me:$LINENO: result: $archive_cmds_need_lc_GCJ" >&5 +echo "${ECHO_T}$archive_cmds_need_lc_GCJ" >&6 + ;; + esac + fi + ;; +esac + +echo "$as_me:$LINENO: checking how to hardcode library paths into programs" >&5 +echo $ECHO_N "checking how to hardcode library paths into programs... $ECHO_C" >&6 +hardcode_action_GCJ= +if test -n "$hardcode_libdir_flag_spec_GCJ" || \ + test -n "$runpath_var GCJ" || \ + test "X$hardcode_automatic_GCJ"="Xyes" ; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct_GCJ" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$_LT_AC_TAGVAR(hardcode_shlibpath_var, GCJ)" != no && + test "$hardcode_minus_L_GCJ" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action_GCJ=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action_GCJ=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action_GCJ=unsupported +fi +echo "$as_me:$LINENO: result: $hardcode_action_GCJ" >&5 +echo "${ECHO_T}$hardcode_action_GCJ" >&6 + +if test "$hardcode_action_GCJ" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +striplib= +old_striplib= +echo "$as_me:$LINENO: checking whether stripping libraries is possible" >&5 +echo $ECHO_N "checking whether stripping libraries is possible... $ECHO_C" >&6 +if test -n "$STRIP" && $STRIP -V 2>&1 | grep "GNU strip" >/dev/null; then + test -z "$old_striplib" && old_striplib="$STRIP --strip-debug" + test -z "$striplib" && striplib="$STRIP --strip-unneeded" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 +else +# FIXME - insert some real tests, host_os isn't really good enough + case $host_os in + darwin*) + if test -n "$STRIP" ; then + striplib="$STRIP -x" + echo "$as_me:$LINENO: result: yes" >&5 +echo "${ECHO_T}yes" >&6 + else + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 +fi + ;; + *) + echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6 + ;; + esac +fi + +echo "$as_me:$LINENO: checking dynamic linker characteristics" >&5 +echo $ECHO_N "checking dynamic linker characteristics... $ECHO_C" >&6 +library_names_spec= +libname_spec='lib$name' +soname_spec= +shrext=".so" +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +if test "$GCC" = yes; then + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';' >/dev/null ; then + # if the path contains ";" then we assume it to be the separator + # otherwise default to the standard path separator (i.e. ":") - it is + # assumed that no part of a normal pathname contains ";" but that should + # okay in the real world where ";" in dirpaths is itself problematic. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi +else + sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +fi +need_lib_prefix=unknown +hardcode_into_libs=no + +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +need_version=unknown + +case $host_os in +aix3*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX 3 has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}${shared_ext}$major' + ;; + +aix4* | aix5*) + version_type=linux + need_lib_prefix=no + need_version=no + hardcode_into_libs=yes + if test "$host_cpu" = ia64; then + # AIX 5 supports IA64 + library_names_spec='${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext}$versuffix $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + else + # With GCC up to 2.95.x, collect2 would create an import file + # for dependence libraries. The import file would start with + # the line `#! .'. This would cause the generated library to + # depend on `.', always an invalid library. This was fixed in + # development snapshots of GCC prior to 3.0. + case $host_os in + aix4 | aix4.[01] | aix4.[01].*) + if { echo '#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 97)' + echo ' yes ' + echo '#endif'; } | ${CC} -E - | grep yes > /dev/null; then + : + else + can_build_shared=no + fi + ;; + esac + # AIX (on Power*) has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + if test "$aix_use_runtimelinking" = yes; then + # If using run time linking (on AIX 4.2 or later) use lib<name>.so + # instead of lib<name>.a to let people know that these are not + # typical AIX shared libraries. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + else + # We preserve .a as extension for shared libraries through AIX4.2 + # and later when we are not doing run time linking. + library_names_spec='${libname}${release}.a $libname.a' + soname_spec='${libname}${release}${shared_ext}$major' + fi + shlibpath_var=LIBPATH + fi + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}${shared_ext}' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw* | pw32*) + version_type=windows + shrext=".dll" + need_version=no + need_lib_prefix=no + + case $GCC,$host_os in + yes,cygwin* | yes,mingw* | yes,pw32*) + library_names_spec='$libname.dll.a' + # DLL is installed to $(libdir)/../bin by postinstall_cmds + postinstall_cmds='base_file=`basename \${file}`~ + dlpath=`$SHELL 2>&1 -c '\''. $dir/'\''\${base_file}'\''i;echo \$dlname'\''`~ + dldir=$destdir/`dirname \$dlpath`~ + test -d \$dldir || mkdir -p \$dldir~ + $install_prog $dir/$dlname \$dldir/$dlname' + postuninstall_cmds='dldll=`$SHELL 2>&1 -c '\''. $file; echo \$dlname'\''`~ + dlpath=$dir/\$dldll~ + $rm \$dlpath' + shlibpath_overrides_runpath=yes + + case $host_os in + cygwin*) + # Cygwin DLLs use 'cyg' prefix rather than 'lib' + soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec="/lib /lib/w32api /usr/lib /usr/local/lib" + ;; + mingw*) + # MinGW DLLs use traditional 'lib' prefix + soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' + sys_lib_search_path_spec=`$CC -print-search-dirs | grep "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` + if echo "$sys_lib_search_path_spec" | grep ';[c-zC-Z]:/' >/dev/null; then + # It is most probably a Windows format PATH printed by + # mingw gcc, but we are running on Cygwin. Gcc prints its search + # path with ; separators, and with drive letters. We can handle the + # drive letters (cygwin fileutils understands them), so leave them, + # especially as we might pass files found there to a mingw objdump, + # which wouldn't understand a cygwinified path. Ahh. + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` + else + sys_lib_search_path_spec=`echo "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` + fi + ;; + pw32*) + # pw32 DLLs use 'pw' prefix rather than 'lib' + library_names_spec='`echo ${libname} | sed -e 's/^lib/pw/'``echo ${release} | $SED -e 's/./-/g'`${versuffix}${shared_ext}' + ;; + esac + ;; + + *) + library_names_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext} $libname.lib' + ;; + esac + dynamic_linker='Win32 ld.exe' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + ;; + +darwin* | rhapsody*) + dynamic_linker="$host_os dyld" + version_type=darwin + need_lib_prefix=no + need_version=no + # FIXME: Relying on posixy $() will cause problems for + # cross-compilation, but unfortunately the echo tests do not + # yet detect zsh echo's removal of \ escapes. + library_names_spec='${libname}${release}${versuffix}$shared_ext ${libname}${release}${major}$shared_ext ${libname}$shared_ext' + soname_spec='${libname}${release}${major}$shared_ext' + shlibpath_overrides_runpath=yes + shlibpath_var=DYLD_LIBRARY_PATH + shrext='$(test .$module = .yes && echo .so || echo .dylib)' + # Apple's gcc prints 'gcc -print-search-dirs' doesn't operate the same. + if $CC -v 2>&1 | grep 'Apple' >/dev/null ; then + sys_lib_search_path_spec=`$CC -print-search-dirs | tr "\n" "$PATH_SEPARATOR" | sed -e 's/libraries:/@libraries:/' | tr "@" "\n" | grep "^libraries:" | sed -e "s/^libraries://" -e "s,=/,/,g" -e "s,$PATH_SEPARATOR, ,g" -e "s,.*,& /lib /usr/lib /usr/local/lib,g"` + fi + sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib' + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname$shared_ext' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case $version_type in + freebsd-elf*) + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext} $libname${shared_ext}' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + library_names_spec='${libname}${release}${shared_ext}$versuffix $libname${shared_ext}$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case $host_os in + freebsd2*) + shlibpath_overrides_runpath=yes + ;; + freebsd3.01* | freebsdelf3.01*) + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + hardcode_into_libs=yes + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + hardcode_into_libs=yes + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + version_type=sunos + need_lib_prefix=no + need_version=no + case "$host_cpu" in + ia64*) + shrext='.so' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.so" + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + if test "X$HPUX_IA64_MODE" = X32; then + sys_lib_search_path_spec="/usr/lib/hpux32 /usr/local/lib/hpux32 /usr/local/lib" + else + sys_lib_search_path_spec="/usr/lib/hpux64 /usr/local/lib/hpux64" + fi + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + hppa*64*) + shrext='.sl' + hardcode_into_libs=yes + dynamic_linker="$host_os dld.sl" + shlibpath_var=LD_LIBRARY_PATH # How should we handle SHLIB_PATH + shlibpath_overrides_runpath=yes # Unless +noenvvar is specified. + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + sys_lib_search_path_spec="/usr/lib/pa20_64 /usr/ccs/lib/pa20_64" + sys_lib_dlsearch_path_spec=$sys_lib_search_path_spec + ;; + *) + shrext='.sl' + dynamic_linker="$host_os dld.sl" + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + ;; + esac + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + ;; + +irix5* | irix6* | nonstopux*) + case $host_os in + nonstopux*) version_type=nonstopux ;; + *) + if test "$lt_cv_prog_gnu_ld" = yes; then + version_type=linux + else + version_type=irix + fi ;; + esac + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} $libname${shared_ext}' + case $host_os in + irix5* | nonstopux*) + libsuff= shlibsuff= + ;; + *) + case $LD in # libtool.m4 will add one of these switches to LD + *-32|*"-32 "|*-melf32bsmip|*"-melf32bsmip ") + libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 "|*-melf32bmipn32|*"-melf32bmipn32 ") + libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 "|*-melf64bmip|*"-melf64bmip ") + libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + hardcode_into_libs=yes + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux*oldld* | linux*aout* | linux*coff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + # This implies no fast_install, which is unacceptable. + # Some rework will be needed to allow for fast_install + # before this can be enabled. + hardcode_into_libs=yes + + # We used to test for /lib/ld.so.1 and disable shared libraries on + # powerpc, because MkLinux only supported shared libraries with the + # GNU dynamic linker. Since this was broken with cross compilers, + # most powerpc-linux boxes support dynamic linking these days and + # people can always --disable-shared, the test was removed, and we + # assume the GNU/Linux dynamic linker is in use. + dynamic_linker='GNU/Linux ld.so' + + # Find out which ABI we are using (multilib Linux x86_64 hack). + libsuff= + case "$host_cpu" in + x86_64*|s390x*) + echo '#line 16576 "configure"' > conftest.$ac_ext + if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; then + case `/usr/bin/file conftest.$ac_objext` in + *64-bit*) + libsuff=64 + ;; + esac + fi + rm -rf conftest* + ;; + *) + ;; + esac + sys_lib_dlsearch_path_spec="/lib${libsuff} /usr/lib${libsuff}" + sys_lib_search_path_spec="/lib${libsuff} /usr/lib${libsuff} /usr/local/lib${libsuff}" + ;; + +netbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major ${libname}${release}${shared_ext} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + ;; + +newsos6) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +nto-qnx) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + ;; + +openbsd*) + version_type=sunos + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + if test -z "`echo __ELF__ | $CC -E - | grep __ELF__`" || test "$host_os-$host_cpu" = "openbsd2.8-powerpc"; then + case $host_os in + openbsd2.[89] | openbsd2.[89].*) + shlibpath_overrides_runpath=no + ;; + *) + shlibpath_overrides_runpath=yes + ;; + esac + else + shlibpath_overrides_runpath=yes + fi + ;; + +os2*) + libname_spec='$name' + shrext=".dll" + need_lib_prefix=no + library_names_spec='$libname${shared_ext} $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}${shared_ext}$major' + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + hardcode_into_libs=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${shared_ext}$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + case $host_vendor in + sni) + shlibpath_overrides_runpath=no + need_lib_prefix=no + export_dynamic_flag_spec='${wl}-Blargedynsym' + runpath_var=LD_RUN_PATH + ;; + siemens) + need_lib_prefix=no + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + ;; + esac + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname${shared_ext}.$versuffix $libname${shared_ext}.$major $libname${shared_ext}' + soname_spec='$libname${shared_ext}.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}$major $libname${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$as_me:$LINENO: result: $dynamic_linker" >&5 +echo "${ECHO_T}$dynamic_linker" >&6 +test "$dynamic_linker" = no && can_build_shared=no + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else + lt_cv_dlopen=no + lt_cv_dlopen_libs= + + case $host_os in + beos*) + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + + mingw* | pw32*) + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + + cygwin*) + lt_cv_dlopen="dlopen" + lt_cv_dlopen_libs= + ;; + + darwin*) + # if libdl is installed we need to link against it + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + + lt_cv_dlopen="dyld" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + +fi + + ;; + + *) + echo "$as_me:$LINENO: checking for shl_load" >&5 +echo $ECHO_N "checking for shl_load... $ECHO_C" >&6 +if test "${ac_cv_func_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +char (*f) () = shl_load; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != shl_load; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_shl_load" >&5 +echo "${ECHO_T}$ac_cv_func_shl_load" >&6 +if test $ac_cv_func_shl_load = yes; then + lt_cv_dlopen="shl_load" +else + echo "$as_me:$LINENO: checking for shl_load in -ldld" >&5 +echo $ECHO_N "checking for shl_load in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_shl_load+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char shl_load (); +int +main () +{ +shl_load (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_shl_load=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_shl_load=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_shl_load" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_shl_load" >&6 +if test $ac_cv_lib_dld_shl_load = yes; then + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-dld" +else + echo "$as_me:$LINENO: checking for dlopen" >&5 +echo $ECHO_N "checking for dlopen... $ECHO_C" >&6 +if test "${ac_cv_func_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +char (*f) () = dlopen; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != dlopen; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_dlopen" >&5 +echo "${ECHO_T}$ac_cv_func_dlopen" >&6 +if test $ac_cv_func_dlopen = yes; then + lt_cv_dlopen="dlopen" +else + echo "$as_me:$LINENO: checking for dlopen in -ldl" >&5 +echo $ECHO_N "checking for dlopen in -ldl... $ECHO_C" >&6 +if test "${ac_cv_lib_dl_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldl $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dl_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dl_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dl_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_dl_dlopen" >&6 +if test $ac_cv_lib_dl_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$as_me:$LINENO: checking for dlopen in -lsvld" >&5 +echo $ECHO_N "checking for dlopen in -lsvld... $ECHO_C" >&6 +if test "${ac_cv_lib_svld_dlopen+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lsvld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dlopen (); +int +main () +{ +dlopen (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_svld_dlopen=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_svld_dlopen=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_svld_dlopen" >&5 +echo "${ECHO_T}$ac_cv_lib_svld_dlopen" >&6 +if test $ac_cv_lib_svld_dlopen = yes; then + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-lsvld" +else + echo "$as_me:$LINENO: checking for dld_link in -ldld" >&5 +echo $ECHO_N "checking for dld_link in -ldld... $ECHO_C" >&6 +if test "${ac_cv_lib_dld_dld_link+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-ldld $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char dld_link (); +int +main () +{ +dld_link (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_dld_dld_link=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_dld_dld_link=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_dld_dld_link" >&5 +echo "${ECHO_T}$ac_cv_lib_dld_dld_link" >&6 +if test $ac_cv_lib_dld_dld_link = yes; then + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-dld" +fi + + +fi + + +fi + + +fi + + +fi + + +fi + + ;; + esac + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + else + enable_dlopen=no + fi + + case $lt_cv_dlopen in + dlopen) + save_CPPFLAGS="$CPPFLAGS" + test "x$ac_cv_header_dlfcn_h" = xyes && CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + + save_LDFLAGS="$LDFLAGS" + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + + save_LIBS="$LIBS" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo "$as_me:$LINENO: checking whether a program can dlopen itself" >&5 +echo $ECHO_N "checking whether a program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 17272 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self" >&6 + + if test "x$lt_cv_dlopen_self" = xyes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo "$as_me:$LINENO: checking whether a statically linked program can dlopen itself" >&5 +echo $ECHO_N "checking whether a statically linked program can dlopen itself... $ECHO_C" >&6 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + if test "$cross_compiling" = yes; then : + lt_cv_dlopen_self_static=cross +else + lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 + lt_status=$lt_dlunknown + cat > conftest.$ac_ext <<EOF +#line 17370 "configure" +#include "confdefs.h" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LT_DLGLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LT_DLGLOBAL DL_GLOBAL +# else +# define LT_DLGLOBAL 0 +# endif +#endif + +/* We may have to define LT_DLLAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LT_DLLAZY_OR_NOW +# ifdef RTLD_LAZY +# define LT_DLLAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LT_DLLAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LT_DLLAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LT_DLLAZY_OR_NOW DL_NOW +# else +# define LT_DLLAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +#ifdef __cplusplus +extern "C" void exit (int); +#endif + +void fnord() { int i=42;} +int main () +{ + void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); + int status = $lt_dlunknown; + + if (self) + { + if (dlsym (self,"fnord")) status = $lt_dlno_uscore; + else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + /* dlclose (self); */ + } + + exit (status); +} +EOF + if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && test -s conftest${ac_exeext} 2>/dev/null; then + (./conftest; exit; ) 2>/dev/null + lt_status=$? + case x$lt_status in + x$lt_dlno_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_dlneed_uscore) lt_cv_dlopen_self_static=yes ;; + x$lt_unknown|x*) lt_cv_dlopen_self_static=no ;; + esac + else : + # compilation failed + lt_cv_dlopen_self_static=no + fi +fi +rm -fr conftest* + + +fi +echo "$as_me:$LINENO: result: $lt_cv_dlopen_self_static" >&5 +echo "${ECHO_T}$lt_cv_dlopen_self_static" >&6 + fi + + CPPFLAGS="$save_CPPFLAGS" + LDFLAGS="$save_LDFLAGS" + LIBS="$save_LIBS" + ;; + esac + + case $lt_cv_dlopen_self in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case $lt_cv_dlopen_self_static in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_GCJ \ + CC_GCJ \ + LD_GCJ \ + lt_prog_compiler_wl_GCJ \ + lt_prog_compiler_pic_GCJ \ + lt_prog_compiler_static_GCJ \ + lt_prog_compiler_no_builtin_flag_GCJ \ + export_dynamic_flag_spec_GCJ \ + thread_safe_flag_spec_GCJ \ + whole_archive_flag_spec_GCJ \ + enable_shared_with_static_runtimes_GCJ \ + old_archive_cmds_GCJ \ + old_archive_from_new_cmds_GCJ \ + predep_objects_GCJ \ + postdep_objects_GCJ \ + predeps_GCJ \ + postdeps_GCJ \ + compiler_lib_search_path_GCJ \ + archive_cmds_GCJ \ + archive_expsym_cmds_GCJ \ + postinstall_cmds_GCJ \ + postuninstall_cmds_GCJ \ + old_archive_from_expsyms_cmds_GCJ \ + allow_undefined_flag_GCJ \ + no_undefined_flag_GCJ \ + export_symbols_cmds_GCJ \ + hardcode_libdir_flag_spec_GCJ \ + hardcode_libdir_flag_spec_ld_GCJ \ + hardcode_libdir_separator_GCJ \ + hardcode_automatic_GCJ \ + module_cmds_GCJ \ + module_expsym_cmds_GCJ \ + lt_cv_prog_compiler_c_o_GCJ \ + exclude_expsyms_GCJ \ + include_expsyms_GCJ; do + + case $var in + old_archive_cmds_GCJ | \ + old_archive_from_new_cmds_GCJ | \ + archive_cmds_GCJ | \ + archive_expsym_cmds_GCJ | \ + module_cmds_GCJ | \ + module_expsym_cmds_GCJ | \ + old_archive_from_expsyms_cmds_GCJ | \ + export_symbols_cmds_GCJ | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_GCJ + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_GCJ + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_compiler_GCJ + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_GCJ + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_GCJ + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_GCJ + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_GCJ +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_GCJ + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_GCJ + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_GCJ + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_GCJ + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_GCJ + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_GCJ + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_GCJ +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_GCJ + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_GCJ + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_GCJ +archive_expsym_cmds=$lt_archive_expsym_cmds_GCJ +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_GCJ +module_expsym_cmds=$lt_module_expsym_cmds_GCJ + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_GCJ + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_GCJ + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_GCJ + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_GCJ + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_GCJ + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_GCJ + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_GCJ + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_GCJ + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_GCJ + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_GCJ + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_GCJ + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_GCJ + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_GCJ + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_GCJ + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_GCJ + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_GCJ" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_GCJ + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_GCJ + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_GCJ + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_GCJ + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + else + tagname="" + fi + ;; + + RC) + + + +# Source file extension for RC test sources. +ac_ext=rc + +# Object file extension for compiled RC test sources. +objext=o +objext_RC=$objext + +# Code to be used in simple compile tests +lt_simple_compile_test_code='sample MENU { MENUITEM "&Soup", 100, CHECKED }\n' + +# Code to be used in simple link tests +lt_simple_link_test_code="$lt_simple_compile_test_code" + +# ltmain only uses $CC for tagged configurations so make sure $CC is set. + +# If no C compiler was specified, use CC. +LTCC=${LTCC-"$CC"} + +# Allow CC to be a program name with arguments. +compiler=$CC + + +# Allow CC to be a program name with arguments. +lt_save_CC="$CC" +CC=${RC-"windres"} +compiler=$CC +compiler_RC=$CC +lt_cv_prog_compiler_c_o_RC=yes + +# The else clause should only fire when bootstrapping the +# libtool distribution, otherwise you forgot to ship ltmain.sh +# with your package, and you will get complaints that there are +# no rules to generate ltmain.sh. +if test -f "$ltmain"; then + # See if we are running on zsh, and set the options which allow our commands through + # without removal of \ escapes. + if test -n "${ZSH_VERSION+set}" ; then + setopt NO_GLOB_SUBST + fi + # Now quote all the things that may contain metacharacters while being + # careful not to overquote the AC_SUBSTed values. We take copies of the + # variables and quote the copies for generation of the libtool script. + for var in echo old_CC old_CFLAGS AR AR_FLAGS EGREP RANLIB LN_S LTCC NM SED SHELL \ + libname_spec library_names_spec soname_spec extract_expsyms_cmds \ + old_striplib striplib file_magic_cmd finish_cmds finish_eval \ + deplibs_check_method reload_flag reload_cmds need_locks \ + lt_cv_sys_global_symbol_pipe lt_cv_sys_global_symbol_to_cdecl \ + lt_cv_sys_global_symbol_to_c_name_address \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + old_postinstall_cmds old_postuninstall_cmds \ + compiler_RC \ + CC_RC \ + LD_RC \ + lt_prog_compiler_wl_RC \ + lt_prog_compiler_pic_RC \ + lt_prog_compiler_static_RC \ + lt_prog_compiler_no_builtin_flag_RC \ + export_dynamic_flag_spec_RC \ + thread_safe_flag_spec_RC \ + whole_archive_flag_spec_RC \ + enable_shared_with_static_runtimes_RC \ + old_archive_cmds_RC \ + old_archive_from_new_cmds_RC \ + predep_objects_RC \ + postdep_objects_RC \ + predeps_RC \ + postdeps_RC \ + compiler_lib_search_path_RC \ + archive_cmds_RC \ + archive_expsym_cmds_RC \ + postinstall_cmds_RC \ + postuninstall_cmds_RC \ + old_archive_from_expsyms_cmds_RC \ + allow_undefined_flag_RC \ + no_undefined_flag_RC \ + export_symbols_cmds_RC \ + hardcode_libdir_flag_spec_RC \ + hardcode_libdir_flag_spec_ld_RC \ + hardcode_libdir_separator_RC \ + hardcode_automatic_RC \ + module_cmds_RC \ + module_expsym_cmds_RC \ + lt_cv_prog_compiler_c_o_RC \ + exclude_expsyms_RC \ + include_expsyms_RC; do + + case $var in + old_archive_cmds_RC | \ + old_archive_from_new_cmds_RC | \ + archive_cmds_RC | \ + archive_expsym_cmds_RC | \ + module_cmds_RC | \ + module_expsym_cmds_RC | \ + old_archive_from_expsyms_cmds_RC | \ + export_symbols_cmds_RC | \ + extract_expsyms_cmds | reload_cmds | finish_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "lt_$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case $lt_echo in + *'\$0 --fallback-echo"') + lt_echo=`$echo "X$lt_echo" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + +cfgfile="$ofile" + + cat <<__EOF__ >> "$cfgfile" +# ### BEGIN LIBTOOL TAG CONFIG: $tagname + +# Libtool was configured on host `(hostname || uname -n) 2>/dev/null | sed 1q`: + +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to add -lc for building shared libraries. +build_libtool_need_lc=$archive_cmds_need_lc_RC + +# Whether or not to disallow shared libs when runtime libs are static +allow_libtool_libs_with_static_runtimes=$enable_shared_with_static_runtimes_RC + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$lt_echo + +# The archiver. +AR=$lt_AR +AR_FLAGS=$lt_AR_FLAGS + +# A C compiler. +LTCC=$lt_LTCC + +# A language-specific compiler. +CC=$lt_compiler_RC + +# Is the compiler the GNU C compiler? +with_gcc=$GCC_RC + +# An ERE matcher. +EGREP=$lt_EGREP + +# The linker used to build libraries. +LD=$lt_LD_RC + +# Whether we need hard or soft links. +LN_S=$lt_LN_S + +# A BSD-compatible nm program. +NM=$lt_NM + +# A symbol stripping program +STRIP=$STRIP + +# Used to examine libraries when file_magic_cmd begins "file" +MAGIC_CMD=$MAGIC_CMD + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + +# How to pass a linker flag through the compiler. +wl=$lt_lt_prog_compiler_wl_RC + +# Object file suffix (normally "o"). +objext="$ac_objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Shared library suffix (normally ".so"). +shrext='$shrext' + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$lt_lt_prog_compiler_pic_RC +pic_mode=$pic_mode + +# What is the maximum length of a command? +max_cmd_len=$lt_cv_sys_max_cmd_len + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$lt_lt_cv_prog_compiler_c_o_RC + +# Must we lock files when doing compilation ? +need_locks=$lt_need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen_support=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$lt_lt_prog_compiler_static_RC + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$lt_lt_prog_compiler_no_builtin_flag_RC + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$lt_export_dynamic_flag_spec_RC + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$lt_whole_archive_flag_spec_RC + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$lt_thread_safe_flag_spec_RC + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$lt_libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$lt_library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$lt_soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$lt_RANLIB +old_archive_cmds=$lt_old_archive_cmds_RC +old_postinstall_cmds=$lt_old_postinstall_cmds +old_postuninstall_cmds=$lt_old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$lt_old_archive_from_new_cmds_RC + +# Create a temporary old-style archive to link instead of a shared archive. +old_archive_from_expsyms_cmds=$lt_old_archive_from_expsyms_cmds_RC + +# Commands used to build and install a shared archive. +archive_cmds=$lt_archive_cmds_RC +archive_expsym_cmds=$lt_archive_expsym_cmds_RC +postinstall_cmds=$lt_postinstall_cmds +postuninstall_cmds=$lt_postuninstall_cmds + +# Commands used to build a loadable module (assumed same as above if empty) +module_cmds=$lt_module_cmds_RC +module_expsym_cmds=$lt_module_expsym_cmds_RC + +# Commands to strip libraries. +old_striplib=$lt_old_striplib +striplib=$lt_striplib + +# Dependencies to place before the objects being linked to create a +# shared library. +predep_objects=$lt_predep_objects_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdep_objects=$lt_postdep_objects_RC + +# Dependencies to place before the objects being linked to create a +# shared library. +predeps=$lt_predeps_RC + +# Dependencies to place after the objects being linked to create a +# shared library. +postdeps=$lt_postdeps_RC + +# The library search path used internally by the compiler when linking +# a shared library. +compiler_lib_search_path=$lt_compiler_lib_search_path_RC + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$lt_deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$lt_file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$lt_allow_undefined_flag_RC + +# Flag that forces no undefined symbols. +no_undefined_flag=$lt_no_undefined_flag_RC + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$lt_finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$lt_finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$lt_lt_cv_sys_global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$lt_lt_cv_sys_global_symbol_to_cdecl + +# Transform the output of nm in a C name address pair +global_symbol_to_c_name_address=$lt_lt_cv_sys_global_symbol_to_c_name_address + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action_RC + +# Whether we should hardcode library paths into libraries. +hardcode_into_libs=$hardcode_into_libs + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$lt_hardcode_libdir_flag_spec_RC + +# If ld is used when linking, flag to hardcode \$libdir into +# a binary during linking. This must work even if \$libdir does +# not exist. +hardcode_libdir_flag_spec_ld=$lt_hardcode_libdir_flag_spec_ld_RC + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$lt_hardcode_libdir_separator_RC + +# Set to yes if using DIR/libNAME${shared_ext} during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct_RC + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L_RC + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var_RC + +# Set to yes if building a shared library automatically hardcodes DIR into the library +# and all subsequent libraries and executables linked against it. +hardcode_automatic=$hardcode_automatic_RC + +# Variables whose values should be saved in libtool wrapper scripts and +# restored at relink time. +variables_saved_for_relink="$variables_saved_for_relink" + +# Whether libtool must link a program against all its dependency libraries. +link_all_deplibs=$link_all_deplibs_RC + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$lt_sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$lt_sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path_RC" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols_RC + +# The commands to list exported symbols. +export_symbols_cmds=$lt_export_symbols_cmds_RC + +# The commands to extract the exported symbol list from a shared archive. +extract_expsyms_cmds=$lt_extract_expsyms_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$lt_exclude_expsyms_RC + +# Symbols that must always be exported. +include_expsyms=$lt_include_expsyms_RC + +# ### END LIBTOOL TAG CONFIG: $tagname + +__EOF__ + + +else + # If there is no Makefile yet, we rely on a make rule to execute + # `config.status --recheck' to rerun these tests and create the + # libtool script then. + test -f Makefile && make "$ltmain" +fi + + +ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + +CC="$lt_save_CC" + + ;; + + *) + { { echo "$as_me:$LINENO: error: Unsupported tag name: $tagname" >&5 +echo "$as_me: error: Unsupported tag name: $tagname" >&2;} + { (exit 1); exit 1; }; } + ;; + esac + + # Append the new tag name to the list of available tags. + if test -n "$tagname" ; then + available_tags="$available_tags $tagname" + fi + fi + done + IFS="$lt_save_ifs" + + # Now substitute the updated list of available tags. + if eval "sed -e 's/^available_tags=.*\$/available_tags=\"$available_tags\"/' \"$ofile\" > \"${ofile}T\""; then + mv "${ofile}T" "$ofile" + chmod +x "$ofile" + else + rm -f "${ofile}T" + { { echo "$as_me:$LINENO: error: unable to update list of available tagged configurations." >&5 +echo "$as_me: error: unable to update list of available tagged configurations." >&2;} + { (exit 1); exit 1; }; } + fi +fi + + + +# This can be used to rebuild libtool when needed +LIBTOOL_DEPS="$ac_aux_dir/ltmain.sh" + +# Always use our own libtool. +LIBTOOL='$(SHELL) $(top_builddir)/libtool' + +# Prevent multiple expansion + + + + + + + + + + + + + + + + + + + + + +# Check whether --enable-64-bit or --disable-64-bit was given. +if test "${enable_64_bit+set}" = set; then + enableval="$enable_64_bit" + case "${enableval}" in + yes) want64=true ;; + no) want64=false ;; + *) { { echo "$as_me:$LINENO: error: bad value ${enableval} for 64-bit option" >&5 +echo "$as_me: error: bad value ${enableval} for 64-bit option" >&2;} + { (exit 1); exit 1; }; } ;; +esac +else + want64=true +fi; +if test "${ac_cv_header_libelf_h+set}" = set; then + echo "$as_me:$LINENO: checking for libelf.h" >&5 +echo $ECHO_N "checking for libelf.h... $ECHO_C" >&6 +if test "${ac_cv_header_libelf_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_libelf_h" >&5 +echo "${ECHO_T}$ac_cv_header_libelf_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking libelf.h usability" >&5 +echo $ECHO_N "checking libelf.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <libelf.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking libelf.h presence" >&5 +echo $ECHO_N "checking libelf.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <libelf.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: libelf.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: libelf.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: libelf.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libelf.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: libelf.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: libelf.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: libelf.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: libelf.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: libelf.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: libelf.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for libelf.h" >&5 +echo $ECHO_N "checking for libelf.h... $ECHO_C" >&6 +if test "${ac_cv_header_libelf_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_libelf_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_libelf_h" >&5 +echo "${ECHO_T}$ac_cv_header_libelf_h" >&6 + +fi +if test $ac_cv_header_libelf_h = yes; then + : +else + + if test -f /usr/include/elfutils/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/include/elfutils" + elif test -f /usr/local/include/elfutils/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/local/include/elfutils" + elif test -f /usr/include/libelf/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/include/libelf" + elif test -f /usr/local/include/libelf/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/local/include/libelf" + else + { { echo "$as_me:$LINENO: error: libelf.h not found" >&5 +echo "$as_me: error: libelf.h not found" >&2;} + { (exit 1); exit 1; }; } + fi +fi + + +LIBGELF="" +if test "$want64"x = falsex; then + GELFINCLUDE='-I$(top_srcdir)/gelfx32' +else + GELFINCLUDE='-I$(top_srcdir)/gelfx' + if test "${ac_cv_header_gelf_h+set}" = set; then + echo "$as_me:$LINENO: checking for gelf.h" >&5 +echo $ECHO_N "checking for gelf.h... $ECHO_C" >&6 +if test "${ac_cv_header_gelf_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: $ac_cv_header_gelf_h" >&5 +echo "${ECHO_T}$ac_cv_header_gelf_h" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking gelf.h usability" >&5 +echo $ECHO_N "checking gelf.h usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <gelf.h> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking gelf.h presence" >&5 +echo $ECHO_N "checking gelf.h presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <gelf.h> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: gelf.h: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: gelf.h: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: gelf.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: gelf.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: gelf.h: present but cannot be compiled" >&5 +echo "$as_me: WARNING: gelf.h: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: gelf.h: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: gelf.h: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: gelf.h: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: gelf.h: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for gelf.h" >&5 +echo $ECHO_N "checking for gelf.h... $ECHO_C" >&6 +if test "${ac_cv_header_gelf_h+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_header_gelf_h=$ac_header_preproc +fi +echo "$as_me:$LINENO: result: $ac_cv_header_gelf_h" >&5 +echo "${ECHO_T}$ac_cv_header_gelf_h" >&6 + +fi +if test $ac_cv_header_gelf_h = yes; then + : +else + + GELFINCLUDE="$GELFINCLUDE "'-I$(top_srcdir)/gelf' + LIBGELF='../gelf/libgelf.la' + +fi + + +fi + +echo "$as_me:$LINENO: checking for elf_begin in -lelf" >&5 +echo $ECHO_N "checking for elf_begin in -lelf... $ECHO_C" >&6 +if test "${ac_cv_lib_elf_elf_begin+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lelf $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char elf_begin (); +int +main () +{ +elf_begin (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_elf_elf_begin=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_elf_elf_begin=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_elf_elf_begin" >&5 +echo "${ECHO_T}$ac_cv_lib_elf_elf_begin" >&6 +if test $ac_cv_lib_elf_elf_begin = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBELF 1 +_ACEOF + + LIBS="-lelf $LIBS" + +fi + + + + +echo "$as_me:$LINENO: checking for gelf_getvernaux" >&5 +echo $ECHO_N "checking for gelf_getvernaux... $ECHO_C" >&6 +if test "${ac_cv_func_gelf_getvernaux+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char gelf_getvernaux (); below. + Prefer <limits.h> to <assert.h> if __STDC__ is defined, since + <limits.h> exists even on freestanding compilers. */ +#ifdef __STDC__ +# include <limits.h> +#else +# include <assert.h> +#endif +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +{ +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char gelf_getvernaux (); +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_gelf_getvernaux) || defined (__stub___gelf_getvernaux) +choke me +#else +char (*f) () = gelf_getvernaux; +#endif +#ifdef __cplusplus +} +#endif + +int +main () +{ +return f != gelf_getvernaux; + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_func_gelf_getvernaux=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_func_gelf_getvernaux=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +fi +echo "$as_me:$LINENO: result: $ac_cv_func_gelf_getvernaux" >&5 +echo "${ECHO_T}$ac_cv_func_gelf_getvernaux" >&6 +if test $ac_cv_func_gelf_getvernaux = yes; then + newbu=true +else + newbu=false +fi + + +echo "$as_me:$LINENO: checking whether FTW_ACTIONRETVAL is supported" >&5 +echo $ECHO_N "checking whether FTW_ACTIONRETVAL is supported... $ECHO_C" >&6 +if test "${ac_cv_ftw_actionretval+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + + #ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 + #endif + #include <ftw.h> + #ifdef FTW_ACTIONRETVAL + FTW supports ACTIONRETVAL + #endif + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "FTW supports ACTIONRETVAL" >/dev/null 2>&1; then + ac_cv_ftw_actionretval=yes +else + ac_cv_ftw_actionretval=no +fi +rm -f conftest* + +fi +echo "$as_me:$LINENO: result: $ac_cv_ftw_actionretval" >&5 +echo "${ECHO_T}$ac_cv_ftw_actionretval" >&6 +if test "x$ac_cv_ftw_actionretval" = xyes; then + +cat >>confdefs.h <<\_ACEOF +#define HAVE_FTW_ACTIONRETVAL 1 +_ACEOF + +fi + + +echo "$as_me:$LINENO: checking for is_selinux_enabled in -lselinux" >&5 +echo $ECHO_N "checking for is_selinux_enabled in -lselinux... $ECHO_C" >&6 +if test "${ac_cv_lib_selinux_is_selinux_enabled+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lselinux $LIBS" +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +/* Override any gcc2 internal prototype to avoid an error. */ +#ifdef __cplusplus +extern "C" +#endif +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +char is_selinux_enabled (); +int +main () +{ +is_selinux_enabled (); + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_lib_selinux_is_selinux_enabled=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_cv_lib_selinux_is_selinux_enabled=no +fi +rm -f conftest.$ac_objext conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +echo "$as_me:$LINENO: result: $ac_cv_lib_selinux_is_selinux_enabled" >&5 +echo "${ECHO_T}$ac_cv_lib_selinux_is_selinux_enabled" >&6 +if test $ac_cv_lib_selinux_is_selinux_enabled = yes; then + cat >>confdefs.h <<_ACEOF +#define HAVE_LIBSELINUX 1 +_ACEOF + + LIBS="-lselinux $LIBS" + +fi + + +for ac_header in selinux/selinux.h +do +as_ac_Header=`echo "ac_cv_header_$ac_header" | $as_tr_sh` +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 +else + # Is the header compilable? +echo "$as_me:$LINENO: checking $ac_header usability" >&5 +echo $ECHO_N "checking $ac_header usability... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +$ac_includes_default +#include <$ac_header> +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_header_compiler=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +ac_header_compiler=no +fi +rm -f conftest.$ac_objext conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_compiler" >&5 +echo "${ECHO_T}$ac_header_compiler" >&6 + +# Is the header present? +echo "$as_me:$LINENO: checking $ac_header presence" >&5 +echo $ECHO_N "checking $ac_header presence... $ECHO_C" >&6 +cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <$ac_header> +_ACEOF +if { (eval echo "$as_me:$LINENO: \"$ac_cpp conftest.$ac_ext\"") >&5 + (eval $ac_cpp conftest.$ac_ext) 2>conftest.er1 + ac_status=$? + grep -v '^ *+' conftest.er1 >conftest.err + rm -f conftest.er1 + cat conftest.err >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } >/dev/null; then + if test -s conftest.err; then + ac_cpp_err=$ac_c_preproc_warn_flag + else + ac_cpp_err= + fi +else + ac_cpp_err=yes +fi +if test -z "$ac_cpp_err"; then + ac_header_preproc=yes +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + + ac_header_preproc=no +fi +rm -f conftest.err conftest.$ac_ext +echo "$as_me:$LINENO: result: $ac_header_preproc" >&5 +echo "${ECHO_T}$ac_header_preproc" >&6 + +# So? What about this header? +case $ac_header_compiler:$ac_header_preproc in + yes:no ) + { echo "$as_me:$LINENO: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&5 +echo "$as_me: WARNING: $ac_header: accepted by the compiler, rejected by the preprocessor!" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; + no:yes ) + { echo "$as_me:$LINENO: WARNING: $ac_header: present but cannot be compiled" >&5 +echo "$as_me: WARNING: $ac_header: present but cannot be compiled" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: check for missing prerequisite headers?" >&5 +echo "$as_me: WARNING: $ac_header: check for missing prerequisite headers?" >&2;} + { echo "$as_me:$LINENO: WARNING: $ac_header: proceeding with the preprocessor's result" >&5 +echo "$as_me: WARNING: $ac_header: proceeding with the preprocessor's result" >&2;} + ( + cat <<\_ASBOX +## ------------------------------------ ## +## Report this to bug-autoconf@gnu.org. ## +## ------------------------------------ ## +_ASBOX + ) | + sed "s/^/$as_me: WARNING: /" >&2 + ;; +esac +echo "$as_me:$LINENO: checking for $ac_header" >&5 +echo $ECHO_N "checking for $ac_header... $ECHO_C" >&6 +if eval "test \"\${$as_ac_Header+set}\" = set"; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + eval "$as_ac_Header=$ac_header_preproc" +fi +echo "$as_me:$LINENO: result: `eval echo '${'$as_ac_Header'}'`" >&5 +echo "${ECHO_T}`eval echo '${'$as_ac_Header'}'`" >&6 + +fi +if test `eval echo '${'$as_ac_Header'}'` = yes; then + cat >>confdefs.h <<_ACEOF +#define `echo "HAVE_$ac_header" | $as_tr_cpp` 1 +_ACEOF + +fi + +done + + +if test x"$newbu" = xtrue; then + # Don't use LFS for libelf-0.x + # Check whether --enable-largefile or --disable-largefile was given. +if test "${enable_largefile+set}" = set; then + enableval="$enable_largefile" + +fi; +if test "$enable_largefile" != no; then + + echo "$as_me:$LINENO: checking for special C compiler options needed for large files" >&5 +echo $ECHO_N "checking for special C compiler options needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_largefile_CC+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + ac_cv_sys_largefile_CC=no + if test "$GCC" != yes; then + ac_save_CC=$CC + while :; do + # IRIX 6.2 and later do not support large files by default, + # so use the C compiler's -n32 option if that helps. + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext + CC="$CC -n32" + rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_largefile_CC=' -n32'; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext + break + done + CC=$ac_save_CC + rm -f conftest.$ac_ext + fi +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_largefile_CC" >&5 +echo "${ECHO_T}$ac_cv_sys_largefile_CC" >&6 + if test "$ac_cv_sys_largefile_CC" != no; then + CC=$CC$ac_cv_sys_largefile_CC + fi + + echo "$as_me:$LINENO: checking for _FILE_OFFSET_BITS value needed for large files" >&5 +echo $ECHO_N "checking for _FILE_OFFSET_BITS value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_file_offset_bits+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_file_offset_bits=no + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _FILE_OFFSET_BITS 64 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_file_offset_bits=64; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_file_offset_bits" >&5 +echo "${ECHO_T}$ac_cv_sys_file_offset_bits" >&6 +if test "$ac_cv_sys_file_offset_bits" != no; then + +cat >>confdefs.h <<_ACEOF +#define _FILE_OFFSET_BITS $ac_cv_sys_file_offset_bits +_ACEOF + +fi +rm -f conftest* + echo "$as_me:$LINENO: checking for _LARGE_FILES value needed for large files" >&5 +echo $ECHO_N "checking for _LARGE_FILES value needed for large files... $ECHO_C" >&6 +if test "${ac_cv_sys_large_files+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + while :; do + ac_cv_sys_large_files=no + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ +#define _LARGE_FILES 1 +#include <sys/types.h> + /* Check that off_t can represent 2**63 - 1 correctly. + We can't simply define LARGE_OFF_T to be 9223372036854775807, + since some C++ compilers masquerading as C compilers + incorrectly reject 9223372036854775807. */ +#define LARGE_OFF_T (((off_t) 1 << 62) - 1 + ((off_t) 1 << 62)) + int off_t_is_large[(LARGE_OFF_T % 2147483629 == 721 + && LARGE_OFF_T % 2147483647 == 1) + ? 1 : -1]; +int +main () +{ + + ; + return 0; +} +_ACEOF +rm -f conftest.$ac_objext +if { (eval echo "$as_me:$LINENO: \"$ac_compile\"") >&5 + (eval $ac_compile) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && + { ac_try='test -s conftest.$ac_objext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + ac_cv_sys_large_files=1; break +else + echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +fi +rm -f conftest.$ac_objext conftest.$ac_ext + break +done +fi +echo "$as_me:$LINENO: result: $ac_cv_sys_large_files" >&5 +echo "${ECHO_T}$ac_cv_sys_large_files" >&6 +if test "$ac_cv_sys_large_files" != no; then + +cat >>confdefs.h <<_ACEOF +#define _LARGE_FILES $ac_cv_sys_large_files +_ACEOF + +fi +rm -f conftest* +fi + +fi + +if test "$cross_compiling" = yes; then + { echo "$as_me:$LINENO: WARNING: Could not test whether libelf properly converts Elf64_Sxword quantities. +If you are using libelf-0.7.0 and your libelf is buggy, please use +patches/libelf-0.7.0.patch." >&5 +echo "$as_me: WARNING: Could not test whether libelf properly converts Elf64_Sxword quantities. +If you are using libelf-0.7.0 and your libelf is buggy, please use +patches/libelf-0.7.0.patch." >&2;} +else + cat >conftest.$ac_ext <<_ACEOF +#line $LINENO "configure" +/* confdefs.h. */ +_ACEOF +cat confdefs.h >>conftest.$ac_ext +cat >>conftest.$ac_ext <<_ACEOF +/* end confdefs.h. */ + +#include <errno.h> +#include <fcntl.h> +#include <elf.h> +#include <libelf.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static unsigned char sparc64_elf[] = { +0x7f,0x45,0x4c,0x46,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,0x05, +0x00,0x00,0x07,0xff,0xf0,0x00,0x00,0x00,0x00,0x2e,0x73,0x79,0x6d,0x74,0x61,0x62, +0x00,0x2e,0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x73,0x68,0x73,0x74,0x72,0x74, +0x61,0x62,0x00,0x2e,0x74,0x65,0x78,0x74,0x00,0x2e,0x64,0x61,0x74,0x61,0x00,0x2e, +0x62,0x73,0x73,0x00,0x66,0x6f,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x04, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00 }; + +int main (void) +{ + Elf *elf; + int fd; + Elf64_Ehdr *ehdr; + Elf64_Addr val; + Elf_Scn *scn; + + fd = open ("conflibelftest", O_RDWR | O_CREAT | O_EXCL, 0600); + if (fd == -1) exit (1); + unlink ("conflibelftest"); + if (write (fd, sparc64_elf, sizeof(sparc64_elf)) != sizeof(sparc64_elf)) + exit (1); + if (lseek (fd, 0, SEEK_SET) != 0) exit (1); + elf_version (EV_CURRENT); + elf = elf_begin (fd, ELF_C_RDWR, NULL); if (elf == NULL) exit (2); + if ((ehdr = elf64_getehdr (elf)) == NULL) exit (3); + scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + char *name = NULL; + Elf64_Shdr *shdr; + Elf_Data *src, *dst; + + if ((shdr = elf64_getshdr (scn)) + && (name = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name)) + && !strcmp (name, "foo")) + { + src = elf_rawdata (scn, NULL); + if (shdr->sh_size != 8 || src->d_off || src->d_size != 8) exit (4); + if (src == NULL || elf_rawdata (scn, src) != NULL) exit (5); + if ((dst = elf_newdata (scn)) == NULL) exit (6); + dst->d_buf = &val; + dst->d_size = 8; + dst->d_off = 0; + dst->d_type = ELF_T_SXWORD; + src->d_type = ELF_T_SXWORD; + if (elf64_xlatetom (dst, src, ELFDATA2MSB) == NULL) exit (7); + if (val != 0x7fff0000000) + exit (42); + elf_end (elf); + exit (0); + } + } + exit (8); +} + +_ACEOF +rm -f conftest$ac_exeext +if { (eval echo "$as_me:$LINENO: \"$ac_link\"") >&5 + (eval $ac_link) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); } && { ac_try='./conftest$ac_exeext' + { (eval echo "$as_me:$LINENO: \"$ac_try\"") >&5 + (eval $ac_try) 2>&5 + ac_status=$? + echo "$as_me:$LINENO: \$? = $ac_status" >&5 + (exit $ac_status); }; }; then + : +else + echo "$as_me: program exited with status $ac_status" >&5 +echo "$as_me: failed program was:" >&5 +sed 's/^/| /' conftest.$ac_ext >&5 + +( exit $ac_status ) +{ { echo "$as_me:$LINENO: error: libelf does not properly convert Elf64_Sxword quantities. +If you are using libelf-0.7.0, please use patches/libelf-0.7.0.patch." >&5 +echo "$as_me: error: libelf does not properly convert Elf64_Sxword quantities. +If you are using libelf-0.7.0, please use patches/libelf-0.7.0.patch." >&2;} + { (exit 1); exit 1; }; } +fi +rm -f core core.* *.core gmon.out bb.out conftest$ac_exeext conftest.$ac_objext conftest.$ac_ext +fi + + + ac_config_files="$ac_config_files Makefile src/Makefile gelfx/Makefile gelfx32/Makefile gelf/Makefile m4/Makefile patches/Makefile doc/Makefile testsuite/Makefile" +cat >confcache <<\_ACEOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs, see configure's option --config-cache. +# It is not useful on other systems. If it contains results you don't +# want to keep, you may remove or edit it. +# +# config.status only pays attention to the cache file if you give it +# the --recheck option to rerun configure. +# +# `ac_cv_env_foo' variables (set or unset) will be overridden when +# loading this file, other *unset* `ac_cv_foo' will be assigned the +# following values. + +_ACEOF + +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +{ + (set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote + # substitution turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + "s/'/'\\\\''/g; + s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n \ + "s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1=\\2/p" + ;; + esac; +} | + sed ' + t clear + : clear + s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/ + t end + /^ac_cv_env/!s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/ + : end' >>confcache +if diff $cache_file confcache >/dev/null 2>&1; then :; else + if test -w $cache_file; then + test "x$cache_file" != "x/dev/null" && echo "updating cache $cache_file" + cat confcache >$cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +test "x$prefix" = xNONE && prefix=$ac_default_prefix +# Let make expand exec_prefix. +test "x$exec_prefix" = xNONE && exec_prefix='${prefix}' + +# VPATH may cause trouble with some makes, so we remove $(srcdir), +# ${srcdir} and @srcdir@ from VPATH if srcdir is ".", strip leading and +# trailing colons and then remove the whole line if VPATH becomes empty +# (actually we leave an empty line to preserve line numbers). +if test "x$srcdir" = x.; then + ac_vpsub='/^[ ]*VPATH[ ]*=/{ +s/:*\$(srcdir):*/:/; +s/:*\${srcdir}:*/:/; +s/:*@srcdir@:*/:/; +s/^\([^=]*=[ ]*\):*/\1/; +s/:*$//; +s/^[^=]*=[ ]*$//; +}' +fi + +DEFS=-DHAVE_CONFIG_H + +ac_libobjs= +ac_ltlibobjs= +for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue + # 1. Remove the extension, and $U if already installed. + ac_i=`echo "$ac_i" | + sed 's/\$U\././;s/\.o$//;s/\.obj$//'` + # 2. Add them. + ac_libobjs="$ac_libobjs $ac_i\$U.$ac_objext" + ac_ltlibobjs="$ac_ltlibobjs $ac_i"'$U.lo' +done +LIBOBJS=$ac_libobjs + +LTLIBOBJS=$ac_ltlibobjs + + +if test -z "${AMDEP_TRUE}" && test -z "${AMDEP_FALSE}"; then + { { echo "$as_me:$LINENO: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&5 +echo "$as_me: error: conditional \"AMDEP\" was never defined. +Usually this means the macro was only invoked conditionally." >&2;} + { (exit 1); exit 1; }; } +fi + +: ${CONFIG_STATUS=./config.status} +ac_clean_files_save=$ac_clean_files +ac_clean_files="$ac_clean_files $CONFIG_STATUS" +{ echo "$as_me:$LINENO: creating $CONFIG_STATUS" >&5 +echo "$as_me: creating $CONFIG_STATUS" >&6;} +cat >$CONFIG_STATUS <<_ACEOF +#! $SHELL +# Generated by $as_me. +# Run this file to recreate the current configuration. +# Compiler output produced by configure, useful for debugging +# configure, is in config.log if it exists. + +debug=false +ac_cs_recheck=false +ac_cs_silent=false +SHELL=\${CONFIG_SHELL-$SHELL} +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +## --------------------- ## +## M4sh Initialization. ## +## --------------------- ## + +# Be Bourne compatible +if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then + emulate sh + NULLCMD=: + # Zsh 3.x and 4.x performs word splitting on ${1+"$@"}, which + # is contrary to our usage. Disable this feature. + alias -g '${1+"$@"}'='"$@"' +elif test -n "${BASH_VERSION+set}" && (set -o posix) >/dev/null 2>&1; then + set -o posix +fi + +# Support unset when possible. +if (FOO=FOO; unset FOO) >/dev/null 2>&1; then + as_unset=unset +else + as_unset=false +fi + + +# Work around bugs in pre-3.0 UWIN ksh. +$as_unset ENV MAIL MAILPATH +PS1='$ ' +PS2='> ' +PS4='+ ' + +# NLS nuisances. +for as_var in \ + LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION \ + LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER \ + LC_TELEPHONE LC_TIME +do + if (set +x; test -n "`(eval $as_var=C; export $as_var) 2>&1`"); then + eval $as_var=C; export $as_var + else + $as_unset $as_var + fi +done + +# Required to use basename. +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +if (basename /) >/dev/null 2>&1 && test "X`basename / 2>&1`" = "X/"; then + as_basename=basename +else + as_basename=false +fi + + +# Name of the executable. +as_me=`$as_basename "$0" || +$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \ + X"$0" : 'X\(//\)$' \| \ + X"$0" : 'X\(/\)$' \| \ + . : '\(.\)' 2>/dev/null || +echo X/"$0" | + sed '/^.*\/\([^/][^/]*\)\/*$/{ s//\1/; q; } + /^X\/\(\/\/\)$/{ s//\1/; q; } + /^X\/\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + + +# PATH needs CR, and LINENO needs CR and PATH. +# Avoid depending upon Character Ranges. +as_cr_letters='abcdefghijklmnopqrstuvwxyz' +as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ' +as_cr_Letters=$as_cr_letters$as_cr_LETTERS +as_cr_digits='0123456789' +as_cr_alnum=$as_cr_Letters$as_cr_digits + +# The user is always right. +if test "${PATH_SEPARATOR+set}" != set; then + echo "#! /bin/sh" >conf$$.sh + echo "exit 0" >>conf$$.sh + chmod +x conf$$.sh + if (PATH="/nonexistent;."; conf$$.sh) >/dev/null 2>&1; then + PATH_SEPARATOR=';' + else + PATH_SEPARATOR=: + fi + rm -f conf$$.sh +fi + + + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" || { + # Find who we are. Look in the path if we contain no path at all + # relative or not. + case $0 in + *[\\/]* ) as_myself=$0 ;; + *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break +done + + ;; + esac + # We did not find ourselves, most probably we were run as `sh COMMAND' + # in which case we are not to be found in the path. + if test "x$as_myself" = x; then + as_myself=$0 + fi + if test ! -f "$as_myself"; then + { { echo "$as_me:$LINENO: error: cannot find myself; rerun with an absolute path" >&5 +echo "$as_me: error: cannot find myself; rerun with an absolute path" >&2;} + { (exit 1); exit 1; }; } + fi + case $CONFIG_SHELL in + '') + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for as_base in sh bash ksh sh5; do + case $as_dir in + /*) + if ("$as_dir/$as_base" -c ' + as_lineno_1=$LINENO + as_lineno_2=$LINENO + as_lineno_3=`(expr $as_lineno_1 + 1) 2>/dev/null` + test "x$as_lineno_1" != "x$as_lineno_2" && + test "x$as_lineno_3" = "x$as_lineno_2" ') 2>/dev/null; then + $as_unset BASH_ENV || test "${BASH_ENV+set}" != set || { BASH_ENV=; export BASH_ENV; } + $as_unset ENV || test "${ENV+set}" != set || { ENV=; export ENV; } + CONFIG_SHELL=$as_dir/$as_base + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" ${1+"$@"} + fi;; + esac + done +done +;; + esac + + # Create $as_me.lineno as a copy of $as_myself, but with $LINENO + # uniformly replaced by the line number. The first 'sed' inserts a + # line-number line before each line; the second 'sed' does the real + # work. The second script uses 'N' to pair each line-number line + # with the numbered line, and appends trailing '-' during + # substitution so that $LINENO is not a special case at line end. + # (Raja R Harinath suggested sed '=', and Paul Eggert wrote the + # second 'sed' script. Blame Lee E. McMahon for sed's syntax. :-) + sed '=' <$as_myself | + sed ' + N + s,$,-, + : loop + s,^\(['$as_cr_digits']*\)\(.*\)[$]LINENO\([^'$as_cr_alnum'_]\),\1\2\1\3, + t loop + s,-$,, + s,^['$as_cr_digits']*\n,, + ' >$as_me.lineno && + chmod +x $as_me.lineno || + { { echo "$as_me:$LINENO: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&5 +echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2;} + { (exit 1); exit 1; }; } + + # Don't try to exec as it changes $[0], causing all sort of problems + # (the dirname of $[0] is not the place where we might find the + # original and so on. Autoconf is especially sensible to this). + . ./$as_me.lineno + # Exit status is that of the last command. + exit +} + + +case `echo "testing\c"; echo 1,2,3`,`echo -n testing; echo 1,2,3` in + *c*,-n*) ECHO_N= ECHO_C=' +' ECHO_T=' ' ;; + *c*,* ) ECHO_N=-n ECHO_C= ECHO_T= ;; + *) ECHO_N= ECHO_C='\c' ECHO_T= ;; +esac + +if expr a : '\(a\)' >/dev/null 2>&1; then + as_expr=expr +else + as_expr=false +fi + +rm -f conf$$ conf$$.exe conf$$.file +echo >conf$$.file +if ln -s conf$$.file conf$$ 2>/dev/null; then + # We could just check for DJGPP; but this test a) works b) is more generic + # and c) will remain valid once DJGPP supports symlinks (DJGPP 2.04). + if test -f conf$$.exe; then + # Don't use ln at all; we don't have any links + as_ln_s='cp -p' + else + as_ln_s='ln -s' + fi +elif ln conf$$.file conf$$ 2>/dev/null; then + as_ln_s=ln +else + as_ln_s='cp -p' +fi +rm -f conf$$ conf$$.exe conf$$.file + +if mkdir -p . 2>/dev/null; then + as_mkdir_p=: +else + as_mkdir_p=false +fi + +as_executable_p="test -f" + +# Sed expression to map a string onto a valid CPP name. +as_tr_cpp="sed y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g" + +# Sed expression to map a string onto a valid variable name. +as_tr_sh="sed y%*+%pp%;s%[^_$as_cr_alnum]%_%g" + + +# IFS +# We need space, tab and new line, in precisely that order. +as_nl=' +' +IFS=" $as_nl" + +# CDPATH. +$as_unset CDPATH + +exec 6>&1 + +# Open the log real soon, to keep \$[0] and so on meaningful, and to +# report actual input values of CONFIG_FILES etc. instead of their +# values after options handling. Logging --version etc. is OK. +exec 5>>config.log +{ + echo + sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX +## Running $as_me. ## +_ASBOX +} >&5 +cat >&5 <<_CSEOF + +This file was extended by $as_me, which was +generated by GNU Autoconf 2.57. Invocation command line was + + CONFIG_FILES = $CONFIG_FILES + CONFIG_HEADERS = $CONFIG_HEADERS + CONFIG_LINKS = $CONFIG_LINKS + CONFIG_COMMANDS = $CONFIG_COMMANDS + $ $0 $@ + +_CSEOF +echo "on `(hostname || uname -n) 2>/dev/null | sed 1q`" >&5 +echo >&5 +_ACEOF + +# Files that config.status was made for. +if test -n "$ac_config_files"; then + echo "config_files=\"$ac_config_files\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_headers"; then + echo "config_headers=\"$ac_config_headers\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_links"; then + echo "config_links=\"$ac_config_links\"" >>$CONFIG_STATUS +fi + +if test -n "$ac_config_commands"; then + echo "config_commands=\"$ac_config_commands\"" >>$CONFIG_STATUS +fi + +cat >>$CONFIG_STATUS <<\_ACEOF + +ac_cs_usage="\ +\`$as_me' instantiates files from templates according to the +current configuration. + +Usage: $0 [OPTIONS] [FILE]... + + -h, --help print this help, then exit + -V, --version print version number, then exit + -q, --quiet do not print progress messages + -d, --debug don't remove temporary files + --recheck update $as_me by reconfiguring in the same conditions + --file=FILE[:TEMPLATE] + instantiate the configuration file FILE + --header=FILE[:TEMPLATE] + instantiate the configuration header FILE + +Configuration files: +$config_files + +Configuration headers: +$config_headers + +Configuration commands: +$config_commands + +Report bugs to <bug-autoconf@gnu.org>." +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +ac_cs_version="\\ +config.status +configured by $0, generated by GNU Autoconf 2.57, + with options \\"`echo "$ac_configure_args" | sed 's/[\\""\`\$]/\\\\&/g'`\\" + +Copyright 1992, 1993, 1994, 1995, 1996, 1998, 1999, 2000, 2001 +Free Software Foundation, Inc. +This config.status script is free software; the Free Software Foundation +gives unlimited permission to copy, distribute and modify it." +srcdir=$srcdir +INSTALL="$INSTALL" +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF +# If no file are specified by the user, then we need to provide default +# value. By we need to know if files were specified by the user. +ac_need_defaults=: +while test $# != 0 +do + case $1 in + --*=*) + ac_option=`expr "x$1" : 'x\([^=]*\)='` + ac_optarg=`expr "x$1" : 'x[^=]*=\(.*\)'` + ac_shift=: + ;; + -*) + ac_option=$1 + ac_optarg=$2 + ac_shift=shift + ;; + *) # This is not an option, so the user has probably given explicit + # arguments. + ac_option=$1 + ac_need_defaults=false;; + esac + + case $ac_option in + # Handling of the options. +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r) + ac_cs_recheck=: ;; + --version | --vers* | -V ) + echo "$ac_cs_version"; exit 0 ;; + --he | --h) + # Conflict between --help and --header + { { echo "$as_me:$LINENO: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: ambiguous option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; };; + --help | --hel | -h ) + echo "$ac_cs_usage"; exit 0 ;; + --debug | --d* | -d ) + debug=: ;; + --file | --fil | --fi | --f ) + $ac_shift + CONFIG_FILES="$CONFIG_FILES $ac_optarg" + ac_need_defaults=false;; + --header | --heade | --head | --hea ) + $ac_shift + CONFIG_HEADERS="$CONFIG_HEADERS $ac_optarg" + ac_need_defaults=false;; + -q | -quiet | --quiet | --quie | --qui | --qu | --q \ + | -silent | --silent | --silen | --sile | --sil | --si | --s) + ac_cs_silent=: ;; + + # This is an error. + -*) { { echo "$as_me:$LINENO: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&5 +echo "$as_me: error: unrecognized option: $1 +Try \`$0 --help' for more information." >&2;} + { (exit 1); exit 1; }; } ;; + + *) ac_config_targets="$ac_config_targets $1" ;; + + esac + shift +done + +ac_configure_extra_args= + +if $ac_cs_silent; then + exec 6>/dev/null + ac_configure_extra_args="$ac_configure_extra_args --silent" +fi + +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF +if \$ac_cs_recheck; then + echo "running $SHELL $0 " $ac_configure_args \$ac_configure_extra_args " --no-create --no-recursion" >&6 + exec $SHELL $0 $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion +fi + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF +# +# INIT-COMMANDS section. +# + +AMDEP_TRUE="$AMDEP_TRUE" ac_aux_dir="$ac_aux_dir" + +_ACEOF + + + +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_config_target in $ac_config_targets +do + case "$ac_config_target" in + # Handling of arguments. + "Makefile" ) CONFIG_FILES="$CONFIG_FILES Makefile" ;; + "src/Makefile" ) CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "gelfx/Makefile" ) CONFIG_FILES="$CONFIG_FILES gelfx/Makefile" ;; + "gelfx32/Makefile" ) CONFIG_FILES="$CONFIG_FILES gelfx32/Makefile" ;; + "gelf/Makefile" ) CONFIG_FILES="$CONFIG_FILES gelf/Makefile" ;; + "m4/Makefile" ) CONFIG_FILES="$CONFIG_FILES m4/Makefile" ;; + "patches/Makefile" ) CONFIG_FILES="$CONFIG_FILES patches/Makefile" ;; + "doc/Makefile" ) CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "testsuite/Makefile" ) CONFIG_FILES="$CONFIG_FILES testsuite/Makefile" ;; + "depfiles" ) CONFIG_COMMANDS="$CONFIG_COMMANDS depfiles" ;; + "config.h" ) CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; + *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 +echo "$as_me: error: invalid argument: $ac_config_target" >&2;} + { (exit 1); exit 1; }; };; + esac +done + +# If the user did not use the arguments to specify the items to instantiate, +# then the envvar interface is used. Set only those that are not. +# We use the long form for the default assignment because of an extremely +# bizarre bug on SunOS 4.1.3. +if $ac_need_defaults; then + test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files + test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers + test "${CONFIG_COMMANDS+set}" = set || CONFIG_COMMANDS=$config_commands +fi + +# Have a temporary directory for convenience. Make it in the build tree +# simply because there is no reason to put it here, and in addition, +# creating and moving files from /tmp can sometimes cause problems. +# Create a temporary directory, and hook for its removal unless debugging. +$debug || +{ + trap 'exit_status=$?; rm -rf $tmp && exit $exit_status' 0 + trap '{ (exit 1); exit 1; }' 1 2 13 15 +} + +# Create a (secure) tmp directory for tmp files. + +{ + tmp=`(umask 077 && mktemp -d -q "./confstatXXXXXX") 2>/dev/null` && + test -n "$tmp" && test -d "$tmp" +} || +{ + tmp=./confstat$$-$RANDOM + (umask 077 && mkdir $tmp) +} || +{ + echo "$me: cannot create a temporary directory in ." >&2 + { (exit 1); exit 1; } +} + +_ACEOF + +cat >>$CONFIG_STATUS <<_ACEOF + +# +# CONFIG_FILES section. +# + +# No need to generate the scripts if there are no CONFIG_FILES. +# This happens for instance when ./config.status config.h +if test -n "\$CONFIG_FILES"; then + # Protect against being on the right side of a sed subst in config.status. + sed 's/,@/@@/; s/@,/@@/; s/,;t t\$/@;t t/; /@;t t\$/s/[\\\\&,]/\\\\&/g; + s/@@/,@/; s/@@/@,/; s/@;t t\$/,;t t/' >\$tmp/subs.sed <<\\CEOF +s,@SHELL@,$SHELL,;t t +s,@PATH_SEPARATOR@,$PATH_SEPARATOR,;t t +s,@PACKAGE_NAME@,$PACKAGE_NAME,;t t +s,@PACKAGE_TARNAME@,$PACKAGE_TARNAME,;t t +s,@PACKAGE_VERSION@,$PACKAGE_VERSION,;t t +s,@PACKAGE_STRING@,$PACKAGE_STRING,;t t +s,@PACKAGE_BUGREPORT@,$PACKAGE_BUGREPORT,;t t +s,@exec_prefix@,$exec_prefix,;t t +s,@prefix@,$prefix,;t t +s,@program_transform_name@,$program_transform_name,;t t +s,@bindir@,$bindir,;t t +s,@sbindir@,$sbindir,;t t +s,@libexecdir@,$libexecdir,;t t +s,@datadir@,$datadir,;t t +s,@sysconfdir@,$sysconfdir,;t t +s,@sharedstatedir@,$sharedstatedir,;t t +s,@localstatedir@,$localstatedir,;t t +s,@libdir@,$libdir,;t t +s,@includedir@,$includedir,;t t +s,@oldincludedir@,$oldincludedir,;t t +s,@infodir@,$infodir,;t t +s,@mandir@,$mandir,;t t +s,@build_alias@,$build_alias,;t t +s,@host_alias@,$host_alias,;t t +s,@target_alias@,$target_alias,;t t +s,@DEFS@,$DEFS,;t t +s,@ECHO_C@,$ECHO_C,;t t +s,@ECHO_N@,$ECHO_N,;t t +s,@ECHO_T@,$ECHO_T,;t t +s,@LIBS@,$LIBS,;t t +s,@build@,$build,;t t +s,@build_cpu@,$build_cpu,;t t +s,@build_vendor@,$build_vendor,;t t +s,@build_os@,$build_os,;t t +s,@host@,$host,;t t +s,@host_cpu@,$host_cpu,;t t +s,@host_vendor@,$host_vendor,;t t +s,@host_os@,$host_os,;t t +s,@INSTALL_PROGRAM@,$INSTALL_PROGRAM,;t t +s,@INSTALL_SCRIPT@,$INSTALL_SCRIPT,;t t +s,@INSTALL_DATA@,$INSTALL_DATA,;t t +s,@PACKAGE@,$PACKAGE,;t t +s,@VERSION@,$VERSION,;t t +s,@ACLOCAL@,$ACLOCAL,;t t +s,@AUTOCONF@,$AUTOCONF,;t t +s,@AUTOMAKE@,$AUTOMAKE,;t t +s,@AUTOHEADER@,$AUTOHEADER,;t t +s,@MAKEINFO@,$MAKEINFO,;t t +s,@AMTAR@,$AMTAR,;t t +s,@install_sh@,$install_sh,;t t +s,@STRIP@,$STRIP,;t t +s,@ac_ct_STRIP@,$ac_ct_STRIP,;t t +s,@INSTALL_STRIP_PROGRAM@,$INSTALL_STRIP_PROGRAM,;t t +s,@AWK@,$AWK,;t t +s,@SET_MAKE@,$SET_MAKE,;t t +s,@CC@,$CC,;t t +s,@CFLAGS@,$CFLAGS,;t t +s,@LDFLAGS@,$LDFLAGS,;t t +s,@CPPFLAGS@,$CPPFLAGS,;t t +s,@ac_ct_CC@,$ac_ct_CC,;t t +s,@EXEEXT@,$EXEEXT,;t t +s,@OBJEXT@,$OBJEXT,;t t +s,@DEPDIR@,$DEPDIR,;t t +s,@am__include@,$am__include,;t t +s,@am__quote@,$am__quote,;t t +s,@AMDEP_TRUE@,$AMDEP_TRUE,;t t +s,@AMDEP_FALSE@,$AMDEP_FALSE,;t t +s,@AMDEPBACKSLASH@,$AMDEPBACKSLASH,;t t +s,@CCDEPMODE@,$CCDEPMODE,;t t +s,@CXX@,$CXX,;t t +s,@CXXFLAGS@,$CXXFLAGS,;t t +s,@ac_ct_CXX@,$ac_ct_CXX,;t t +s,@CXXDEPMODE@,$CXXDEPMODE,;t t +s,@CPP@,$CPP,;t t +s,@EGREP@,$EGREP,;t t +s,@LN_S@,$LN_S,;t t +s,@ECHO@,$ECHO,;t t +s,@AR@,$AR,;t t +s,@ac_ct_AR@,$ac_ct_AR,;t t +s,@RANLIB@,$RANLIB,;t t +s,@ac_ct_RANLIB@,$ac_ct_RANLIB,;t t +s,@CXXCPP@,$CXXCPP,;t t +s,@F77@,$F77,;t t +s,@FFLAGS@,$FFLAGS,;t t +s,@ac_ct_F77@,$ac_ct_F77,;t t +s,@LIBTOOL@,$LIBTOOL,;t t +s,@GELFINCLUDE@,$GELFINCLUDE,;t t +s,@LIBGELF@,$LIBGELF,;t t +s,@LIBOBJS@,$LIBOBJS,;t t +s,@LTLIBOBJS@,$LTLIBOBJS,;t t +CEOF + +_ACEOF + + cat >>$CONFIG_STATUS <<\_ACEOF + # Split the substitutions into bite-sized pieces for seds with + # small command number limits, like on Digital OSF/1 and HP-UX. + ac_max_sed_lines=48 + ac_sed_frag=1 # Number of current file. + ac_beg=1 # First line for current file. + ac_end=$ac_max_sed_lines # Line after last line for current file. + ac_more_lines=: + ac_sed_cmds= + while $ac_more_lines; do + if test $ac_beg -gt 1; then + sed "1,${ac_beg}d; ${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + else + sed "${ac_end}q" $tmp/subs.sed >$tmp/subs.frag + fi + if test ! -s $tmp/subs.frag; then + ac_more_lines=false + else + # The purpose of the label and of the branching condition is to + # speed up the sed processing (if there are no `@' at all, there + # is no need to browse any of the substitutions). + # These are the two extra sed commands mentioned above. + (echo ':t + /@[a-zA-Z_][a-zA-Z_0-9]*@/!b' && cat $tmp/subs.frag) >$tmp/subs-$ac_sed_frag.sed + if test -z "$ac_sed_cmds"; then + ac_sed_cmds="sed -f $tmp/subs-$ac_sed_frag.sed" + else + ac_sed_cmds="$ac_sed_cmds | sed -f $tmp/subs-$ac_sed_frag.sed" + fi + ac_sed_frag=`expr $ac_sed_frag + 1` + ac_beg=$ac_end + ac_end=`expr $ac_end + $ac_max_sed_lines` + fi + done + if test -z "$ac_sed_cmds"; then + ac_sed_cmds=cat + fi +fi # test -n "$CONFIG_FILES" + +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +for ac_file in : $CONFIG_FILES; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + # Compute @srcdir@, @top_srcdir@, and @INSTALL@ for subdirectories. + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + case $INSTALL in + [\\/$]* | ?:[\\/]* ) ac_INSTALL=$INSTALL ;; + *) ac_INSTALL=$ac_top_builddir$INSTALL ;; + esac + + if test x"$ac_file" != x-; then + { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + rm -f "$ac_file" + fi + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + configure_input= + else + configure_input="$ac_file. " + fi + configure_input=$configure_input"Generated from `echo $ac_file_in | + sed 's,.*/,,'` by configure." + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } +_ACEOF +cat >>$CONFIG_STATUS <<_ACEOF + sed "$ac_vpsub +$extrasub +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF +:t +/@[a-zA-Z_][a-zA-Z_0-9]*@/!b +s,@configure_input@,$configure_input,;t t +s,@srcdir@,$ac_srcdir,;t t +s,@abs_srcdir@,$ac_abs_srcdir,;t t +s,@top_srcdir@,$ac_top_srcdir,;t t +s,@abs_top_srcdir@,$ac_abs_top_srcdir,;t t +s,@builddir@,$ac_builddir,;t t +s,@abs_builddir@,$ac_abs_builddir,;t t +s,@top_builddir@,$ac_top_builddir,;t t +s,@abs_top_builddir@,$ac_abs_top_builddir,;t t +s,@INSTALL@,$ac_INSTALL,;t t +" $ac_file_inputs | (eval "$ac_sed_cmds") >$tmp/out + rm -f $tmp/stdin + if test x"$ac_file" != x-; then + mv $tmp/out $ac_file + else + cat $tmp/out + rm -f $tmp/out + fi + +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_HEADER section. +# + +# These sed commands are passed to sed as "A NAME B NAME C VALUE D", where +# NAME is the cpp macro being defined and VALUE is the value it is being given. +# +# ac_d sets the value in "#define NAME VALUE" lines. +ac_dA='s,^\([ ]*\)#\([ ]*define[ ][ ]*\)' +ac_dB='[ ].*$,\1#\2' +ac_dC=' ' +ac_dD=',;t' +# ac_u turns "#undef NAME" without trailing blanks into "#define NAME VALUE". +ac_uA='s,^\([ ]*\)#\([ ]*\)undef\([ ][ ]*\)' +ac_uB='$,\1#\2define\3' +ac_uC=' ' +ac_uD=',;t' + +for ac_file in : $CONFIG_HEADERS; do test "x$ac_file" = x: && continue + # Support "outfile[:infile[:infile...]]", defaulting infile="outfile.in". + case $ac_file in + - | *:- | *:-:* ) # input from stdin + cat >$tmp/stdin + ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + *:* ) ac_file_in=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_file=`echo "$ac_file" | sed 's,:.*,,'` ;; + * ) ac_file_in=$ac_file.in ;; + esac + + test x"$ac_file" != x- && { echo "$as_me:$LINENO: creating $ac_file" >&5 +echo "$as_me: creating $ac_file" >&6;} + + # First look for the input files in the build tree, otherwise in the + # src tree. + ac_file_inputs=`IFS=: + for f in $ac_file_in; do + case $f in + -) echo $tmp/stdin ;; + [\\/$]*) + # Absolute (can't be DOS-style, as IFS=:) + test -f "$f" || { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + echo $f;; + *) # Relative + if test -f "$f"; then + # Build tree + echo $f + elif test -f "$srcdir/$f"; then + # Source tree + echo $srcdir/$f + else + # /dev/null tree + { { echo "$as_me:$LINENO: error: cannot find input file: $f" >&5 +echo "$as_me: error: cannot find input file: $f" >&2;} + { (exit 1); exit 1; }; } + fi;; + esac + done` || { (exit 1); exit 1; } + # Remove the trailing spaces. + sed 's/[ ]*$//' $ac_file_inputs >$tmp/in + +_ACEOF + +# Transform confdefs.h into two sed scripts, `conftest.defines' and +# `conftest.undefs', that substitutes the proper values into +# config.h.in to produce config.h. The first handles `#define' +# templates, and the second `#undef' templates. +# And first: Protect against being on the right side of a sed subst in +# config.status. Protect against being in an unquoted here document +# in config.status. +rm -f conftest.defines conftest.undefs +# Using a here document instead of a string reduces the quoting nightmare. +# Putting comments in sed scripts is not portable. +# +# `end' is used to avoid that the second main sed command (meant for +# 0-ary CPP macros) applies to n-ary macro definitions. +# See the Autoconf documentation for `clear'. +cat >confdef2sed.sed <<\_ACEOF +s/[\\&,]/\\&/g +s,[\\$`],\\&,g +t clear +: clear +s,^[ ]*#[ ]*define[ ][ ]*\([^ (][^ (]*\)\(([^)]*)\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1\2${ac_dC}\3${ac_dD},gp +t end +s,^[ ]*#[ ]*define[ ][ ]*\([^ ][^ ]*\)[ ]*\(.*\)$,${ac_dA}\1${ac_dB}\1${ac_dC}\2${ac_dD},gp +: end +_ACEOF +# If some macros were called several times there might be several times +# the same #defines, which is useless. Nevertheless, we may not want to +# sort them, since we want the *last* AC-DEFINE to be honored. +uniq confdefs.h | sed -n -f confdef2sed.sed >conftest.defines +sed 's/ac_d/ac_u/g' conftest.defines >conftest.undefs +rm -f confdef2sed.sed + +# This sed command replaces #undef with comments. This is necessary, for +# example, in the case of _POSIX_SOURCE, which is predefined and required +# on some systems where configure will not decide to define it. +cat >>conftest.undefs <<\_ACEOF +s,^[ ]*#[ ]*undef[ ][ ]*[a-zA-Z_][a-zA-Z_0-9]*,/* & */, +_ACEOF + +# Break up conftest.defines because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #define templates only if necessary.' >>$CONFIG_STATUS +echo ' if grep "^[ ]*#[ ]*define" $tmp/in >/dev/null; then' >>$CONFIG_STATUS +echo ' # If there are no defines, we may have an empty if/fi' >>$CONFIG_STATUS +echo ' :' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.defines >/dev/null +do + # Write a limited-size here document to $tmp/defines.sed. + echo ' cat >$tmp/defines.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#define' lines. + echo '/^[ ]*#[ ]*define/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.defines >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/defines.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.defines >conftest.tail + rm -f conftest.defines + mv conftest.tail conftest.defines +done +rm -f conftest.defines +echo ' fi # grep' >>$CONFIG_STATUS +echo >>$CONFIG_STATUS + +# Break up conftest.undefs because some shells have a limit on the size +# of here documents, and old seds have small limits too (100 cmds). +echo ' # Handle all the #undef templates' >>$CONFIG_STATUS +rm -f conftest.tail +while grep . conftest.undefs >/dev/null +do + # Write a limited-size here document to $tmp/undefs.sed. + echo ' cat >$tmp/undefs.sed <<CEOF' >>$CONFIG_STATUS + # Speed up: don't consider the non `#undef' + echo '/^[ ]*#[ ]*undef/!b' >>$CONFIG_STATUS + # Work around the forget-to-reset-the-flag bug. + echo 't clr' >>$CONFIG_STATUS + echo ': clr' >>$CONFIG_STATUS + sed ${ac_max_here_lines}q conftest.undefs >>$CONFIG_STATUS + echo 'CEOF + sed -f $tmp/undefs.sed $tmp/in >$tmp/out + rm -f $tmp/in + mv $tmp/out $tmp/in +' >>$CONFIG_STATUS + sed 1,${ac_max_here_lines}d conftest.undefs >conftest.tail + rm -f conftest.undefs + mv conftest.tail conftest.undefs +done +rm -f conftest.undefs + +cat >>$CONFIG_STATUS <<\_ACEOF + # Let's still pretend it is `configure' which instantiates (i.e., don't + # use $as_me), people would be surprised to read: + # /* config.h. Generated by config.status. */ + if test x"$ac_file" = x-; then + echo "/* Generated by configure. */" >$tmp/config.h + else + echo "/* $ac_file. Generated by configure. */" >$tmp/config.h + fi + cat $tmp/in >>$tmp/config.h + rm -f $tmp/in + if test x"$ac_file" != x-; then + if diff $ac_file $tmp/config.h >/dev/null 2>&1; then + { echo "$as_me:$LINENO: $ac_file is unchanged" >&5 +echo "$as_me: $ac_file is unchanged" >&6;} + else + ac_dir=`(dirname "$ac_file") 2>/dev/null || +$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_file" : 'X\(//\)[^/]' \| \ + X"$ac_file" : 'X\(//\)$' \| \ + X"$ac_file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p "$ac_dir" + else + as_dir="$ac_dir" + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory \"$ac_dir\"" >&5 +echo "$as_me: error: cannot create directory \"$ac_dir\"" >&2;} + { (exit 1); exit 1; }; }; } + + rm -f $ac_file + mv $tmp/config.h $ac_file + fi + else + cat $tmp/config.h + rm -f $tmp/config.h + fi + # Run the commands associated with the file. + case $ac_file in + config.h ) # update the timestamp +echo 'timestamp for config.h' >"./stamp-h1" + ;; + esac +done +_ACEOF +cat >>$CONFIG_STATUS <<\_ACEOF + +# +# CONFIG_COMMANDS section. +# +for ac_file in : $CONFIG_COMMANDS; do test "x$ac_file" = x: && continue + ac_dest=`echo "$ac_file" | sed 's,:.*,,'` + ac_source=`echo "$ac_file" | sed 's,[^:]*:,,'` + ac_dir=`(dirname "$ac_dest") 2>/dev/null || +$as_expr X"$ac_dest" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$ac_dest" : 'X\(//\)[^/]' \| \ + X"$ac_dest" : 'X\(//\)$' \| \ + X"$ac_dest" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$ac_dest" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + ac_builddir=. + +if test "$ac_dir" != .; then + ac_dir_suffix=/`echo "$ac_dir" | sed 's,^\.[\\/],,'` + # A "../" for each directory in $ac_dir_suffix. + ac_top_builddir=`echo "$ac_dir_suffix" | sed 's,/[^\\/]*,../,g'` +else + ac_dir_suffix= ac_top_builddir= +fi + +case $srcdir in + .) # No --srcdir option. We are building in place. + ac_srcdir=. + if test -z "$ac_top_builddir"; then + ac_top_srcdir=. + else + ac_top_srcdir=`echo $ac_top_builddir | sed 's,/$,,'` + fi ;; + [\\/]* | ?:[\\/]* ) # Absolute path. + ac_srcdir=$srcdir$ac_dir_suffix; + ac_top_srcdir=$srcdir ;; + *) # Relative path. + ac_srcdir=$ac_top_builddir$srcdir$ac_dir_suffix + ac_top_srcdir=$ac_top_builddir$srcdir ;; +esac +# Don't blindly perform a `cd "$ac_dir"/$ac_foo && pwd` since $ac_foo can be +# absolute. +ac_abs_builddir=`cd "$ac_dir" && cd $ac_builddir && pwd` +ac_abs_top_builddir=`cd "$ac_dir" && cd ${ac_top_builddir}. && pwd` +ac_abs_srcdir=`cd "$ac_dir" && cd $ac_srcdir && pwd` +ac_abs_top_srcdir=`cd "$ac_dir" && cd $ac_top_srcdir && pwd` + + + { echo "$as_me:$LINENO: executing $ac_dest commands" >&5 +echo "$as_me: executing $ac_dest commands" >&6;} + case $ac_dest in + depfiles ) test x"$AMDEP_TRUE" != x"" || for mf in $CONFIG_FILES; do + # Strip MF so we end up with the name of the file. + mf=`echo "$mf" | sed -e 's/:.*$//'` + # Check whether this is an Automake generated Makefile or not. + # We used to match only the files named `Makefile.in', but + # some people rename them; so instead we look at the file content. + # Grep'ing the first line is not enough: some people post-process + # each Makefile.in and add a new line on top of each file to say so. + # So let's grep whole file. + if grep '^#.*generated by automake' $mf > /dev/null 2>&1; then + dirpart=`(dirname "$mf") 2>/dev/null || +$as_expr X"$mf" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$mf" : 'X\(//\)[^/]' \| \ + X"$mf" : 'X\(//\)$' \| \ + X"$mf" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$mf" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + else + continue + fi + grep '^DEP_FILES *= *[^ #]' < "$mf" > /dev/null || continue + # Extract the definition of DEP_FILES from the Makefile without + # running `make'. + DEPDIR=`sed -n -e '/^DEPDIR = / s///p' < "$mf"` + test -z "$DEPDIR" && continue + # When using ansi2knr, U may be empty or an underscore; expand it + U=`sed -n -e '/^U = / s///p' < "$mf"` + test -d "$dirpart/$DEPDIR" || mkdir "$dirpart/$DEPDIR" + # We invoke sed twice because it is the simplest approach to + # changing $(DEPDIR) to its actual value in the expansion. + for file in `sed -n -e ' + /^DEP_FILES = .*\\\\$/ { + s/^DEP_FILES = // + :loop + s/\\\\$// + p + n + /\\\\$/ b loop + p + } + /^DEP_FILES = / s/^DEP_FILES = //p' < "$mf" | \ + sed -e 's/\$(DEPDIR)/'"$DEPDIR"'/g' -e 's/\$U/'"$U"'/g'`; do + # Make sure the directory exists. + test -f "$dirpart/$file" && continue + fdir=`(dirname "$file") 2>/dev/null || +$as_expr X"$file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$file" : 'X\(//\)[^/]' \| \ + X"$file" : 'X\(//\)$' \| \ + X"$file" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$file" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + { if $as_mkdir_p; then + mkdir -p $dirpart/$fdir + else + as_dir=$dirpart/$fdir + as_dirs= + while test ! -d "$as_dir"; do + as_dirs="$as_dir $as_dirs" + as_dir=`(dirname "$as_dir") 2>/dev/null || +$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \ + X"$as_dir" : 'X\(//\)[^/]' \| \ + X"$as_dir" : 'X\(//\)$' \| \ + X"$as_dir" : 'X\(/\)' \| \ + . : '\(.\)' 2>/dev/null || +echo X"$as_dir" | + sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{ s//\1/; q; } + /^X\(\/\/\)[^/].*/{ s//\1/; q; } + /^X\(\/\/\)$/{ s//\1/; q; } + /^X\(\/\).*/{ s//\1/; q; } + s/.*/./; q'` + done + test ! -n "$as_dirs" || mkdir $as_dirs + fi || { { echo "$as_me:$LINENO: error: cannot create directory $dirpart/$fdir" >&5 +echo "$as_me: error: cannot create directory $dirpart/$fdir" >&2;} + { (exit 1); exit 1; }; }; } + + # echo "creating $dirpart/$file" + echo '# dummy' > "$dirpart/$file" + done +done + ;; + esac +done +_ACEOF + +cat >>$CONFIG_STATUS <<\_ACEOF + +{ (exit 0); exit 0; } +_ACEOF +chmod +x $CONFIG_STATUS +ac_clean_files=$ac_clean_files_save + + +# configure is writing to config.log, and then calls config.status. +# config.status does its own redirection, appending to config.log. +# Unfortunately, on DOS this fails, as config.log is still kept open +# by configure, so config.status won't be able to write to it; its +# output is simply discarded. So we exec the FD to /dev/null, +# effectively closing config.log, so it can be properly (re)opened and +# appended to by config.status. When coming back to configure, we +# need to make the FD available again. +if test "$no_create" != yes; then + ac_cs_success=: + ac_config_status_args= + test "$silent" = yes && + ac_config_status_args="$ac_config_status_args --quiet" + exec 5>/dev/null + $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false + exec 5>>config.log + # Use ||, not &&, to avoid exiting from the if with $? = 1, which + # would make configure fail if this is the last instruction. + $ac_cs_success || { (exit 1); exit 1; } +fi + diff --git a/trunk/configure.in b/trunk/configure.in new file mode 100644 index 0000000..396f3ac --- /dev/null +++ b/trunk/configure.in @@ -0,0 +1,93 @@ +dnl Process this file with autoconf to produce a configure script. -*-m4-*- +AC_INIT(src/prelink.c) +AM_CONFIG_HEADER(config.h) +AC_PREREQ(2.13) dnl Minimum Autoconf version required. +AC_CANONICAL_HOST + +AM_INIT_AUTOMAKE([prelink], [0.0]) + +ALL_LINGUAS= + +AC_PROG_CC +AC_PROG_CXX +AC_PROG_CPP +AC_PROG_GCC_TRADITIONAL +AM_PROG_LIBTOOL + +AC_ARG_ENABLE(64-bit, +[ --disable-64-bit only support 32-bit ELF], +[case "${enableval}" in + yes) want64=true ;; + no) want64=false ;; + *) AC_MSG_ERROR(bad value ${enableval} for 64-bit option) ;; +esac],[want64=true])dnl + +AC_CHECK_HEADER(libelf.h,,[ + if test -f /usr/include/elfutils/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/include/elfutils" + elif test -f /usr/local/include/elfutils/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/local/include/elfutils" + elif test -f /usr/include/libelf/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/include/libelf" + elif test -f /usr/local/include/libelf/libelf.h; then + CPPFLAGS="$CPPFLAGS -I /usr/local/include/libelf" + else + AC_MSG_ERROR(libelf.h not found) + fi]) +LIBGELF="" +if test "$want64"x = falsex; then + GELFINCLUDE='-I$(top_srcdir)/gelfx32' +else + GELFINCLUDE='-I$(top_srcdir)/gelfx' + AC_CHECK_HEADER(gelf.h,,[ + GELFINCLUDE="$GELFINCLUDE "'-I$(top_srcdir)/gelf' + LIBGELF='../gelf/libgelf.la' + ]) +fi +AC_CHECK_LIB(elf,elf_begin) +AC_SUBST(GELFINCLUDE) +AC_SUBST(LIBGELF) + +dnl Now check what kind of libelf we will link against +AC_CHECK_FUNC(gelf_getvernaux,[newbu=true],[newbu=false]) + +dnl Check if FTW_ACTIONRETVAL is supported +AC_CACHE_CHECK([whether FTW_ACTIONRETVAL is supported], + [ac_cv_ftw_actionretval], [dnl + AC_EGREP_CPP([FTW supports ACTIONRETVAL], [ + #ifndef _GNU_SOURCE + #define _GNU_SOURCE 1 + #endif + #include <ftw.h> + #ifdef FTW_ACTIONRETVAL + FTW supports ACTIONRETVAL + #endif + ], ac_cv_ftw_actionretval=yes, ac_cv_ftw_actionretval=no)]) +if test "x$ac_cv_ftw_actionretval" = xyes; then + AC_DEFINE(HAVE_FTW_ACTIONRETVAL, 1, + [Define if FTW_ACTIONRETVAL is supported.]) +fi + +dnl SELinux checks +AC_CHECK_LIB(selinux,is_selinux_enabled) +AC_CHECK_HEADERS(selinux/selinux.h) + +dnl This test must come as early as possible after the compiler configuration +dnl tests, because the choice of the file model can (in principle) affect +dnl whether functions and headers are available, whether they work, etc. +if test x"$newbu" = xtrue; then + # Don't use LFS for libelf-0.x + AC_SYS_LARGEFILE +fi + +AC_LIBELF_SXWORD + +AC_OUTPUT([Makefile + src/Makefile + gelfx/Makefile + gelfx32/Makefile + gelf/Makefile + m4/Makefile + patches/Makefile + doc/Makefile + testsuite/Makefile]) diff --git a/trunk/depcomp b/trunk/depcomp new file mode 100755 index 0000000..368e3be --- /dev/null +++ b/trunk/depcomp @@ -0,0 +1,436 @@ +#! /bin/sh + +# depcomp - compile a program generating dependencies as side-effects +# Copyright 1999, 2000 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Originally written by Alexandre Oliva <oliva@dcc.unicamp.br>. + +if test -z "$depmode" || test -z "$source" || test -z "$object"; then + echo "depcomp: Variables source, object and depmode must be set" 1>&2 + exit 1 +fi +# `libtool' can also be set to `yes' or `no'. + +if test -z "$depfile"; then + base=`echo "$object" | sed -e 's,^.*/,,' -e 's,\.\([^.]*\)$,.P\1,'` + dir=`echo "$object" | sed 's,/.*$,/,'` + if test "$dir" = "$object"; then + dir= + fi + # FIXME: should be _deps on DOS. + depfile="$dir.deps/$base" +fi + +tmpdepfile=${tmpdepfile-`echo "$depfile" | sed 's/\.\([^.]*\)$/.T\1/'`} + +rm -f "$tmpdepfile" + +# Some modes work just like other modes, but use different flags. We +# parameterize here, but still list the modes in the big case below, +# to make depend.m4 easier to write. Note that we *cannot* use a case +# here, because this file can only contain one case statement. +if test "$depmode" = hp; then + # HP compiler uses -M and no extra arg. + gccflag=-M + depmode=gcc +fi + +if test "$depmode" = dashXmstdout; then + # This is just like dashmstdout with a different argument. + dashmflag=-xM + depmode=dashmstdout +fi + +case "$depmode" in +gcc3) +## gcc 3 implements dependency tracking that does exactly what +## we want. Yay! Note: for some reason libtool 1.4 doesn't like +## it if -MD -MP comes after the -MF stuff. Hmm. + "$@" -MT "$object" -MD -MP -MF "$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + mv "$tmpdepfile" "$depfile" + ;; + +gcc) +## There are various ways to get dependency output from gcc. Here's +## why we pick this rather obscure method: +## - Don't want to use -MD because we'd like the dependencies to end +## up in a subdir. Having to rename by hand is ugly. +## (We might end up doing this anyway to support other compilers.) +## - The DEPENDENCIES_OUTPUT environment variable makes gcc act like +## -MM, not -M (despite what the docs say). +## - Using -M directly means running the compiler twice (even worse +## than renaming). + if test -z "$gccflag"; then + gccflag=-MD, + fi + "$@" -Wp,"$gccflag$tmpdepfile" + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + alpha=ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz +## The second -e expression handles DOS-style file names with drive letters. + sed -e 's/^[^:]*: / /' \ + -e 's/^['$alpha']:\/[^:]*: / /' < "$tmpdepfile" >> "$depfile" +## This next piece of magic avoids the `deleted header file' problem. +## The problem is that when a header file which appears in a .P file +## is deleted, the dependency causes make to die (because there is +## typically no way to rebuild the header). We avoid this by adding +## dummy dependencies for each header file. Too bad gcc doesn't do +## this for us directly. + tr ' ' ' +' < "$tmpdepfile" | +## Some versions of gcc put a space before the `:'. On the theory +## that the space means something, we add a space to the output as +## well. +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +hp) + # This case exists only to let depend.m4 do its work. It works by + # looking at the text of this script. This case will never be run, + # since it is checked for above. + exit 1 + ;; + +sgi) + if test "$libtool" = yes; then + "$@" "-Wp,-MDupdate,$tmpdepfile" + else + "$@" -MDupdate "$tmpdepfile" + fi + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + rm -f "$depfile" + + if test -f "$tmpdepfile"; then # yes, the sourcefile depend on other files + echo "$object : \\" > "$depfile" + + # Clip off the initial element (the dependent). Don't try to be + # clever and replace this with sed code, as IRIX sed won't handle + # lines with more than a fixed number of characters (4096 in + # IRIX 6.2 sed, 8192 in IRIX 6.5). We also remove comment lines; + # the IRIX cc adds comments like `#:fec' to the end of the + # dependency line. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' | \ + tr ' +' ' ' >> $depfile + echo >> $depfile + + # The second pass generates a dummy entry for each header file. + tr ' ' ' +' < "$tmpdepfile" \ + | sed -e 's/^.*\.o://' -e 's/#.*$//' -e '/^$/ d' -e 's/$/:/' \ + >> $depfile + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +aix) + # The C for AIX Compiler uses -M and outputs the dependencies + # in a .u file. This file always lives in the current directory. + # Also, the AIX compiler puts `$object:' at the start of each line; + # $object doesn't have directory information. + stripped=`echo "$object" | sed -e 's,^.*/,,' -e 's/\(.*\)\..*$/\1/'` + tmpdepfile="$stripped.u" + outname="$stripped.o" + if test "$libtool" = yes; then + "$@" -Wc,-M + else + "$@" -M + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile" + exit $stat + fi + + if test -f "$tmpdepfile"; then + # Each line is of the form `foo.o: dependent.h'. + # Do two passes, one to just change these to + # `$object: dependent.h' and one to simply `dependent.h:'. + sed -e "s,^$outname:,$object :," < "$tmpdepfile" > "$depfile" + sed -e "s,^$outname: \(.*\)$,\1:," < "$tmpdepfile" >> "$depfile" + else + # The sourcefile does not contain any dependencies, so just + # store a dummy comment line, to avoid errors with the Makefile + # "include basename.Plo" scheme. + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +tru64) + # The Tru64 AIX compiler uses -MD to generate dependencies as a side + # effect. `cc -MD -o foo.o ...' puts the dependencies into `foo.o.d'. + # At least on Alpha/Redhat 6.1, Compaq CCC V6.2-504 seems to put + # dependencies in `foo.d' instead, so we check for that too. + # Subdirectories are respected. + + base=`echo "$object" | sed -e 's/\.o$/.d/' -e 's/\.lo$/.d/'` + tmpdepfile1="$base.o.d" + tmpdepfile2="$base.d" + if test "$libtool" = yes; then + "$@" -Wc,-MD + else + "$@" -MD + fi + + stat=$? + if test $stat -eq 0; then : + else + rm -f "$tmpdepfile1" "$tmpdepfile2" + exit $stat + fi + + if test -f "$tmpdepfile1"; then + tmpdepfile="$tmpdepfile1" + else + tmpdepfile="$tmpdepfile2" + fi + if test -f "$tmpdepfile"; then + sed -e "s,^.*\.[a-z]*:,$object:," < "$tmpdepfile" > "$depfile" + # That's a space and a tab in the []. + sed -e 's,^.*\.[a-z]*:[ ]*,,' -e 's,$,:,' < "$tmpdepfile" >> "$depfile" + else + echo "#dummy" > "$depfile" + fi + rm -f "$tmpdepfile" + ;; + +#nosideeffect) + # This comment above is used by automake to tell side-effect + # dependency tracking mechanisms from slower ones. + +dashmstdout) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + test -z "$dashmflag" && dashmflag=-M + ( IFS=" " + case " $* " in + *" --mode=compile "*) # this is libtool, let us make it quiet + for arg + do # cycle over the arguments + case "$arg" in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" $dashmflag | sed 's:^[^:]*\:[ ]*:'"$object"'\: :' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + tr ' ' ' +' < "$tmpdepfile" | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +dashXmstdout) + # This case only exists to satisfy depend.m4. It is never actually + # run, as this mode is specially recognized in the preamble. + exit 1 + ;; + +makedepend) + # X makedepend + ( + shift + cleared=no + for arg in "$@"; do + case $cleared in no) + set ""; shift + cleared=yes + esac + case "$arg" in + -D*|-I*) + set fnord "$@" "$arg"; shift;; + -*) + ;; + *) + set fnord "$@" "$arg"; shift;; + esac + done + obj_suffix="`echo $object | sed 's/^.*\././'`" + touch "$tmpdepfile" + ${MAKEDEPEND-makedepend} 2>/dev/null -o"$obj_suffix" -f"$tmpdepfile" "$@" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + cat < "$tmpdepfile" > "$depfile" + sed '1,2d' "$tmpdepfile" | tr ' ' ' +' | \ +## Some versions of the HPUX 10.20 sed can't process this invocation +## correctly. Breaking it into two sed invocations is a workaround. + sed -e 's/^\\$//' -e '/^$/d' -e '/:$/d' | sed -e 's/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" "$tmpdepfile".bak + ;; + +cpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + "$@" -E | + sed -n '/^# [0-9][0-9]* "\([^"]*\)".*/ s:: \1 \\:p' | + sed '$ s: \\$::' > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + cat < "$tmpdepfile" >> "$depfile" + sed < "$tmpdepfile" '/^$/d;s/^ //;s/ \\$//;s/$/ :/' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +msvisualcpp) + # Important note: in order to support this mode, a compiler *must* + # always write the proprocessed file to stdout, regardless of -o, + # because we must use -o when running libtool. + ( IFS=" " + case " $* " in + *" --mode=compile "*) + for arg + do # cycle over the arguments + case $arg in + "--mode=compile") + # insert --quiet before "--mode=compile" + set fnord "$@" --quiet + shift # fnord + ;; + esac + set fnord "$@" "$arg" + shift # fnord + shift # "$arg" + done + ;; + esac + for arg + do + case "$arg" in + "-Gm"|"/Gm"|"-Gi"|"/Gi"|"-ZI"|"/ZI") + set fnord "$@" + shift + shift + ;; + *) + set fnord "$@" "$arg" + shift + shift + ;; + esac + done + "$@" -E | + sed -n '/^#line [0-9][0-9]* "\([^"]*\)"/ s::echo "`cygpath -u \\"\1\\"`":p' | sort | uniq > "$tmpdepfile" + ) & + proc=$! + "$@" + stat=$? + wait "$proc" + if test "$stat" != 0; then exit $stat; fi + rm -f "$depfile" + echo "$object : \\" > "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s:: \1 \\:p' >> "$depfile" + echo " " >> "$depfile" + . "$tmpdepfile" | sed 's% %\\ %g' | sed -n '/^\(.*\)$/ s::\1\::p' >> "$depfile" + rm -f "$tmpdepfile" + ;; + +none) + exec "$@" + ;; + +*) + echo "Unknown depmode $depmode" 1>&2 + exit 1 + ;; +esac + +exit 0 diff --git a/trunk/doc/Makefile.am b/trunk/doc/Makefile.am new file mode 100644 index 0000000..45f4757 --- /dev/null +++ b/trunk/doc/Makefile.am @@ -0,0 +1,42 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +man_MANS = prelink.8 execstack.8 +EXTRA_DIST = prelink.8 execstack.8 prelink.conf +PDFLATEXINPUTS = TEXINPUTS_pdflatex=.:$(srcdir):`kpsewhich --progname=pdflatex --show-path=cnf.pdflatex` +LATEXINPUTS = TEXINPUTS_latex=.:$(srcdir):`kpsewhich --progname=latex --show-path=cnf.latex` + +noinst_DATA = prelink.pdf +pics = gap bss basemove newseg dso1 dso2 dso3 + +prelink.pdf: prelink.tex $(pics:=.fig) linuxtag.sty \ + prelinklisting.sty lineno.sty glossary.conf + $(MAKE) $(pics:=.pdf) + $(PDFLATEXINPUTS) pdflatex $< + makeindex -s $(srcdir)/glossary.conf -o prelink.gls prelink.glo + if grep -q Rerun prelink.log; then $(PDFLATEXINPUTS) pdflatex $<; fi + thumbpdf $@ && $(PDFLATEXINPUTS) pdflatex $< + mv $@ prelinkin.pdf + pdfopt prelinkin.pdf $@ + rm prelinkin.pdf + +prelink.ps: prelink.dvi + dvips $< -o $@ + +prelink.dvi: prelink.tex $(pics:=.eps) + $(LATEXINPUTS) latex $< + if grep -q Rerun prelink.log; then $(LATEXINPUTS) latex $<; fi + +SUFFIXES = .fig .eps .pdf + +.fig.eps: + fig2dev -L eps $^ $@ + +.fig.pdf: + fig2dev -L pdf $^ $@ + +CLEANFILES = $(pics:=.eps) $(pics:=.pdf) prelink.aux prelink.dvi \ + prelink.log prelink.mtc prelink.mtc1 prelink.pdf prelink.ps \ + prelink.glo prelink.idx prelink.out prelink.tpt prelink.ilg \ + prelink.gls prelink.toc diff --git a/trunk/doc/Makefile.in b/trunk/doc/Makefile.in new file mode 100644 index 0000000..678002b --- /dev/null +++ b/trunk/doc/Makefile.in @@ -0,0 +1,323 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +man_MANS = prelink.8 execstack.8 +EXTRA_DIST = prelink.8 execstack.8 prelink.conf +PDFLATEXINPUTS = TEXINPUTS_pdflatex=.:$(srcdir):`kpsewhich --progname=pdflatex --show-path=cnf.pdflatex` +LATEXINPUTS = TEXINPUTS_latex=.:$(srcdir):`kpsewhich --progname=latex --show-path=cnf.latex` + +noinst_DATA = prelink.pdf +pics = gap bss basemove newseg dso1 dso2 dso3 + +SUFFIXES = .fig .eps .pdf + +CLEANFILES = $(pics:=.eps) $(pics:=.pdf) prelink.aux prelink.dvi \ + prelink.log prelink.mtc prelink.mtc1 prelink.pdf prelink.ps \ + prelink.glo prelink.idx prelink.out prelink.tpt prelink.ilg \ + prelink.gls prelink.toc + +subdir = doc +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = + +NROFF = nroff +MANS = $(man_MANS) +DATA = $(noinst_DATA) + +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +.SUFFIXES: .fig .eps .pdf +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu doc/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +man8dir = $(mandir)/man8 +install-man8: $(man8_MANS) $(man_MANS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + case "$$ext" in \ + 8*) ;; \ + *) ext='8' ;; \ + esac; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done +uninstall-man8: + @$(NORMAL_UNINSTALL) + @list='$(man8_MANS) $(dist_man8_MANS) $(nodist_man8_MANS)'; \ + l2='$(man_MANS) $(dist_man_MANS) $(nodist_man_MANS)'; \ + for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed -e 's/^.*\///'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(MANS) $(DATA) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: install-man + +install-exec-am: + +install-info: install-info-am + +install-man: install-man8 + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am uninstall-man + +uninstall-man: uninstall-man8 + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-man8 install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool uninstall uninstall-am uninstall-info-am \ + uninstall-man uninstall-man8 + + +prelink.pdf: prelink.tex $(pics:=.fig) linuxtag.sty \ + prelinklisting.sty lineno.sty glossary.conf + $(MAKE) $(pics:=.pdf) + $(PDFLATEXINPUTS) pdflatex $< + makeindex -s $(srcdir)/glossary.conf -o prelink.gls prelink.glo + if grep -q Rerun prelink.log; then $(PDFLATEXINPUTS) pdflatex $<; fi + thumbpdf $@ && $(PDFLATEXINPUTS) pdflatex $< + mv $@ prelinkin.pdf + pdfopt prelinkin.pdf $@ + rm prelinkin.pdf + +prelink.ps: prelink.dvi + dvips $< -o $@ + +prelink.dvi: prelink.tex $(pics:=.eps) + $(LATEXINPUTS) latex $< + if grep -q Rerun prelink.log; then $(LATEXINPUTS) latex $<; fi + +.fig.eps: + fig2dev -L eps $^ $@ + +.fig.pdf: + fig2dev -L pdf $^ $@ +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/doc/basemove.fig b/trunk/doc/basemove.fig new file mode 100644 index 0000000..6fb1c02 --- /dev/null +++ b/trunk/doc/basemove.fig @@ -0,0 +1,97 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 5925 2775 10275 3525 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 2850 7200 2850 7200 3450 6000 3450 6000 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10200 2850 8025 2850 8025 3450 10200 3450 10200 2850 +4 0 0 50 0 0 12 0.0000 4 180 1125 6000 3225 .hash, .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 8100 3225 .gnu.version ... .eh_frame\001 +-6 +6 5925 1125 10275 1875 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 1200 7200 1200 7200 1800 6000 1800 6000 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10200 1200 8025 1200 8025 1800 10200 1800 10200 1200 +4 0 0 50 0 0 12 0.0000 4 180 1125 6000 1575 .hash, .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 8100 1575 .gnu.version ... .eh_frame\001 +-6 +6 525 2775 2400 3525 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2325 2850 2325 3450 600 3450 600 2850 +4 0 0 50 0 0 12 0.0000 4 180 1605 675 3225 .interp, .note.ABI-tag\001 +-6 +6 4200 1125 6075 1875 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4275 1200 6000 1200 6000 1800 4275 1800 4275 1200 +4 0 0 50 0 0 12 0.0000 4 180 1605 4350 1575 .interp, .note.ABI-tag\001 +-6 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 2325 2850 3300 2850 3300 3450 2325 3450 2325 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4125 2850 3300 2850 3300 3450 4125 3450 4125 2850 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 4125 2850 5100 2850 5100 3450 4125 3450 4125 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 10200 2700 10200 3600 450 3600 450 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10800 2850 11925 2850 11925 3450 10800 3450 10800 2850 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 11925 2700 11925 3600 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 11925 2850 12525 2850 12525 3450 11925 3450 11925 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 10800 1200 11925 1200 11925 1800 10800 1800 10800 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 10800 975 12525 975 12525 1950 10800 1950 10800 975 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 11925 975 11925 1950 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 11925 1200 12525 1200 12525 1800 11925 1800 11925 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 10800 2700 12525 2700 12525 3600 10800 3600 10800 2700 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 7200 1200 8025 1200 8025 1800 7200 1800 7200 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 10200 2700 10200 3600 450 3600 450 2700 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 4125 975 10200 975 10200 1950 4125 1950 4125 975 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5025 1950 1350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6600 1950 6600 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 9000 1950 9000 2025 9000 2100 9000 2175 9000 2250 9000 2325 + 9000 2400 9000 2475 9000 2550 9000 2625 9000 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 12 + 0 0 1.00 60.00 120.00 + 11400 1950 11400 2025 11400 2100 11400 2175 11400 2250 11400 2325 + 11400 2400 11400 2475 11400 2550 11400 2625 11400 2700 11400 2625 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 12225 1950 12225 2025 12225 2100 12225 2175 12225 2250 12225 2325 + 12225 2400 12225 2475 12225 2550 12225 2625 12225 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 8025 1950 3300 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7200 1950 2325 2700 +4 0 0 50 0 0 12 0.0000 4 180 780 3300 3225 .gnu.liblist\001 +4 0 0 50 0 0 12 0.0000 4 180 930 4125 3225 .gnu.conflict\001 +4 0 0 50 0 0 12 0.0000 4 180 885 10950 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 12000 3225 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 885 10950 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 12000 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 525 7275 1575 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 525 2475 3225 .dynstr\001 diff --git a/trunk/doc/bss.fig b/trunk/doc/bss.fig new file mode 100644 index 0000000..2c9325f --- /dev/null +++ b/trunk/doc/bss.fig @@ -0,0 +1,74 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2175 1200 2175 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3225 1200 2175 1200 2175 1800 3225 1800 3225 1200 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1425 1950 1425 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2175 2850 2175 3450 600 3450 600 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3000 2850 2175 2850 2175 3450 3000 3450 3000 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 5400 2700 5400 3600 450 3600 450 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5400 2850 3225 2850 3225 3450 5400 3450 5400 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 5400 975 5400 1950 450 1950 450 975 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5400 1200 3225 1200 3225 1800 5400 1800 5400 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 1200 7125 1200 7125 1800 6000 1800 6000 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 2850 7125 2850 7125 3450 6000 3450 6000 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 975 7725 975 7725 1950 6000 1950 6000 975 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6525 1950 6525 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7350 1950 7350 2700 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7125 975 7125 1950 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 8925 2850 7725 2850 7725 3450 8925 3450 8925 2850 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 8925 2850 10050 2850 10050 3450 8925 3450 8925 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 2700 10050 2700 10050 3600 6000 3600 6000 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2175 1950 7725 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3225 1950 8925 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 3975 1950 3975 2025 3975 2100 3975 2175 3975 2250 3975 2325 + 3975 2400 3975 2475 3975 2550 3975 2625 3975 2700 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 7125 2850 7725 2850 7725 3450 7125 3450 7125 2850 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7125 1200 7725 1200 7725 1800 7125 1800 7125 1200 +4 0 0 50 0 0 12 0.0000 4 180 1335 750 1575 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 525 2325 1575 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 1335 750 3225 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 780 2175 3225 .gnu.liblist\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 3300 3225 .gnu.version ... .eh_frame\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 3300 1575 .gnu.version ... .eh_frame\001 +4 0 0 50 0 0 12 0.0000 4 180 885 6150 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 180 885 6150 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7200 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7275 3225 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 525 7950 3225 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 930 9000 3225 .gnu.conflict\001 diff --git a/trunk/doc/dso1.fig b/trunk/doc/dso1.fig new file mode 100644 index 0000000..0bd75f3 --- /dev/null +++ b/trunk/doc/dso1.fig @@ -0,0 +1,81 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 6375 2625 8250 3675 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6450 2850 7575 2850 7575 3450 6450 3450 6450 2850 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7575 2700 7575 3600 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7575 2850 8175 2850 8175 3450 7575 3450 7575 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6450 2700 8175 2700 8175 3600 6450 3600 6450 2700 +4 0 0 50 0 0 12 0.0000 4 180 885 6600 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7650 3225 .bss\001 +-6 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 4950 975 4950 1950 450 1950 450 975 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2100 1200 2100 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4950 1200 2775 1200 2775 1800 4950 1800 4950 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2100 2850 2100 3450 600 3450 600 2850 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 2100 1200 2775 1200 2775 1800 2100 1800 2100 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 2850 3075 2850 3075 3450 2100 3450 2100 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5250 2850 3075 2850 3075 3450 5250 3450 5250 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 5250 2700 5250 3600 450 3600 450 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6150 1200 7275 1200 7275 1800 6150 1800 6150 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6150 975 7875 975 7875 1950 6150 1950 6150 975 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7275 975 7275 1950 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7275 1200 7875 1200 7875 1800 7275 1800 7275 1200 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 4800 675 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 4800 750 4800 3825 +2 1 5 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 6000 675 6000 3750 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1350 1950 1350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2100 1950 2100 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2775 1950 3075 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 3375 1950 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3375 1950 3675 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7050 1950 7350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7575 1950 7875 2700 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 1575 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 1575 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 2850 1575 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 3225 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 3225 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 3225 3225 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 885 6300 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7350 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 3675 2475 page boundary\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 6075 2475 page boundary\001 diff --git a/trunk/doc/dso2.fig b/trunk/doc/dso2.fig new file mode 100644 index 0000000..73d0a14 --- /dev/null +++ b/trunk/doc/dso2.fig @@ -0,0 +1,81 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 6225 2625 8100 3675 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6300 2850 7425 2850 7425 3450 6300 3450 6300 2850 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7425 2700 7425 3600 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7425 2850 8025 2850 8025 3450 7425 3450 7425 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6300 2700 8025 2700 8025 3600 6300 3600 6300 2700 +4 0 0 50 0 0 12 0.0000 4 180 885 6450 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7500 3225 .bss\001 +-6 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 4950 975 4950 1950 450 1950 450 975 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2100 1200 2100 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4950 1200 2775 1200 2775 1800 4950 1800 4950 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2100 2850 2100 3450 600 3450 600 2850 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 2100 1200 2775 1200 2775 1800 2100 1800 2100 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 2850 3075 2850 3075 3450 2100 3450 2100 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5250 2850 3075 2850 3075 3450 5250 3450 5250 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 5250 2700 5250 3600 450 3600 450 2700 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 4800 675 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 4800 750 4800 3825 +2 1 5 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 6000 675 6000 3750 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1350 1950 1350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2100 1950 2100 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2775 1950 3075 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 3375 1950 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3375 1950 3675 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 1200 7125 1200 7125 1800 6000 1800 6000 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 975 7725 975 7725 1950 6000 1950 6000 975 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7125 975 7125 1950 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7125 1200 7725 1200 7725 1800 7125 1800 7125 1200 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6900 1950 7200 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 7425 1950 7725 2700 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 1575 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 1575 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 2850 1575 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 3225 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 3225 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 3225 3225 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 3675 2475 page boundary\001 +4 0 0 50 0 0 12 0.0000 4 180 885 6150 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7200 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 6075 2475 page boundary\001 diff --git a/trunk/doc/dso3.fig b/trunk/doc/dso3.fig new file mode 100644 index 0000000..ffdb9de --- /dev/null +++ b/trunk/doc/dso3.fig @@ -0,0 +1,110 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 375 4125 6900 5175 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 4350 2100 4350 2100 4950 600 4950 600 4350 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 4350 3075 4350 3075 4950 2100 4950 2100 4350 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4950 4350 3075 4350 3075 4950 4950 4950 4950 4350 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 4200 4950 4200 4950 5100 450 5100 450 4200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5100 4350 6225 4350 6225 4950 5100 4950 5100 4350 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 6225 4350 6825 4350 6825 4950 6225 4950 6225 4350 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 5100 4200 6825 4200 6825 5100 5100 5100 5100 4200 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 6225 4200 6225 5100 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 4725 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 4725 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 3150 4725 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 885 5250 4724 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 6300 4724 .bss\001 +-6 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2100 1200 2100 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 2100 1200 2775 1200 2775 1800 2100 1800 2100 1200 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 4800 675 +2 1 5 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 6000 675 6000 5250 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1350 1950 1350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2100 1950 2100 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2775 1950 3075 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 0 0 1 + 3375 1950 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3375 1950 4500 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5400 1950 6600 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 6300 1950 7500 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4650 1200 2775 1200 2775 1800 4650 1800 4650 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 4650 975 4650 1950 450 1950 450 975 +2 1 4 1 0 7 50 0 -1 4.000 0 0 -1 0 0 2 + 4800 750 4800 5250 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4800 1200 5925 1200 5925 1800 4800 1800 4800 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 4800 975 6525 975 6525 1950 4800 1950 4800 975 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 5925 975 5925 1950 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 5925 1200 6525 1200 6525 1800 5925 1800 5925 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2100 2850 2100 3450 600 3450 600 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 2100 2850 3075 2850 3075 3450 2100 3450 2100 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5850 2850 3975 2850 3975 3450 5850 3450 5850 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 5850 2700 5850 3600 450 3600 450 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 6000 2850 7125 2850 7125 3450 6000 3450 6000 2850 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 7125 2850 7725 2850 7725 3450 7125 3450 7125 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 6000 2700 7725 2700 7725 3600 6000 3600 6000 2700 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 7125 2700 7125 3600 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5475 5400 5475 5175 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 5475 5400 4950 5250 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 1575 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 1575 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 2850 1575 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 3675 2475 page boundary\001 +4 0 0 50 0 0 12 0.0000 4 180 1095 6075 2475 page boundary\001 +4 0 0 50 0 0 12 0.0000 4 180 885 4950 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 6000 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 1155 675 3225 .hash ... .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 555 2175 3225 .rel.dyn\001 +4 0 0 50 0 0 12 0.0000 4 180 1440 4050 3225 .text ... ro_seg_end\001 +4 0 0 50 0 0 12 0.0000 4 180 885 6150 3224 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 7200 3224 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 3450 3675 5550 This page needs to be mapped from 2 sources\001 +4 0 0 50 0 0 12 0.0000 4 135 645 1125 4050 And not:\001 diff --git a/trunk/doc/execstack.8 b/trunk/doc/execstack.8 new file mode 100644 index 0000000..e0e95fa --- /dev/null +++ b/trunk/doc/execstack.8 @@ -0,0 +1,92 @@ +.TH execstack 8 "28 October 2003" +.SH NAME +execstack \- tool to set, clear, or query executable stack flag of ELF binaries and shared libraries +.SH SYNOPSIS +execstack +.RB [OPTION...]\ [FILES] +.SH DESCRIPTION +.B execstack +is a program which sets, clears, or queries executable stack flag of ELF +binaries and shared libraries. Linux has in the past allowed execution +of instructions on the stack and there are lots of binaries and shared +libraries assuming this behaviour. Furthermore, GCC trampoline code +for e.g. nested functions requires executable stack on many architectures. +To avoid breaking binaries and shared libraries which need executable stack, +ELF binaries and shared libraries now can be marked as requiring executable +stack or not requiring it. This marking is done through the p_flags field +in the PT_GNU_STACK program header entry. If the marking is missing, kernel +or dynamic linker need to assume it might need executable stack. +The marking is done automatically by recent GCC versions (objects using +trampolines on the stack are marked as requiring executable stack, +all other newly built objects are marked as not requiring it) and +linker collects these markings into marking of the whole binary +or shared library. The user can override this at assembly time +(through +.B \-\-execstack +or +.B \-\-noexecstack +assembler options), at link time (through +.B \-z execstack +or +.B \-z noexecstack +linker options) and using the +.B execstack +tool also on an already linker binary or shared library. +This tool is especially useful for third party shared libraries +where it is known that they don't need executable stack or testing proves +it. +.SH OPTIONS +.TP +.B \-s \-\-set\-execstack +Mark binary or shared library as requiring executable stack. +.TP +.B \-c \-\-clear\-execstack +Mark binary or shared library as not requiring executable stack. +.TP +.B \-q \-\-query +Query executable stack marking of binaries and shared libraries. +For each file it prints either +.B \- +when executable stack is not required, +.B X +when executable stack is required or +.B ? +when it is unknown whether the object requires or doesn't require +executable stack (the marking is missing). +.TP +.B \-V +Print +.B execstack +version and exit. +.TP +.B \-? \-\-help +Print help message. +.TP +.B \-\-usage +Print a short usage message. +.SH ARGUMENTS +Command line arguments should be names of ELF binaries and shared libraries +which should be modified or queried. +.SH EXAMPLES +.RS +# execstack -s ~/lib/libfoo.so.1 +.RE +will mark ~/lib/libfoo.so.1 as requiring executable stack. +.RS +# execstack -c ~/bin/bar +.RE +will mark ~/bin/bar as not requiring executable stack. +.RS +# execstack -q ~/lib/libfoo.so.1 ~/bin/bar +.RE +will query executable stack marking of the given files. +.SH SEE ALSO +.BR ld.so (8). +.SH BUGS +.LP +.B execstack +doesn't support yet marking of executables if they do not have +PT_GNU_STACK program header entry nor they have room for program segment +header table growth. +.SH AUTHORS +Jakub Jelinek <jakub@redhat.com>. diff --git a/trunk/doc/gap.fig b/trunk/doc/gap.fig new file mode 100644 index 0000000..ced67c9 --- /dev/null +++ b/trunk/doc/gap.fig @@ -0,0 +1,87 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2175 1200 2175 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4425 1200 3225 1200 3225 1800 4425 1800 4425 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3225 1200 2175 1200 2175 1800 3225 1800 3225 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 9225 975 9225 1950 450 1950 450 975 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9225 1200 7425 1200 7425 1800 9225 1800 9225 1200 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1425 1950 1425 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2175 1950 4425 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3225 1950 5700 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 3750 1950 3750 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 8250 1950 8250 2025 8250 2100 8250 2175 8250 2250 8250 2325 + 8250 2400 8250 2475 8250 2550 8250 2625 8250 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 2850 2175 2850 2175 3450 600 3450 600 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 3000 2850 2175 2850 2175 3450 3000 3450 3000 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4425 2850 3225 2850 3225 3450 4425 3450 4425 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5700 2850 4425 2850 4425 3450 5700 3450 5700 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5700 2850 6900 2850 6900 3450 5700 3450 5700 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 7425 2850 9225 2850 9225 3450 7425 3450 7425 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 9225 2700 9225 3600 450 3600 450 2700 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 1200 10950 1200 10950 1800 9825 1800 9825 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 2850 10950 2850 10950 3450 9825 3450 9825 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 9825 975 11550 975 11550 1950 9825 1950 9825 975 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 9825 2700 11550 2700 11550 3600 9825 3600 9825 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 10350 1950 10350 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 11175 1950 11175 2700 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 10950 975 10950 1950 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 13 + 10950 2700 10950 2775 10950 2850 10950 2925 10950 3000 10950 3075 + 10950 3150 10950 3225 10950 3300 10950 3375 10950 3450 10950 3525 + 10950 3600 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 10950 1200 11550 1200 11550 1800 10950 1800 10950 1200 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 10950 2850 11550 2850 11550 3450 10950 3450 10950 2850 +4 0 0 50 0 0 12 0.0000 4 180 1335 750 1575 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 525 2325 1575 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 1005 3300 1575 .gnu.version*\001 +4 0 0 50 0 0 12 0.0000 4 180 1530 7575 1575 .rel.dyn ... .eh_frame\001 +4 0 0 50 0 0 12 0.0000 4 180 1335 750 3225 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 780 2175 3225 .gnu.liblist\001 +4 0 0 50 0 0 12 0.0000 4 180 1005 3300 3225 .gnu.version*\001 +4 0 0 50 0 0 12 0.0000 4 180 525 4575 3225 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 930 5775 3225 .gnu.conflict\001 +4 0 0 50 0 0 12 0.0000 4 180 1530 7575 3225 .rel.dyn ... .eh_frame\001 +4 0 0 50 0 0 12 0.0000 4 180 885 9975 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 180 885 9975 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 11025 1575 .bss\001 +4 0 0 50 0 0 12 0.0000 4 135 315 11100 3225 .bss\001 diff --git a/trunk/doc/glossary.conf b/trunk/doc/glossary.conf new file mode 100644 index 0000000..477b529 --- /dev/null +++ b/trunk/doc/glossary.conf @@ -0,0 +1,3 @@ +keyword "\\glossaryentry" +preamble "\n \\begin{theglossary}\n" +postamble "\n\n \\end{theglossary}\n" diff --git a/trunk/doc/lineno.sty b/trunk/doc/lineno.sty new file mode 100644 index 0000000..0805bcc --- /dev/null +++ b/trunk/doc/lineno.sty @@ -0,0 +1,1521 @@ +\iffalse; awk '/S[H]ELL/' lineno.sty|sh;exit;\fi +%%% To pretty-print this file, feed it to a unix shell! +%%% +%%% $Id: lineno.sty,v 3.12 2003/01/14 21:11:53 stephan Exp $ +%%% +%%% Copyright 1995--2001 Stephan I. B"ottcher <stephan@nevis.columbia.edu> +%%% +%%% This program can be redistributed and/or modified under the terms +%%% of the LaTeX Project Public License Distributed from CTAN +%%% archives in directory macros/latex/base/lppl.txt; either +%%% version 1 of the License, or any later version. +%%% +% \documentclass[a4paper,12pt]{article}%D +% \usepackage{lineno}%D +% +% \title{ +% \texttt{\itshape +% lineno.sty \ v3.09 2003/01/14 +% }\\\ \\ +% A \LaTeX\ package to attach +% \\ Line numbers to paragraphs +% }\author{ +% Stephan I. B\"ottcher +% }\date{ +% boettcher@physik.uni-kiel.de +%% \\ stephan@nevis.columbia.edu +%% \\ Stephan.Boettcher@cern.ch +% \\} +% +% +% \def~{\verb~} +% \catcode`\<\catcode`\~ +% \def<#1>{$\langle${\itshape#1}\/$\rangle$} +% \catcode`\|\catcode`\~ +% \def|#1{{\ttfamily\string#1}} +% \newenvironment{code} +% {\par\runninglinenumbers +% \modulolinenumbers[1] +% \linenumbersep.3em +% \footnotesize +% \def\linenumberfont +% {\normalfont\tiny\itshape}} +% {} +% +% \begin{document}%D +%% \DocInput{lineno.doc}%D +% \pagewiselinenumbers +% \maketitle +% \tableofcontents +% \sloppy +% +% +% +% \section{ +% Introduction +% } +% This package provides line numbers on paragraphs. +% After \TeX\ has broken a paragraph into lines there will +% be line numbers attached to them, with the possibility to +% make references through the \LaTeX\ ~\ref~, ~\pageref~ +% cross reference mechanism. This includes four issues: +% \begin{itemize} +% \item attach a line number on each line, +% \item create references to a line number, +% \item control line numbering mode, +% \item count the lines and print the numbers. +% \end{itemize} +% The first two points are implemented through patches to +% the output routine. The third by redefining ~\par~, ~\@par~ +% and ~\@@par~. The counting is easy, as long as you want +% the line numbers run through the text. If they shall +% start over at the top of each page, the aux-file as well +% as \TeX s memory have to carry a load for each counted line. +% +% I wrote this package for my wife Petra, who needs it for +% transcriptions of interviews. This allows her to +% precisely refer to passages in the text. It works well +% together with ~\marginpar~s, but not to well with displaymath. +% ~\footnote~s are a problem, especially when they +% are split, but we may get there. +% +% lineno.sty works +% surprisingly well with other packages, for +% example, ~wrapfig.sty~. So please try if it +% works with whatever you need, and if it does, +% please tell me, and if it does not, tell me as +% well, so I can try to fix it. +% +% This style option is written for \LaTeXe, later than November 1994, +% since we need the ~\protected@write~ macro. + +\NeedsTeXFormat{LaTeX2e}[1994/11/04] +\ProvidesPackage{lineno} + [2003/01/14 line numbers on paragraphs v3.09] + +%% v1.00 1995/03/31 SIB: first release for Petras interview transcriptions +%% v1.01 1995/10/28 SIB: added ~pagewise~ mode +%% v1.02 1995/11/15 SIB: added ~modulo~ option +%% v1.03 1995/12/05 SIB: pagewise: try to reduce the hash-size requirements +%% v2.00 1995/12/06 SIB: .. it works, new user interface +%% v2.01 1996/09/17 SIB: put into CVS +%% v2.02 1997/03/17 SIB: add: \@reinserts, for footnotes +%% v2.04 1998/03/09 SIB: add: linenomath environment +%% v2.05 1998/04/26 SIB: add: prevgraf test +%% v2.06 1999/03/02 SIB: LPPL added +%% v3.00 1999/06/11 SiB: include the extension in the main file +%% v3.01 1999/08/28 SiB: \@reinserts -> \holdinginserts +%% v3.02 2000/03/10 SiB: \@LN@output +%% v3.03 2000/07/01 SiB: \@LN@ExtraLabelItems, hyperref +%% v3.04 2000/12/17 SiB: longtable compatibility. +%% v3.05 2001/01/02 SiB: [fleqn] detection. +%% v3.05a 2001/01/04 SiB: [fleqn] detection reverted for eqnarray. +%% v3.06 2001/01/17 SiB: [twocolumn] mode support. +%% v3.07 2001/07/30 SiB: [hyperref] option obsoleted. +%% v3.08 2001/08/02 SiB: linenomath wrapping for \[ \] +%% v3.08a 2001/08/04 SiB: linenomath wrapping for \[ \] fixed +%% v3.08b 2002/01/27 SiB: enquotation typo fix +%% v3.09 2003/01/14 SIB: hyperref detection fix +%% +%% Acknowledgements: +%% v3.06: Donald Arseneau, pointed to mparhack.sty. +%% v3.07+: Frank Mittelbach, points out inconsistencies in the +%% user interface. +% +% \section{ +% Put the line numbers to the lines +% } +% The line numbers have to be attached by the output +% routine. We simply set the ~\interlinepenalty~ to -100000. +% The output routine will be called after each line in the +% paragraph, except the last, where we trigger by ~\par~. +% The ~\linenopenalty~ is small enough to compensate a bunch of +% penalties (e.g., with ~\samepage~). +% +% (New v3.04) Longtable uses +% ~\penaly~-30000. The lineno penalty range was +% shrunk to $-188000 \dots -32000$. (/New v3.04) + +\newcount\linenopenalty\linenopenalty=-100000 +\mathchardef\linenopenaltypar=32000 + +% So let's make a hook to ~\output~, the direct way. The \LaTeX\ +% macro ~\@reinserts~ puts the footnotes back on the page. +% +% (New v3.01) ~\@reinserts~ badly +% screws up split footnotes. The bottom part is +% still on the recent contributions list, and the +% top part will be put back there after the bottom +% part. Thus, since lineno.sty does not play well +% with ~\inserts~ anyway, we can safely experiment +% with ~\holdinginserts~, without making things +% much worse. +% +% Or that's what I thought, but: Just activating +% ~\holdinginserts~ while doing the ~\par~ will +% not do the trick: The ~\output~ routine may be +% called for a real page break before all line +% numbers are done, and how can we get control +% over ~\holdinginserts~ at that point? +% +% Let's try this: When the ~\output~ routine is +% run with ~\holdinginserts=3~ for a real page +% break, then we reset ~\holdinginserts~ and +% restart ~\output~. +% +% Then, again, how do we keep the remaining +% ~\inserts~ while doing further line numbers? +% +% If we find ~\holdinginserts~=-3 we activate it again +% after doing ~\output~. (/New v3.01) +% +% (New v3.02) To work with +% multicol.sty, the original output routine is now +% called indirectly, instead of being replaced. +% When multicol.sty changes ~\output~, it is a +% toks register, not the real thing. (/New v3.02) + +\let\@LN@output\output +\newtoks\output +\output=\expandafter{\the\@LN@output} +\@LN@output={% + \LineNoTest + \if@tempswa + \LineNoHoldInsertsTest + \if@tempswa + \if@twocolumn\let\@makecol\@LN@makecol\fi + \the\output + \ifnum\holdinginserts=-3 + \global\holdinginserts 3 + \fi + \else + \global\holdinginserts-3 + \unvbox\@cclv + \ifnum\outputpenalty=10000\else + \penalty\outputpenalty + \fi + \fi + \else + \MakeLineNo + \fi + } + +% The float mechanism inserts ~\interlinepenalty~s during +% ~\output~. So carefully reset it before going on. Else +% we get doubled line numbers on every float placed in +% horizontal mode, e.g, from ~\linelabel~. +% +% Sorry, neither a ~\linelabel~ nor a ~\marginpar~ should +% insert a penalty, else the following linenumber +% could go to the next page. Nor should any other +% float. So let us suppress the ~\interlinepenalty~ +% altogether with the ~\@nobreak~ switch. +% +% Since (ltspace.dtx, v1.2p)[1996/07/26], the ~\@nobreaktrue~ does +% it's job globally. We need to do it locally here. + +\def\LineNoTest{% + \let\@@par\@@@par + \ifnum\interlinepenalty<-\linenopenaltypar + \advance\interlinepenalty-\linenopenalty + \my@nobreaktrue + \fi + \@tempswatrue + \ifnum\outputpenalty>-\linenopenaltypar\else + \ifnum\outputpenalty>-188000\relax + \@tempswafalse + \fi + \fi + } + +\def\my@nobreaktrue{\let\if@nobreak\iftrue} + +\def\LineNoHoldInsertsTest{% + \ifnum\holdinginserts=3\relax + \@tempswafalse + \fi + } + +% We have to return all the page to the current page, and +% add a box with the line number, without adding +% breakpoints, glue or space. The depth of our line number +% should be equal to the previous depth of the page, in +% case the page breaks here, and the box has to be moved up +% by that depth. +% +% The ~\interlinepenalty~ comes after the ~\vadjust~ from a +% ~\linelabel~, so we increment the line number \emph{after} +% printing it. The macro ~\makeLineNumber~ produces the +% text of the line number, see section \ref{appearance}. +% +% Finally we put in the natural ~\interlinepenalty~, except +% after the last line. + +\def\MakeLineNo{\@tempdima\dp\@cclv \unvbox\@cclv + \sbox\@tempboxa{\hbox to\z@{\makeLineNumber}}% + \stepcounter{linenumber}% + \dp\@tempboxa=\@tempdima\ht\@tempboxa=\z@ + \nointerlineskip\kern-\@tempdima\box\@tempboxa + \ifnum\outputpenalty=-\linenopenaltypar\else + \@tempcnta\outputpenalty + \advance\@tempcnta -\linenopenalty + \penalty\@tempcnta + \fi + } + +% +% +% \section{ +% Control line numbering +% } +% The line numbering is controlled via ~\par~. \LaTeX\ +% saved the \TeX-primitive ~\par~ in ~\@@par~. We push it +% one level further out, and redefine ~\@@par~ to insert +% the ~\interlinepenalty~ needed to trigger the +% line numbering. And we need to allow pagebreaks after a +% paragraph. +% +% New (2.05beta): the prevgraf test. A paragraph that ends with a +% displayed equation, a ~\noindent\par~ or ~wrapfig.sty~ produce empty +% paragraphs. These should not get a spurious line number via +% ~\linenopenaltypar~. + +\let\@@@par\@@par +\newcount\linenoprevgraf + +\def\linenumberpar{\ifvmode\@@@par\else\ifinner\@@@par\else + \advance\interlinepenalty \linenopenalty + \linenoprevgraf\prevgraf + \global\holdinginserts3% + \@@@par + \ifnum\prevgraf>\linenoprevgraf + \penalty-\linenopenaltypar + \fi + \kern\z@ + \global\holdinginserts0% + \advance\interlinepenalty -\linenopenalty + \fi\fi + } + +% The basic commands to enable and disable line numbers. +% ~\@par~ and ~\par~ are only touched, when they are ~\let~ +% to ~\@@@par~/~\linenumberpar~. The line number may be +% reset to 1 with the star-form, or set by an optional +% argument ~[~<number>~]~. + +\def\linenumbers{\let\@@par\linenumberpar + \ifx\@par\@@@par\let\@par\linenumberpar\fi + \ifx\par\@@@par\let\par\linenumberpar\fi + \@ifnextchar[{\resetlinenumber}%] + {\@ifstar{\resetlinenumber}{}}% + } + +\def\nolinenumbers{\let\@@par\@@@par + \ifx\@par\linenumberpar\let\@par\@@@par\fi + \ifx\par\linenumberpar\let\par\@@@par\fi + } + +% What happens with a display math? Since ~\par~ is not executed, +% when breaking the lines before a display, they will not get +% line numbers. Sorry, but I do not dare to change +% ~\interlinepenalty~ globally, nor do I want to redefine +% the display math environments here. +% \begin{displaymath} +% display \ math +% \end{displaymath} +% See the subsection below, for a wrapper enviroment to make +% it work. But that requires to wrap each and every display +% in your LaTeX source. +% +% The next two commands are provided to turn on line +% numbering in a specific mode. Please note the difference: +% for pagewise numbering, ~\linenumbers~ comes first to +% inhibit it from seeing optional arguments, since +% re-/presetting the counter is useless. + +\def\pagewiselinenumbers{\linenumbers\setpagewiselinenumbers} +\def\runninglinenumbers{\setrunninglinenumbers\linenumbers} + +% Finally, it is a \LaTeX\ style, so we provide for the use +% of environments, including the suppression of the +% following paragraph's indentation. + +%%% TO DO: add \par to \linenumbers, if called from an environment. +%%% To DO: add an \@endpe hack if \linenumbers are turned on +%%% in horizontal mode. {\par\parskip\z@\noindent} or +%%% something. + +\@namedef{linenumbers*}{\par\linenumbers*} +\@namedef{runninglinenumbers*}{\par\runninglinenumbers*} + +\def\endlinenumbers{\par\@endpetrue} +\let\endrunninglinenumbers\endlinenumbers +\let\endpagewiselinenumbers\endlinenumbers +\expandafter\let\csname endlinenumbers*\endcsname\endlinenumbers +\expandafter\let\csname endrunninglinenumbers*\endcsname\endlinenumbers +\let\endnolinenumbers\endlinenumbers + +% +% \subsection{ +% Display math +% } +% +% Now we tackle the problem to get display math working. +% There are different options. +% \begin{enumerate}\item[ +% 1.] Precede every display math with a ~\par~. +% Not too good. +% \item[ +% 2.] Change ~\interlinepenalty~ and associates globally. +% Unstable. +% \item[ +% 3.] Wrap each display math with a ~{linenomath}~ +% environment. +% \end{enumerate} +% We'll go for option 3. See if it works: +% \begin{linenomath} +% \begin{equation} +% display \ math +% \end{equation} +% \end{linenomath} +% The star form ~{linenomath*}~ should also number the lines +% of the display itself, +% \begin{linenomath*} +% \begin{eqnarray} +% multi && line \\ +% display && math \\ +% & +% \begin{array}{c} +% with \\ +% array +% \end{array} +% & +% \end{eqnarray} +% \end{linenomath*} +% including multline displays. +% +% First, here are two macros to turn +% on linenumbering on paragraphs preceeding displays, with +% numbering the lines of the display itself, or without. +% The ~\ifx..~ tests if line numbering is turned on. It +% does not harm to add these wrappers in sections that are +% not numbered. Nor does it harm to wrap a display +% twice, e.q, in case you have some ~{equation}~s wrapped +% explicitely, and later you redefine ~\equation~ to do it +% automatically. + +\newcommand\linenomathNonumbers{% + \ifx\@@par\@@@par\else + \ifnum\interlinepenalty>-\linenopenaltypar + \global\holdinginserts3% + \advance\interlinepenalty \linenopenalty + \advance\predisplaypenalty \linenopenalty + \fi + \fi + \ignorespaces + } + +\newcommand\linenomathWithnumbers{% + \ifx\@@par\@@@par\else + \ifnum\interlinepenalty>-\linenopenaltypar + \global\holdinginserts3% + \advance\interlinepenalty \linenopenalty + \advance\predisplaypenalty \linenopenalty + \advance\postdisplaypenalty \linenopenalty + \advance\interdisplaylinepenalty \linenopenalty + \fi + \fi + \ignorespaces + } + +% The ~{linenomath}~ environment has two forms, with and +% without a star. The following two macros define the +% environment, where the stared/non-stared form does/doesn't number the +% lines of the display or vice versa. + +\newcommand\linenumberdisplaymath{% + \def\linenomath{\linenomathWithnumbers}% + \@namedef{linenomath*}{\linenomathNonumbers}% + } + +\newcommand\nolinenumberdisplaymath{% + \def\linenomath{\linenomathNonumbers}% + \@namedef{linenomath*}{\linenomathWithnumbers}% + } + +\def\endlinenomath{% + \global\holdinginserts0 + \@ignoretrue +} +\expandafter\let\csname endlinenomath*\endcsname\endlinenomath + +% The default is not to number the lines of a display. But +% the package option ~mathlines~ may be used to switch +% that behavior. + +\nolinenumberdisplaymath + +% +% +% \section{ +% Line number references +% } +% The only way to get a label to a line number in a +% paragraph is to ask the output routine to mark it. +% +% We use the marginpar mechanism to hook to ~\output~ for a +% second time. Marginpars are floats with number $-1$, we +% fake marginpars with No $-2$. Originally, every negative +% numbered float was considered to be a marginpar. +% +% The float box number ~\@currbox~ is used to transfer the +% label name in a macro called ~\@LNL@~<box-number>. +% +% A ~\newlabel~ is written to the aux-file. The reference +% is to ~\theLineNumber~, \emph{not} ~\thelinenumber~. +% This allows to hook in, as done below for pagewise line +% numbering. +% +% (New v3.03) The ~\@LN@ExtraLabelItems~ are added for a hook +% to keep packages like ~{hyperref}~ happy. (/New v3.03) + +\let\@LN@addmarginpar\@addmarginpar +\def\@addmarginpar{% + \ifnum\count\@currbox>-2\relax + \expandafter\@LN@addmarginpar + \else + \@cons\@freelist\@currbox + \protected@write\@auxout{}{% + \string\newlabel + {\csname @LNL@\the\@currbox\endcsname}% + {{\theLineNumber}{\thepage}\@LN@ExtraLabelItems}}% + \fi} + +\let\@LN@ExtraLabelItems\@empty + +% \subsection{ +% The linelabel command +% } +% To refer to a place in line ~\ref{~<foo>~}~ at page +% ~\pageref{~<foo>~}~ you place a ~\linelabel{~<foo>~}~ at +% that place. +% +% \linelabel{demo} +% \marginpar{\tiny\raggedright +% See if it works: This paragraph +% starts on page \pageref{demo}, line +% \ref{demo}. +% }% +% If you use this command outside a ~\linenumbers~ +% paragraph, you will get references to some bogus +% line numbers, sorry. But we don't disable the command, +% because only the ~\par~ at the end of a paragraph may +% decides whether to print line numbers on this paragraph +% or not. A ~\linelabel~ may legally appear earlier than +% ~\linenumbers~. +% +% ~\linelabel~, via a fake float number $-2$, puts a +% ~\penalty~ into a ~\vadjust~, which triggers the +% pagebuilder after putting the current line to the main +% vertical list. A ~\write~ is placed on the main vertical +% list, which prints a reference to the current value of +% ~\thelinenumber~ and ~\thepage~ at the time of the +% ~\shipout~. +% +% A ~\linelabel~ is allowed only in outer horizontal mode. +% In outer vertical mode we start a paragraph, and ignore +% trailing spaces (by fooling ~\@esphack~). +% +% The argument of ~\linelabel~ is put into a macro with a +% name derived from the number of the allocated float box. +% Much of the rest is dummy float setup. + +\def\linelabel#1{% + \ifvmode + \ifinner \else + \leavevmode \@bsphack \@savsk\p@ + \fi + \else + \@bsphack + \fi + \ifhmode + \ifinner + \@parmoderr + \else + \@floatpenalty -\@Mii + \@next\@currbox\@freelist + {\global\count\@currbox-2% + \expandafter\gdef\csname @LNL@\the\@currbox\endcsname{#1}}% + {\@floatpenalty\z@ \@fltovf \def\@currbox{\@tempboxa}}% + \begingroup + \setbox\@currbox \color@vbox \vbox \bgroup \end@float + \endgroup + \@ignorefalse \@esphack + \fi + \else + \@parmoderr + \fi + } + +% \modulolinenumbers[3] +% \section{ +% The appearance of the line numbers +% }\label{appearance} +% The line numbers are set as ~\tiny\sffamily\arabic{linenumber}~, +% $10pt$ left of the text. With options to place it +% right of the text, or . . . +% +% . . . here are the hooks: + +\def\makeLineNumberLeft{\hss\linenumberfont\LineNumber\hskip\linenumbersep} + +\def\makeLineNumberRight{\linenumberfont\hskip\linenumbersep\hskip\columnwidth + \hbox to\linenumberwidth{\hss\LineNumber}\hss} + +\def\linenumberfont{\normalfont\tiny\sffamily} + +\newdimen\linenumbersep +\newdimen\linenumberwidth + +\linenumberwidth=10pt +\linenumbersep=10pt + +% Margin switching requires ~pagewise~ numbering mode, but +% choosing the left or right margin for the numbers always +% works. + +\def\switchlinenumbers{\@ifstar + {\let\makeLineNumberOdd\makeLineNumberRight + \let\makeLineNumberEven\makeLineNumberLeft}% + {\let\makeLineNumberOdd\makeLineNumberLeft + \let\makeLineNumberEven\makeLineNumberRight}% + } + +\def\setmakelinenumbers#1{\@ifstar + {\let\makeLineNumberRunning#1% + \let\makeLineNumberOdd#1% + \let\makeLineNumberEven#1}% + {\ifx\c@linenumber\c@runninglinenumber + \let\makeLineNumberRunning#1% + \else + \let\makeLineNumberOdd#1% + \let\makeLineNumberEven#1% + \fi}% + } + +\def\leftlinenumbers{\setmakelinenumbers\makeLineNumberLeft} +\def\rightlinenumbers{\setmakelinenumbers\makeLineNumberRight} + +\leftlinenumbers* + +% ~\LineNumber~ is a hook which is used for the modulo stuff. +% It is the command to use for the line number, when you +% customizes ~\makeLineNumber~. Use ~\thelinenumber~ to +% change the outfit of the digits. +% +% +% We will implement two modes of operation: +% \begin{itemize} +% \item numbers ~running~ through (parts of) the text +% \item ~pagewise~ numbers starting over with one on top of +% each page. +% \end{itemize} +% Both modes have their own count register, but only one is +% allocated as a \LaTeX\ counter, with the attached +% facilities serving both. + +\newcounter{linenumber} +\newcount\c@pagewiselinenumber +\let\c@runninglinenumber\c@linenumber + +% Only the running mode counter may be reset, or preset, +% for individual paragraphs. The pagewise counter must +% give a unique anonymous number for each line. + +\newcommand\resetlinenumber[1][1]{\c@runninglinenumber#1} + +% \subsection{ +% Running line numbers +% } +% Running mode is easy, ~\LineNumber~ and ~\theLineNumber~ +% produce ~\thelinenumber~, which defaults to +% ~\arabic{linenumber}~, using the ~\c@runninglinenumber~ +% counter. This is the default mode of operation. + +\def\makeRunningLineNumber{\makeLineNumberRunning} + +\def\setrunninglinenumbers{% + \def\theLineNumber{\thelinenumber}% + \let\c@linenumber\c@runninglinenumber + \let\makeLineNumber\makeRunningLineNumber + } + +\setrunninglinenumbers\resetlinenumber + +% +% +% \subsection{ +% Pagewise line numbers +% } +% Difficult, if you think about it. The number has to be +% printed when there is no means to know on which page it +% will end up, except through the aux-file. My solution +% is really expensive, but quite robust. +% +% With version ~v2.00~ the hashsize requirements are +% reduced, because we do not need one controlsequence for +% each line any more. But this costs some computation time +% to find out on which page we are. +% +% ~\makeLineNumber~ gets a hook to log the line and page +% number to the aux-file. Another hook tries to find out +% what the page offset is, and subtracts it from the counter +% ~\c@linenumber~. Additionally, the switch +% ~\ifoddNumberedPage~ is set true for odd numbered pages, +% false otherwise. + +\def\setpagewiselinenumbers{% + \let\theLineNumber\thePagewiseLineNumber + \let\c@linenumber\c@pagewiselinenumber + \let\makeLineNumber\makePagewiseLineNumber + } + +\def\makePagewiseLineNumber{\logtheLineNumber\getLineNumber + \ifoddNumberedPage + \makeLineNumberOdd + \else + \makeLineNumberEven + \fi + } + +% Each numbered line gives a line to the aux file +% \begin{verse} +% ~\@LN{~<line>~}{~<page>~}~ +% \end{verse} +% very similar to the ~\newlabel~ business, except that we need +% an arabic representation of the page number, not what +% there might else be in ~\thepage~. + +\def\logtheLineNumber{\protected@write\@auxout{}{% + \string\@LN{\the\c@linenumber}{\noexpand\the\c@page}}} + +% From the aux-file we get one macro ~\LN@P~<page> for each +% page with line numbers on it. This macro calls four other +% macros with one argument each. These macros are +% dynamically defined to do tests and actions, to find out +% on which page the current line number is located. +% +% We need sort of a pointer to the first page with line +% numbers, initiallized to point to nothing: + +\def\LastNumberedPage{first} +\def\LN@Pfirst{\nextLN\relax} + +% The four dynamic macros are initiallized to reproduce +% themselves in an ~\xdef~ + +\let\lastLN\relax % compare to last line on this page +\let\firstLN\relax % compare to first line on this page +\let\pageLN\relax % get the page number, compute the linenumber +\let\nextLN\relax % move to the next page + +% During the end-document run through the aux-files, we +% disable ~\@LN~. I may put in a check here later, to give +% a rerun recommendation. + +\AtEndDocument{\let\@LN\@gobbletwo} + +% Now, this is the tricky part. First of all, the whole +% definition of ~\@LN~ is grouped, to avoid accumulation +% on the save stack. Somehow ~\csname~<cs>~\endcsname~ pushes +% an entry, which stays after an ~\xdef~ to that <cs>. +% +% If ~\LN@P~<page> is undefined, initialize it with the +% current page and line number, with the +% \emph{pointer-to-the-next-page} pointing to nothing. And +% the macro for the previous page will be redefined to point +% to the current one. +% +% If the macro for the current page already exists, just +% redefine the \emph{last-line-number} entry. +% +% Finally, save the current page number, to get the pointer to the +% following page later. + +\def\@LN#1#2{{\expandafter\@@LN + \csname LN@P#2C\@LN@column\expandafter\endcsname + \csname LN@PO#2\endcsname + {#1}{#2}}} + +\def\@@LN#1#2#3#4{\ifx#1\relax + \ifx#2\relax\gdef#2{#3}\fi + \expandafter\@@@LN\csname LN@P\LastNumberedPage\endcsname#1 + \xdef#1{\lastLN{#3}\firstLN{#3}\pageLN{#4}{\@LN@column}{#2}\nextLN\relax}% + \else + \def\lastLN##1{\noexpand\lastLN{#3}}% + \xdef#1{#1}% + \fi + \xdef\LastNumberedPage{#4C\@LN@column}} + +% The previous page macro gets its pointer to the +% current one, replacing the ~\relax~ with the cs-token +% ~\LN@P~<page>. + +\def\@@@LN#1#2{{\def\nextLN##1{\noexpand\nextLN\noexpand#2}% + \xdef#1{#1}}} + +% Now, to print a line number, we need to find the page, +% where it resides. This will most probably be the page where +% the last one came from, or maybe the next page. However, it can +% be a completely different one. We maintain a cache, +% which is ~\let~ to the last page's macro. But for now +% it is initialized to expand ~\LN@first~, where the poiner +% to the first numbered page has been stored in. + +\def\NumberedPageCache{\LN@Pfirst} + +% To find out on which page the current ~\c@linenumber~ is, +% we define the four dynamic macros to do something usefull +% and execute the current cache macro. ~\lastLN~ is run +% first, testing if the line number in question may be on a +% later page. If so, disable ~\firstLN~, and go on to the +% next page via ~\nextLN~. + +\def\testLastNumberedPage#1{\ifnum#1<\c@linenumber + \let\firstLN\@gobble + \fi} + +% Else, if ~\firstLN~ finds out that we need an earlier +% page, we start over from the beginning. Else, ~\nextLN~ +% will be disabled, and ~\pageLN~ will run +% ~\gotNumberedPage~ with four arguments: the first line +% number on this column, the page number, the column +% number, and the first line on the page. + +\def\testFirstNumberedPage#1{\ifnum#1>\c@linenumber + \def\nextLN##1{\testNextNumberedPage\LN@Pfirst}% + \else + \let\nextLN\@gobble + \def\pageLN{\gotNumberedPage{#1}}% + \fi} + +% We start with ~\pageLN~ disabled and ~\nextLN~ defined to +% continue the search with the next page. + +\long\def \@gobblethree #1#2#3{} + +\def\testNumberedPage{% + \let\lastLN\testLastNumberedPage + \let\firstLN\testFirstNumberedPage + \let\pageLN\@gobblethree + \let\nextLN\testNextNumberedPage + \NumberedPageCache + } + +% When we switch to another page, we first have to make +% sure that it is there. If we are done with the last +% page, we probably need to run \TeX\ again, but for the +% rest of this run, the cache macro will just return four +% zeros. This saves a lot of time, for example if you have +% half of an aux-file from an aborted run, in the next run +% the whole page-list would be searched in vain again and +% again for the second half of the document. +% +% If there is another page, we iterate the search. + +\def\testNextNumberedPage#1{\ifx#1\relax + \global\def\NumberedPageCache{\gotNumberedPage0000}% + \PackageWarningNoLine{lineno}% + {Linenumber reference failed, + \MessageBreak rerun to get it right}% + \else + \global\let\NumberedPageCache#1% + \fi + \testNumberedPage + } + +% \linelabel{demo2} +% \marginpar{\tiny\raggedright +% Let's see if it finds the label +% on page \pageref{demo}, +% line \ref{demo}, and back here +% on page \pageref{demo2}, line +% \ref{demo2}. +% }% +% To separate the official hooks from the internals there is +% this equivalence, to hook in later for whatever purpose: + +\let\getLineNumber\testNumberedPage + +% So, now we got the page where the number is on. We +% establish if we are on an odd or even page, and calculate +% the final line number to be printed. + +\newif\ifoddNumberedPage +\newif\ifcolumnwiselinenumbers +\columnwiselinenumbersfalse + +\def\gotNumberedPage#1#2#3#4{\oddNumberedPagefalse + \ifodd \if@twocolumn #3\else #2\fi\relax\oddNumberedPagetrue\fi + \advance\c@linenumber 1\relax + \ifcolumnwiselinenumbers + \subtractlinenumberoffset{#1}% + \else + \subtractlinenumberoffset{#4}% + \fi + } + +% You might want to run the pagewise mode with running line +% numbers, or you might not. It's your choice: + +\def\runningpagewiselinenumbers{% + \let\subtractlinenumberoffset\@gobble + } + +\def\realpagewiselinenumbers{% + \def\subtractlinenumberoffset##1{\advance\c@linenumber-##1\relax}% + } + +\realpagewiselinenumbers + +% For line number references, we need a protected call to +% the whole procedure, with the requested line number stored +% in the ~\c@linenumber~ counter. This is what gets printed +% to the aux-file to make a label: + +\def\thePagewiseLineNumber{\protect + \getpagewiselinenumber{\the\c@linenumber}}% + +% And here is what happens when the label is refered to: + +\def\getpagewiselinenumber#1{{% + \c@linenumber #1\relax\testNumberedPage + \thelinenumber + }} + +% % +% A summary of all per line expenses: +% \begin{description}\item +% [CPU:] The ~\output~ routine is called for each line, +% and the page-search is done. +% \item +% [DISK:] One line of output to the aux-file for each +% numbered line +% \item +% [MEM:] One macro per page. Great improvement over v1.02, +% which had one control sequence per line in +% addition. It blew the hash table after some five +% thousand lines. +% \end{description} +% +% +% +% \subsection{ +% Twocolumn mode (New v3.06) +% } +% +% Twocolumn mode requires another patch to the ~\output~ +% routine, in order to print a column tag to the .aux +% file. + +\let\@LN@orig@makecol\@makecol +\def\@LN@makecol{% + \@LN@orig@makecol + \setbox\@outputbox \vbox{% + \boxmaxdepth \@maxdepth + \protected@write\@auxout{}{% + \string\@LN@col{\if@firstcolumn1\else2\fi}% + }% + \box\@outputbox + }% \vbox +} + +\def\@LN@col#1{\def\@LN@column{#1}} +\@LN@col{1} + +% +% +% +% \subsection{ +% Numbering modulo 5 +% } +% Most users want to have only one in five lines numbered. +% ~\LineNumber~ is supposed to produce the outfit of the +% line number attached to the line, while ~\thelinenumber~ +% is used also for references, which should appear even if +% they are not multiples of five. + +\newcount\c@linenumbermodulo + +\def\themodulolinenumber{{\@tempcnta\c@linenumber + \divide\@tempcnta\c@linenumbermodulo + \multiply\@tempcnta\c@linenumbermodulo + \ifnum\@tempcnta=\c@linenumber\thelinenumber\fi + }} + +% The user command to set the modulo counter: + +\newcommand\modulolinenumbers[1][0]{% + \let\LineNumber\themodulolinenumber + \ifnum#1>1\relax + \c@linenumbermodulo#1\relax + \else\ifnum#1=1\relax + \def\LineNumber{\thelinenumber}% + \fi\fi + } + +\setcounter{linenumbermodulo}{5} +\modulolinenumbers[1] + +% +% \switchlinenumbers +% \modulolinenumbers[1] +% \section{ +% Package options +% } +% There is a bunch of package options, all of them +% executing only user commands (see below). +% +% Options ~left~ (~right~) put the line numbers on the left +% (right) margin. This works in all modes. ~left~ is the +% default. + +\DeclareOption{left}{\leftlinenumbers*} + +\DeclareOption{right}{\rightlinenumbers*} + +% Option ~switch~ (~switch*~) puts the line numbers on the +% outer (inner) margin of the text. This requires running +% the pagewise mode, but we turn off the page offset +% subtraction, getting sort of running numbers again. The +% ~pagewise~ option may restore true pagewise mode later. + +\DeclareOption{switch}{\setpagewiselinenumbers + \switchlinenumbers + \runningpagewiselinenumbers} + +\DeclareOption{switch*}{\setpagewiselinenumbers + \switchlinenumbers*% + \runningpagewiselinenumbers} + +% In twocolumn mode, we can switch the line numbers to +% the outer margin, and/or start with number 1 in each +% column. Margin switching is covered by the ~switch~ +% options. + +\DeclareOption{columnwise}{\setpagewiselinenumbers + \columnwiselinenumberstrue + \realpagewiselinenumbers} + +% The options ~pagewise~ and ~running~ select the major +% linenumber mechanism. ~running~ line numbers refer to a real +% counter value, which can be reset for any paragraph, +% even getting multiple paragraphs on one page starting +% with line number one. ~pagewise~ line numbers get a +% unique hidden number within the document, but with the +% opportunity to establish the page on which they finally +% come to rest. This allows the subtraction of the page +% offset, getting the numbers starting with 1 on top of each +% page, and margin switching in twoside formats becomes +% possible. The default mode is ~running~. +% +% The order of declaration of the options is important here +% ~pagewise~ must come after ~switch~, to overide running +% pagewise mode. ~running~ comes last, to reset the running +% line number mode, e.g, after selecting margin switch mode +% for ~pagewise~ running. Once more, if you specify all +% three of the options ~[switch,pagewise,running]~, the +% result is almost nothing, but if you later say +% ~\pagewiselinenumbers~, you get margin switching, with +% real pagewise line numbers. +% +\DeclareOption{pagewise}{\setpagewiselinenumbers + \realpagewiselinenumbers} + +\DeclareOption{running}{\setrunninglinenumbers} + +% The option ~modulo~ causes only those linenumbers to be +% printed which are multiples of five. + +\DeclareOption{modulo}{\modulolinenumbers\relax} + +% The package option ~mathlines~ switches the behavior of +% the ~{linenomath}~ environment with its star-form. +% Without this option, the ~{linenomath}~ environment does +% not number the lines of the display, while the star-form +% does. With this option, its just the opposite. +% +%%% 1999-06-10: renamed ~displaymath~ to ~mathlines~. + +\DeclareOption{mathlines}{\linenumberdisplaymath} + +% ~displaymath~ now calls for wrappers of the standard +% LaTeX display math environment. This was previously +% done by ~mlineno.sty~. + +\let\do@mlineno\relax +\DeclareOption{displaymath}{\let\do@mlineno\@empty} + +% The ~hyperref~ package, via ~nameref~, requires three more +% groups in the second argment of a ~\newlabel~. Well, why +% shouldn't it get them? (New v3.07) The presencs of the +% ~nameref~ package is now detected automatically +% ~\AtBeginDocument~. (/New v3.07) (Fixed in v3.09) We try +% to be smart, and test ~\AtBeginDocument~ if the ~nameref~ +% package is loaded, but ~hyperref~ postpones the loading of +% ~nameref~ too, so this is all in vain. + +\DeclareOption{hyperref}{\PackageWarningNoLine{lineno}{% + Option [hyperref] is obsolete. + \MessageBreak The hyperref package is detected automatically.}} + +\AtBeginDocument{% + \@ifpackageloaded{nameref}{% + \def\@LN@ExtraLabelItems{{}{}{}}}{}} + +\ProcessOptions + +% \subsection{ +% Package Extensions +% } +% +% The extensions in this section were previously supplied +% in seperate ~.sty~ files. +% +% \subsubsection{ +% $display math$ +% } +% +% The standard \LaTeX\ display math environments are +% wrapped in a ~{linenomath}~ environment. +% +% (New 3.05) The ~[fleqn]~ option of the standard +% \LaTeX\ classes defines the display math +% environments such that line numbers appear just +% fine. Thus, we need not do any tricks when +% ~[fleqn]~ is loaded, as indicated by presents of +% the ~\mathindent~ register. (/New 3.05) +% +% (New 3.05a) for ~{eqnarray}~s we rather keep the +% old trick. (/New 3.05a) +% +% (New 3.08) Wrap ~\[~ and ~\]~ into ~{linenomath}~, +% instead of ~{displaymath}~. Also save the definition +% of ~\equation~, instead of replicating the current +% \LaTeX\ definition. (/New 3.08) + +\ifx\do@mlineno\@empty + \@ifundefined{mathindent}{ + + \let\LN@displaymath\[ + \let\LN@enddisplaymath\] + \renewcommand\[{\begin{linenomath}\LN@displaymath} + \renewcommand\]{\LN@enddisplaymath\end{linenomath}} + + \let\LN@equation\equation + \let\LN@endequation\endequation + \renewenvironment{equation} + {\linenomath\LN@equation} + {\LN@endequation\endlinenomath} + + }% \@ifundefined{mathindent} + + \let\LN@eqnarray\eqnarray + \let\LN@endeqnarray\endeqnarray + \renewenvironment{eqnarray} + {\linenomath\LN@eqnarray} + {\LN@endeqnarray\endlinenomath} + +\fi + +% \subsubsection{ +% Line numbers in internal vertical mode +% } +% +% The command ~\internallinenumbers~ adds line numbers in +% internal vertical mode, but with limitations: we assume +% fixed baseline skip. + +\def\internallinenumbers{\setrunninglinenumbers + \let\@@par\internallinenumberpar + \ifx\@par\@@@par\let\@par\internallinenumberpar\fi + \ifx\par\@@@par\let\par\internallinenumberpar\fi + \ifx\@par\linenumberpar\let\@par\internallinenumberpar\fi + \ifx\par\linenumberpar\let\par\internallinenumberpar\fi + \@ifnextchar[{\resetlinenumber}%] + {\@ifstar{\let\c@linenumber\c@internallinenumber + \c@linenumber\@ne}{}}% + } + +\let\endinternallinenumbers\endlinenumbers +\@namedef{internallinenumbers*}{\internallinenumbers*} +\expandafter\let\csname endinternallinenumbers*\endcsname\endlinenumbers + +\newcount\c@internallinenumber +\newcount\c@internallinenumbers + +\def\internallinenumberpar{\ifvmode\@@@par\else\ifinner\@@@par\else\@@@par + \begingroup + \c@internallinenumbers\prevgraf + \setbox\@tempboxa\hbox{\vbox{\makeinternalLinenumbers}}% + \dp\@tempboxa\prevdepth + \ht\@tempboxa\z@ + \nobreak\vskip-\prevdepth + \nointerlineskip\box\@tempboxa + \endgroup + \fi\fi + } + +\def\makeinternalLinenumbers{\ifnum\c@internallinenumbers>0\relax + \hbox to\z@{\makeLineNumber}\global\advance\c@linenumber\@ne + \advance\c@internallinenumbers\m@ne + \expandafter\makeinternalLinenumbers\fi + } + +% \subsubsection{ +% Line number references with offset +% } +% +% This extension defines macros to refer to line +% numbers with an offset, e.g., to refer to a line +% which cannot be labeled directly (display math). +% This was formerly knows as ~rlineno.sty~. +% +% To refer to a pagewise line number with offset: +% \begin{quote} +% ~\linerefp[~<OFFSET>~]{~<LABEL>~}~ +% \end{quote} +% To refer to a running line number with offset: +% \begin{quote} +% ~\linerefr[~<OFFSET>~]{~<LABEL>~}~ +% \end{quote} +% To refer to a line number labeled in the same mode as currently +% selected: +% \begin{quote} +% ~\lineref[~<OFFSET>~]{~<LABEL>~}~ +% \end{quote} + +\newcommand\lineref{% + \ifx\c@linenumner\c@runninglinenumner + \expandafter\linerefr + \else + \expandafter\linerefp + \fi +} + +\newcommand\linerefp[2][\z@]{{% + \let\@thelinenumber\thelinenumber + \edef\thelinenumber{\advance\c@linenumber#1\relax\noexpand\@thelinenumber}% + \ref{#2}% +}} + +% This goes deep into \LaTeX s internals. + +\newcommand\linerefr[2][\z@]{{% + \def\@@linerefadd{\advance\c@linenumber#1}% + \expandafter\@setref\csname r@#2\endcsname + \@linerefadd{#2}% +}} + +\newcommand\@linerefadd[2]{\c@linenumber=#1\@@linerefadd\relax + \thelinenumber} + +% \subsubsection{ +% Numbered quotation environments +% } +% +% The ~{numquote}~ and ~{numquotation}~ +% environments are like ~{quote}~ and +% ~{quotation}~, except there will be line +% numbers. +% +% An optional argument gives the number to count +% from. A star ~*~ (inside or outside the closing +% ~}~) prevent the reset of the line numbers. +% Default is to count from one. + +\newcommand\quotelinenumbers + {\@ifstar\linenumbers{\@ifnextchar[\linenumbers{\linenumbers*}}} + +\newdimen\quotelinenumbersep +\quotelinenumbersep=\linenumbersep +\let\quotelinenumberfont\linenumberfont + +\newcommand\numquotelist + {\leftlinenumbers + \linenumbersep\quotelinenumbersep + \let\linenumberfont\quotelinenumberfont + \addtolength{\linenumbersep}{-\@totalleftmargin}% + \quotelinenumbers + } + +\newenvironment{numquote} {\quote\numquotelist}{\endquote} +\newenvironment{numquotation} {\quotation\numquotelist}{\endquotation} +\newenvironment{numquote*} {\quote\numquotelist*}{\endquote} +\newenvironment{numquotation*}{\quotation\numquotelist*}{\endquotation} + +% \subsubsection{ +% Frame around a paragraph +% } +% +% The ~{bframe}~ environment draws a frame around +% some text, across page breaks, if necessary. +% +% This works only for plain text paragraphs, +% without special height lines. All lines must be +% ~\baselineskip~ apart, no display math. + +\newenvironment{bframe} + {\par + \@tempdima\textwidth + \advance\@tempdima 2\bframesep + \setbox\bframebox\hbox to\textwidth{% + \hskip-\bframesep + \vrule\@width\bframerule\@height\baselineskip\@depth\bframesep + \advance\@tempdima-2\bframerule + \hskip\@tempdima + \vrule\@width\bframerule\@height\baselineskip\@depth\bframesep + \hskip-\bframesep + }% + \hbox{\hskip-\bframesep + \vrule\@width\@tempdima\@height\bframerule\@depth\z@}% + \nointerlineskip + \copy\bframebox + \nobreak + \kern-\baselineskip + \runninglinenumbers + \def\makeLineNumber{\copy\bframebox\hss}% + } + {\par + \kern-\prevdepth + \kern\bframesep + \nointerlineskip + \@tempdima\textwidth + \advance\@tempdima 2\bframesep + \hbox{\hskip-\bframesep + \vrule\@width\@tempdima\@height\bframerule\@depth\z@}% + } + +\newdimen\bframerule +\bframerule=\fboxrule + +\newdimen\bframesep +\bframesep=\fboxsep + +\newbox\bframebox + +% \section{ +% The final touch +% } +% There is one deadcycle for each line number. + +\advance\maxdeadcycles 100 + +\endinput + +% \section{ +% The user commands +% } +% The user command to turn on and off line numbering +% are +% \begin{description}\item +% [|\linenumbers] \ \par +% Turn on line numbering in the current mode. +% \item +% [|\linenumbers*] \ \par$\qquad$ +% and reset the line number to 1. +% \def\NL{<number>]}\item +% [|\linenumbers[\NL] \ \par$\qquad$ +% and start with <number>. +% \item +% [|\nolinenumbers] \ \par +% Turn off line numbering. +% \item +% [|\runninglinenumbers*[\NL] \ \par +% Turn on ~running~ line numbers, with the same optional +% arguments as ~\linenumbers~. The numbers are running +% through the text over pagebreaks. When you turn +% numbering off and on again, the numbers will continue, +% except, of cause, if you ask to reset or preset the +% counter. +% \item +% [|\pagewiselinenumbers] \ \par +% Turn on ~pagewise~ line numbers. The lines on each +% page are numbered beginning with one at the first +% ~pagewise~ numbered line. +% \item +% [|\resetlinenumber[\NL] \ \par +% Reset ~[~Set~]~ the line number to 1 +% ~[~<number>~]~. +% \item +% [|\setrunninglinenumbers] \ \par +% Switch to ~running~ line number mode. Do \emph{not} +% turn it on or off. +% \item +% [|\setpagewiselinenumbers] \ \par +% Switch to ~pagewise~ line number mode. Do \emph{not} +% turn it on or off. +% \item +% [|\switchlinenumbers*] \ \par +% Causes margin switching in pagewise modes. With the +% star, put the line numbers on the inner margin. +% \item +% [|\leftlinenumbers*] \ \par +% \item +% [|\rightlinenumbers*] \ \par +% Set the line numbers in the left/right margin. With the +% star this works for both modes of operation, without +% the star only for the currently selected mode. +% \item +% [|\runningpagewiselinenumbers] \ \par +% When using the pagewise line number mode, do not +% subtract the page offset. This results in running +% line numbers again, but with the possibility to switch +% margins. Be careful when doing line number +% referencing, this mode status must be the same while +% setting the paragraph and during references. +% \item +% [|\realpagewiselinenumbers] \ \par +% Reverses the effect of ~\runningpagewiselinenumbers~. +% \item +% [|\modulolinenumbers[\NL] \ \par +% Give a number only to lines which are multiples of +% ~[~<number>~]~. If <number> is not specified, the +% current value in the counter ~linenumbermodulo~ is +% retained. <number>=1 turns this off without changing +% ~linenumbermodulo~. The counter is initialized to 5. +% \item +% [|\linenumberdisplaymath] \ \par +% Number the lines of a display math in a ~{linenomath}~ +% environment, but do not in a ~{linenomath*}~ +% environment. This is used by the package option +% ~[mathlines]~. +% \item +% [|\nolinenumberdisplaymath] \ \par +% Do not Number the lines of a display math in a +% ~{linenomath}~ environment, but do in a +% ~{linenomath*}~ environment. This is the default. +% \item +% [|\linelabel] \ \par +% Set a ~\linelabel{~<foo>~}~ to the line number where +% this commands is in. Refer to it with the \LaTeX\ +% referencing commands ~\ref{~<foo>~}~ and +% ~\pageref{~<foo>~}~. +% \end{description} +% The commands can be used globally, locally within groups +% or as environments. It is important to know that they +% take action only when the ~\par~ is executed. The +% ~\end{~<mode>~linenumbers}~ commands provide a ~\par~. +% Examples: +% \begin{verse} +% ~{\linenumbers~ <text> ~\par}~ \\ +% \ \\ +% ~\begin{linenumbers}~ \\ +% <text> \\ +% ~\end{linenumbers}~ \\ +% \ \\ +% <paragraph> ~{\linenumbers\par}~ \\ +% \ \\ +% ~\linenumbers~ \\ +% <text> ~\par~ \\ +% ~\nolinenumbers~ \\ +% \ \\ +% ~\linenumbers~ \\ +% <paragraph> ~{\nolinenumbers\par}~ \\ +% \end{verse} +% +% +% \subsection{ +% Customization hooks +% } +% There are several hooks to customize the appearance of the +% line numbers, and some low level hooks for special +% effects. +% \begin{description}\item +% [|\thelinenumber] \ \par +% This macro should give the representation of the line +% number in the \LaTeX-counter ~linenumber~. The +% default is provided by \LaTeX: \par$\qquad$ +% ~\arabic{linenumber}~ +% \item +% [|\makeLineNumberLeft] \ \par +% This macro is used to attach a line number to the left +% of the text page. This macro should fill an ~\hbox to 0pt~ +% which will be placed at the left margin of the +% page, with the reference point aligned to the line to +% which it should give a number. Please use the macro +% ~\LineNumber~ to refer to the line number. +% +% The default definition is \par$\qquad$ +% ~\hss\linenumberfont\LineNumber\hskip\linenumbersep~ +% \item +% [|\makeLineNumberRight] \ \par +% Like ~\makeLineNumberLeft~, but for line numbers on +% the right margin. +% +% The default definition is \par$\qquad$ +% ~\linenumberfont\hskip\linenumbersep\hskip\textwidth~ \par$\qquad$ +% ~\hbox to\linenumberwidth{\hss\LineNumber}\hss~ +% \item +% [|\linenumberfont] \ \par +% This macro is initialized to \par$\qquad$ +% ~\normalfont\tiny\sffamily~ +% \item +% [|\linenumbersep] \ \par +% This dimension register sets the separation of the +% linenumber to the text. Default value is ~10pt~. +% \item +% [|\linenumberwidth] \ \par +% This dimension register sets the width of the line +% number box on the right margin. The distance of the +% right edge of the text to the right edge of the line +% number is ~\linenumbersep~ + ~\linenumberwidth~. The +% default value is ~10pt~. +% \item +% [|\theLineNumber] (for wizards) \ \par +% This macro is called for printing a ~\newlabel~ entry +% to the aux-file. Its definition depends on the mode. +% For running line numbers it's just ~\thelinenumber~, +% while in pagewise mode, the page offset subtraction +% is done in here. +% \item +% [|\makeLineNumber] (for wizards) \ \par +% This macro produces the line numbers. The definition +% depends on the mode. In the running line numbers +% mode it just expands ~\makeLineNumberLeft~. +% \item +% [|\LineNumber] (for wizards) \ \par +% This macro is called by ~\makeLineNumber~ to typeset +% the line number. This hook is changed by the modulo +% mechanism. +% \end{description} +% \end{document}%D +------------------------------------------------------------------------------ + +echo "expect errors for unknown commands 'iffalse' and 'fi'";# SHELL +awk '/A[W]K/' lineno.sty | awk -f - lineno.sty >lineno.tex; # SHELL +latex lineno; latex lineno; latex lineno; latex lineno; # SHELL + +awk '/DOC A [W] K/' lineno.sty | awk -f - lineno.sty >lineno.doc; # DOC SH + +BEGIN{DOC=-1; # AWK DOC A W K + BEGINCODE = "\\begin{code}\\begin{verbatim}"; # AWK + ENDCODE = "\\end{verbatim}\n\\end{code}"; } # AWK + BEGINCODE = "% \\begin{macrocode}"; # DOC A W K + ENDCODE = "% \\end{macrocode}"; } # DOC A W K +/^[ \t]*$/ { ECNT++; next; } # AWK DOC A W K +/\\documentclass/{ sub("article","ltxdoc") } # DOC A W K +/%D$/ { sub("^%* *",""); sub("%D$",""); # DOC A W K + print > "lineno.drv"; next } # DOC A W K +/^%%/ { next; } # AWK DOC A W K +/^%/ { if (!DOC) { print ENDCODE; } # AWK DOC A W K + DOC=1; ECNT=0; # AWK DOC A W K + sub("^% *",""); # AWK + sub("^% *","% "); # DOC A W K + print; next; } # AWK DOC A W K +DOC<0 { next } # AWK DOC A W K +/^-+-$/ { if (!DOC) print ENDCODE; exit } # AWK DOC A W K +{ if (DOC) { ECNT=DOC=0; print BEGINCODE; } # AWK DOC A W K + while (ECNT>0) { print " "; ECNT--; } # AWK DOC A W K + print $0; } # AWK DOC A W K + diff --git a/trunk/doc/linuxtag.sty b/trunk/doc/linuxtag.sty new file mode 100644 index 0000000..3820886 --- /dev/null +++ b/trunk/doc/linuxtag.sty @@ -0,0 +1,67 @@ +% Modified for european a4 paper size and font size requirements for LT2K++ +% +% TEMPLATE for Usenix papers, specifically to meet requirements of +% TCL97 committee. +% originally a template for producing IEEE-format articles using LaTeX. +% written by Matthew Ward, CS Department, Worcester Polytechnic Institute. +% adapted by David Beazley for his excellent SWIG paper in Proceedings, +% Tcl 96 +% turned into a smartass generic template by De Clarke, with thanks to +% both the above pioneers +% use at your own risk. Complaints to /dev/null. +% make it two column with no page numbering, default is 10 point + +% include following in document. +%\documentclass[a4paper,10pt]{article} +%\usepackage{twocolumn,times} +%\pagestyle{empty} + +% force european A4 paper format +\setlength{\textwidth}{16.6cm} % width of main text +\setlength{\textheight}{25cm} % height of main text +\setlength{\topmargin}{-1.7in} % Subtract default offset +\addtolength{\topmargin}{2.2cm} % Topmargin +\setlength{\topskip}{0pt} % between header and text +\setlength{\headheight}{10pt} % no header +\setlength{\headsep}{10pt} % +\setlength{\oddsidemargin}{-1in} % Subtract default offset +\addtolength{\oddsidemargin}{2.2cm} % odd page left margin +\setlength{\evensidemargin}{-1in} % Subtract default offset +\addtolength{\evensidemargin}{2.2cm} % odd page left margin + +% set dimensions of columns, gap between columns, and space between paragraphs +\setlength{\columnsep}{0.25in} +\setlength{\parindent}{0pt} +\setlength{\parskip}{\baselineskip} + +% started out with art10.sty and modified params to conform to IEEE format +% further mods to conform to Usenix standard + +\makeatletter +%as Latex considers descenders in its calculation of interline spacing, +%to get 12 point spacing for normalsize text, must set it to 10 points +\def\@normalsize{\@setsize\normalsize{12pt}\xpt\@xpt +\abovedisplayskip 10pt plus2pt minus5pt\belowdisplayskip \abovedisplayskip +\abovedisplayshortskip \z@ plus3pt\belowdisplayshortskip 6pt plus3pt +minus3pt\let\@listi\@listI} + +%need a 12 pt font size for subsection and abstract headings +\def\subsize{\@setsize\subsize{12pt}\xipt\@xipt} + +%make section titles bold and 12 point, 2 blank lines before, 1 after +\def\section{\@startsection {section}{1}{\z@}{18pt plus 2pt minus 2pt} +{2pt plus 2pt minus 2pt}{\large\bf}} + +%make subsection titles bold and 11 point, 1 blank line before, 1 after +\def\subsection{\@startsection {subsection}{2}{\z@}{12pt plus 2pt minus 2pt} +{12pt plus 2pt minus 2pt}{\subsize\bf}} + +\renewcommand\scriptsize{\@setfontsize\scriptsize\@viipt\@viiipt} +\renewcommand\tiny{\@setfontsize\tiny\@vpt\@vipt} +\renewcommand\large{\@setfontsize\large\@xiipt{12}} +\renewcommand\Large{\@setfontsize\Large\@xivpt{14}} +\renewcommand\LARGE{\@setfontsize\LARGE\@xviipt{18}} +\renewcommand\huge{\@setfontsize\huge\@xxpt{24}} +\renewcommand\Huge{\@setfontsize\Huge\@xxvpt{28}} + +\makeatother diff --git a/trunk/doc/newseg.fig b/trunk/doc/newseg.fig new file mode 100644 index 0000000..4a2f7ea --- /dev/null +++ b/trunk/doc/newseg.fig @@ -0,0 +1,84 @@ +#FIG 3.2 +Landscape +Center +Inches +Letter +100.00 +Single +-2 +1200 2 +6 5550 900 7425 3675 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5625 2850 6750 2850 6750 3450 5625 3450 5625 2850 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 6750 2700 6750 3600 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 6750 2850 7350 2850 7350 3450 6750 3450 6750 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 5625 1200 6750 1200 6750 1800 5625 1800 5625 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 5625 975 7350 975 7350 1950 5625 1950 5625 975 +2 1 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 2 + 6750 975 6750 1950 +2 2 0 2 0 7 50 0 44 0.000 0 0 -1 0 0 5 + 6750 1200 7350 1200 7350 1800 6750 1800 6750 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 5625 2700 7350 2700 7350 3600 5625 3600 5625 2700 +4 0 0 50 0 0 12 0.0000 4 180 885 5775 3225 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 6825 3225 .bss\001 +4 0 0 50 0 0 12 0.0000 4 180 885 5775 1575 .data ... .got\001 +4 0 0 50 0 0 12 0.0000 4 135 315 6825 1575 .bss\001 +-6 +6 7950 2775 10875 3525 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 8025 2850 9000 2850 9000 3450 8025 3450 8025 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 9825 2850 9000 2850 9000 3450 9825 3450 9825 2850 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 9825 2850 10800 2850 10800 3450 9825 3450 9825 2850 +4 0 0 50 0 0 12 0.0000 4 180 780 9000 3225 .gnu.liblist\001 +4 0 0 50 0 0 12 0.0000 4 180 930 9825 3225 .gnu.conflict\001 +4 0 0 50 0 0 12 0.0000 4 180 525 8175 3225 .dynstr\001 +-6 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 600 1200 2100 1200 2100 1800 600 1800 600 1200 +2 2 0 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 2100 1200 2775 1200 2775 1800 2100 1800 2100 1200 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4950 1200 2775 1200 2775 1800 4950 1800 4950 1200 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 2700 4950 2700 4950 3600 450 3600 450 2700 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 450 975 4950 975 4950 1950 450 1950 450 975 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 4950 2850 2775 2850 2775 3450 4950 3450 4950 2850 +2 2 0 2 0 7 50 0 -1 0.000 0 0 -1 0 0 5 + 750 2850 2250 2850 2250 3450 750 3450 750 2850 +2 2 1 2 0 7 50 0 -1 6.000 0 0 -1 0 0 5 + 8025 2700 10800 2700 10800 3600 8025 3600 8025 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 1350 1950 1500 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 3975 1950 3975 2025 3975 2100 3975 2175 3975 2250 3975 2325 + 3975 2400 3975 2475 3975 2550 3975 2625 3975 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 6150 1950 6150 2025 6150 2100 6150 2175 6150 2250 6150 2325 + 6150 2400 6150 2475 6150 2550 6150 2625 6150 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 11 + 0 0 1.00 60.00 120.00 + 6975 1950 6975 2025 6975 2100 6975 2175 6975 2250 6975 2325 + 6975 2400 6975 2475 6975 2550 6975 2625 6975 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2100 1950 8025 2700 +2 1 0 1 0 7 50 0 -1 4.000 0 0 -1 1 0 2 + 0 0 1.00 60.00 120.00 + 2775 1950 9000 2700 +4 0 0 50 0 0 12 0.0000 4 180 1335 675 1575 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 525 2175 1575 .dynstr\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 2850 1575 .gnu.version ... .eh_frame\001 +4 0 0 50 0 0 12 0.0000 4 180 1335 825 3225 .interp ... .dynsym\001 +4 0 0 50 0 0 12 0.0000 4 180 1890 2850 3225 .gnu.version ... .eh_frame\001 diff --git a/trunk/doc/prelink.8 b/trunk/doc/prelink.8 new file mode 100644 index 0000000..c43b08a --- /dev/null +++ b/trunk/doc/prelink.8 @@ -0,0 +1,302 @@ +.TH prelink 8 "23 November 2004" +.SH NAME +prelink \- prelink ELF shared libraries and binaries to speed up startup time +.SH SYNOPSIS +prelink +.RB [OPTION...]\ [FILES] +.SH DESCRIPTION +.B prelink +is a program which modifies ELF shared libraries and ELF dynamically linked +binaries, so that the time which dynamic linker needs for their relocation +at startup significantly decreases and also due to fewer relocations the +run-time memory consumption decreases too (especially number of unshareable +pages). Such prelinking information is only used if all its dependant +libraries have not changed since prelinking, otherwise programs are +relocated normally. +.PP +.B prelink +first collects ELF binaries which should be prelinked and all the ELF shared +libraries they depend on. Then it assigns a unique virtual address space +slot for each library and relinks the shared library to that base address. +When the dynamic linker attempts to load such a library, unless that virtual +address space slot is already occupied, it will map it into the given slot. +After this is done, +.B prelink +with the help of dynamic linker resolves all relocations in the binary or +library against its dependant libraries and stores the relocations into the +ELF object. +It also stores a list of all dependant libraries together with their +checksums into the binary or library. +For binaries, it also computes a list of +.IR conflicts +(relocations which resolve differently in the binary's symbol search scope +than in the smaller search scope in which the dependant library was +resolved) and stores it into a special ELF section. +.PP +At runtime, the dynamic linker first checks whether all dependant libraries +were successfully mapped into their designated address space slots and +whether they have not changed since the prelinking was done. +If all checks are successful, the dynamic linker just replays the list of +conflicts (which is usually significantly shorter than total number of +relocations) instead of relocating each library. +.SH OPTIONS +.TP +.B \-v\ \-\-verbose +Verbose mode. +Print the virtual address slot assignment to libraries and print what binary +or library is currently being prelinked. +.TP +.B \-n\ \-\-dry\-run +Don't actually prelink anything, just collect the binaries/libraries, assign +them addresses and with +.B \-v +print what would be prelinked. +.TP +.B \-a \-\-all +Prelink all binaries and dependant libraries found in directory hierarchies +specified in +.IR /etc/prelink.conf . +Normally only binaries specified from command line and their dependant +libraries are prelinked. +.TP +.B \-m \-\-conserve\-memory +When assigning addresses to libraries, allow overlap of address space slots +provided that the two libraries are not present together in any of the +binaries or libraries. This results in smaller virtual address space range +used for libraries, on the other side if during incremental prelinking +.B prelink +sees a binary which puts together two libraries which were not present +together in any other binary and were given the same virtual address space +slots, then the binary cannot be prelinked. +Normally each library is assigned a unique virtual address space slot. +.TP +.B \-R \-\-random +When assigning addresses to libraries, start with random address within +architecture dependant virtual address space range. +This can make some buffer overflow attacks slightly harder to exploit, +because libraries are not present on the same addresses accross different +machines. +Normally, assigning virtual addresses starts at the bottom of architecture +dependant range. +.TP +.B \-r \-\-reloc\-only=ADDRESS +Instead of prelinking, just relink given shared libraries to the specified +base address. +.TP +.B \-N \-\-no\-update\-cache +Don't save cache file after prelinking. Normally, list of libraries (and +with +.B \-m +binaries also) is stored into +.I /etc/prelink.cache +file together with their given address space slots and dependencies, so +it can be used during incremental prelinking (prelinking without +.B \-a +option). +.TP +.B \-c \-\-config\-file=CONFIG +Specify alternate config file instead of default +.IR /etc/prelink.conf . +.TP +.B \-C \-\-cache\-file=CACHE +Specify alternate cache file instead of default +.IR /etc/prelink.cache . +.TP +.B \-f \-\-force +Force re-prelinking even for already prelinked objects for which no +dependencies changed. This option causes new virtual address space slots to +be assigned to all libraries. +Normally, only binaries or libraries which are either not prelinked yet, or +some of their dependencies changed, are prelinked. +.TP +.B \-q \-\-quick +Run prelink in quick mode. This mode checks just mtime and ctime timestamps +of libraries and binaries stored in the cache file. If they are unchanged +from the last prelink run, it is assumed that the library in question did +not change and no parsing of its ELF headers and verifying it is done. +.TP +.B \-p \-\-print\-cache +Print the content of the cache file (normally +.IR /etc/prelink.cache ) +and exit. +.TP +.B \-\-dynamic\-linker=LDSO +Specify alternate dynamic linker instead of the default. +.TP +.B \-\-ld\-library\-path=PATH +Specify special +.IR LD_LIBRARY_PATH +to be used when +.B prelink +queries dynamic linker about symbol resolution details. +.TP +.B \-\-libs\-only +Only prelink ELF shared libraries, don't prelink any binaries. +.TP +.B \-h \-\-dereference +When processing command line directory arguments, follow symbolic links when +walking directory hierarchies. +.TP +.B \-l \-\-one\-file\-system +When processing command line directory arguments, limit directory tree walk +to a single filesystem. +.TP +.B \-u \-\-undo +Revert binaries and libraries to their original content before they were +prelinked. +Without +.I \-a +option this causes only the binaries and libraries specified on the command +line to be reverted to their original state (and e.g. not their +dependencies). If used together with +.I \-a +option all binaries and libraries from command line, all their dependencies, +all binaries found in directories specified on command line and in config +file and all their dependencies will be undone. +.TP +.B \-y \-\-verify +Verifies a prelinked binary or library. +This option can be used only on a single binary or library. It first applies +an +.I \-\-undo +operation on the file, then prelinks just that file again and compares this +with the original file. If both are identical, it prints the file after +.I \-\-undo +operation on standard output and exit with zero status. Otherwise it exits +with error status. +Thus if +.I \-\-verify +operation returns zero exit status and its standard output is +equal to the content of the binary or library before prelinking, you can be +sure that nobody modified the binaries or libraries after prelinking. +Similarly with message digests and checksums (unless you trigger the +unprobable case of modified file and original file having the same digest +or checksum). +.TP +.B \-\-md5 +This is similar to +.I \-\-verify +option, except instead of outputing the content of the binary or library +before prelinking to standard output MD5 digest is printed. +See +.BR md5sum (1). +.TP +.B \-\-sha +This is similar to +.I \-\-verify +option, except instead of outputing the content of the binary or library +before prelinking to standard output SHA1 digest is printed. +See +.BR sha1sum (1). +.TP +.B \-\-exec\-shield \-\-no\-exec\-shield +On IA-32, if kernel supports Exec-Shield, prelink attempts to lay libraries +out similarly to how kernel places them (i.e. if possible below the binary, +most widely used into the ASCII armor zone). These switches allow to override +prelink detection of whether Exec-Shield is supported or not. +.TP +.B \-b \-\-black\-list=PATH +This option allows to blacklist certain paths, libraries or binaries. +Prelink will not touch them during prelinking. +.TP +.B \-o \-\-undo\-output=FILE +When doing +.B \-\-undo +operation, don't overwrite the prelinked binary or library with its +original content (before it was prelinked), but save that into the specified +file. +.TP +.B \-V \-\-version +Print version and exit. +.TP +.B \-? \-\-help +Print short help and exit. +.SH ARGUMENTS +Command line arguments should be either directory hierarchies (in which case +.I \-l +and +.I \-h +options apply), or particular ELF binaries or shared libraries. +Unlike when walking directory hierarchies, specifying a shared library +explicitely on the command line causes it to be prelinked even if no binary +is linked against it. Normally, only binaries are collected together with +all libraries they depend on. +.SH EXAMPLES +.RS +# /usr/sbin/prelink -avmR +.RE +will prelink all binaries found in directories specified in +.I /etc/prelink.conf +and all their dependant libraries, assigning libraries unique virtual +address space slots only if they ever appear together and will start +assigning at random address. +.RS +# /usr/sbin/prelink -vm ~/bin/progx +.RE +will prelink ~/bin/progx program and all its dependant libraries (unless +they were prelinked already e.g. during +.I prelink \-a +invocation). +.RS +# /usr/sbin/prelink -au +.RE +will revert all binaries and libraries to their original content. +.RS +# /usr/sbin/prelink -y /bin/prelinked_prog > /tmp/original_prog; echo $? +will verify whether /bin/prelinked_prog hasn't been changed. +.SH FILES +.PD 0 +.TP 20 +.B /etc/prelink.cache +Binary file containing list of prelinked libraries and/or binaries together +with their assigned virtual address space slots and dependencies. +You can run +.I /usr/sbin/prelink -p +to see what is stored in there. +.TP 20 +.B /etc/prelink.conf +Configuration file containing a list of directory hierarchies which can +contain ELF shared libraries or binaries which should be prelinked. +This configuration file is used in +.B \-a +mode to find binaries which should be prelinked and also no matter whether +.B \-a +is given or not to limit which dependant shared libraries should be +prelinked. If +.B prelink +finds a dependant library of some binary or other library which is not +present in any of the directories specified in +.B /etc/prelink.conf +and neither in any of the directories specified on the command line, then it +cannot be prelinked. +Each line of the config file should be either comment starting with +.BR # , +or a directory name, or a blacklist specification. Directory names can be prefixed +by +.B \-l +switch, meaning tree walk of the given directory will be only limited to one +filesystem, or +.B \-h +switch, meaning tree walk of the given directory will follow symbolic links. +Blacklist specification should be prefixed by +.B \-b +and optionally also +.B \-l +or +.B \-h +if needed. It should be either absolute directory name (in that case +all files in that directory hierarchy will be blacklisted), absolute filename +(in that case that particular library or binary will not be touched by +prelink) or a glob pattern without +.B / +character in it (then all files matching that glob in any directory +will be blacklisted). +.SH SEE ALSO +.BR ldd (1), +.BR ld.so (8). +.SH BUGS +.LP +.B prelink +Some architectures, including IA-64, HPPA and MIPS, are not yet supported. +.SH AUTHORS +Jakub Jelinek <jakub@redhat.com>. diff --git a/trunk/doc/prelink.conf b/trunk/doc/prelink.conf new file mode 100644 index 0000000..0b0e8ca --- /dev/null +++ b/trunk/doc/prelink.conf @@ -0,0 +1,35 @@ +# This config file contains a list of directories both with binaries +# and libraries prelink should consider by default. +# If a directory name is prefixed with `-l ', the directory hierarchy +# will be walked as long as filesystem boundaries are not crossed. +# If a directory name is prefixed with `-h ', symbolic links in a +# directory hierarchy are followed. +# Directories or files with `-b ' prefix will be blacklisted. +-b *.la +-b *.png +-b *.py +-b *.pl +-b *.pm +-b *.sh +-b *.xml +-b *.xslt +-b *.a +-b *.js +-b /lib/modules +-b /usr/lib/locale +-b /usr/X11R6/lib{,64}/X11/xfig +-l /bin +-l /usr/bin +-l /sbin +-l /usr/sbin +-l /usr/X11R6/bin +-l /usr/kerberos/bin +-l /usr/games +-l /usr/libexec +-l /var/ftp/bin +-l /lib{,64} +-l /usr/lib{,64} +-l /usr/X11R6/lib{,64} +-l /usr/kerberos/lib{,64} +-l /usr/X11R6/LessTif +-l /var/ftp/lib{,64} diff --git a/trunk/doc/prelink.pdf b/trunk/doc/prelink.pdf Binary files differnew file mode 100644 index 0000000..0783007 --- /dev/null +++ b/trunk/doc/prelink.pdf diff --git a/trunk/doc/prelink.tex b/trunk/doc/prelink.tex new file mode 100644 index 0000000..5075030 --- /dev/null +++ b/trunk/doc/prelink.tex @@ -0,0 +1,3643 @@ +\documentclass[twoside]{article} + +\def\docversion{0.7} +% timezone: +01 == CET +\def\timezone{+01} +% Uncomment for draft print. +\def\isdraft{1} + +\newif\ifpdf +\ifx\pdfoutput\undefined + \pdffalse % we are not running PDFLaTeX +\else + \pdfoutput=1 % we are running PDFLaTeX + \pdftrue +\fi + +\usepackage{linuxtag} +\usepackage{times} +\usepackage{makeidx} +\usepackage{nomencl} +\usepackage[square]{natbib} +\usepackage{marvosym} +\usepackage{longtable} +\renewcommand\bibsection{\chapter{\bibname}} + +\ifpdf + \usepackage[pdftex]{graphics} + \usepackage{type1cm} + \usepackage{thumbpdf} + \pdfcompresslevel9 + \pdfinfo{/CreationDate (D:20030924012900\timezone'00')} + % The following code to set /ModDate comes from Heiko Oberdiek's paper + % one PDF & hyperref. I only added the \timezone stuff. + \begingroup + \def\twodigits#1{\ifnum#1<10 0\fi\the#1}% + \count0=\time \divide\count0 by 60 + \edef\x{\twodigits{\count0}}% + \multiply\count0 by 60 + \count1=\time \advance\count1 by -\count0 + \edef\x{\x\twodigits{\count1}}% + \edef\x{/ModDate (D:\the\year \twodigits\month \twodigits\day \x 00\timezone'00')}% + \expandafter\endgroup + \expandafter\pdfinfo\expandafter{\x}% + \input pdfcolor + + %% For a "Draft" mark on the pages uncomment the following: + \ifx\isdraft\undefined + \relax + \else + \usepackage{eso-pic} + \usepackage{color} + \makeatletter + \AddToShipoutPicture{\rm% + \setlength{\@tempdimb}{.5\paperwidth}% + \setlength{\@tempdimc}{.5\paperheight}% + \setlength{\unitlength}{1pt}% + \put(\strip@pt\@tempdimb,\strip@pt\@tempdimc){% + \makebox(0,0){\rotatebox{45}{\textcolor[gray]{0.9}{\fontsize{5cm}{5cm}\selectfont{Draft}}}} + } + } + \makeatother + \fi +\else + \usepackage[dvips]{graphics} +\fi + +\def\titlecolor{NavyBlue} +\makeatletter +\def\@sect#1#2#3#4#5#6[#7]#8{% + \ifnum #2>\c@secnumdepth + \let\@svsec\@empty + \else + \refstepcounter{#1}% + \protected@edef\@svsec{\@seccntformat{#1}\relax}% + \fi + \@tempskipa #5\relax + \ifdim \@tempskipa>\z@ + \begingroup + \hbox{\expandafter\csname\titlecolor\endcsname#6{% + \@hangfrom{\hskip #3\relax\@svsec}% + \interlinepenalty \@M #8\@@par}\Black}% + \endgroup + \csname #1mark\endcsname{#7}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}% + \else + \def\@svsechd{% + \hbox{\expandafter\csname\titlecolor\endcsname#6{\hskip #3\relax + \@svsec #8}% + \csname #1mark\endcsname{#7}\Black}% + \addcontentsline{toc}{#1}{% + \ifnum #2>\c@secnumdepth \else + \protect\numberline{\csname the#1\endcsname}% + \fi + #7}}% + \fi + \@xsect{#5}} +\def\@ssect#1#2#3#4#5{% + \@tempskipa #3\relax + \ifdim \@tempskipa>\z@ + \begingroup + \expandafter\csname\titlecolor\endcsname#4{% + \@hangfrom{\hskip #1}% + \interlinepenalty \@M #5\@@par}\Black% + \endgroup + \else + \def\@svsechd{\expandafter\csname\titlecolor\endcsname#4{\hskip #1\relax #5}\Black}% + \fi + \@xsect{#3}} +\makeatother + +\usepackage{fancyheadings} +\pagestyle{fancy} +\rhead{} +\chead{} +\lhead{} +\rfoot[\sl Prelink]{\thepage} +\lfoot[\thepage]{\sl Jakub Jel\'\i nek} +\ifx\isdraft\undefined +\cfoot{Version \docversion} +\else +\cfoot{Draft \docversion} +\fi +\renewcommand{\headrulewidth}{0.4pt} +\renewcommand{\footrulewidth}{0.4pt} + +\ifx\isdraft\undefined +\relax +\else +\usepackage[mathlines]{lineno} +\fi + +\usepackage{graphicx} +\usepackage{hyperref} +\hypersetup{ + bookmarksnumbered, + bookmarksopen=true, + pdfpagemode=UseOutlines, + pdfkeywords={Prelink, ELF, DSO, Shared Library, Dynamic Linking, Linux} +} +\usepackage{prelinklisting} + +\def\tts#1{\texttt{\small #1}} + +\setcounter{dbltopnumber}{3} + + +\makeatletter +\newcommand{\annotate}[2][]{% + \marginpar{% + \pdfstringdef\x@title{#1}% + \edef\r{\string\r}% + \pdfstringdef\x@contents{#2}% + \pdfannot + width 50em%\linewidth + height .5\baselineskip + depth 2.5\baselineskip + { + /Subtype /Text + /T (\x@title) + /Contents (\x@contents) + }% + } + } +\makeatother + +\makeglossary +\makeindex + +\begin{document} + + \makeatletter + \newcommand\orgmaketitle{} + \let\orgmaketitle\maketitle + \def\maketitle{% + \hypersetup{ + pdftitle={\@title}, + pdfsubject={Description of prelink tool}, + pdfauthor={\@author} + }% + \orgmaketitle + } + \makeatother + +\title{Prelink} +\author{Jakub Jel\'\i nek\\ +Red Hat, Inc.\\ +{\small\tt\href{mailto:jakub@redhat.com}{jakub@redhat.com}}} + +%\maketitle + +%\tableofcontents +%\vfil\break +%\listoftables +%\vfil\break +%\listofprelinklistings +%\vfil\break +%\listoffigures +%\vfil\break + +\maketitle + +\begin{center} +\begin{abstract} +\vspace*{.5\baselineskip} +\parbox{0.8\textwidth}{% +Prelink is a tool designed to speed up dynamic linking of ELF +programs on various Linux architectures. +It speeds up start up of OpenOffice.org 1.1 by 1.8s from 5.5s on 651MHz Pentium III.} +\end{abstract} +\end{center} + +\ifx\isdraft\undefined + \relax +\else + \linenumbers + \linenumbersep4pt +\fi + +\section{Preface} + +In 1995, Linux changed its binary format from \tts{a.out} to \tts{ELF}. +The \tts{a.out} binary format was very inflexible and shared libraries +were pretty hard to build. Linux's shared libraries in \tts{a.out} are position +dependent and each had to be given a unique virtual address space slot +at link time. Maintaining these assignments was pretty hard even when +there were just a few shared libraries, there used to be a central address +registry maintained by humans in form of a text file, but it is certainly +impossible to do these days when there are thousands of different shared libraries +and their size, version and exported symbols are constantly changing. +On the other side, there was just minimum amount of work the dynamic +linker had to do in order to load these shared libraries, as relocation +handling and symbol lookup was only done at link time. The dynamic linker +used the \tts{uselib} system call which just mapped the named library +into the address space (with no segment or section protection differences, +the whole mapping was writable and executable). + +The \href{http://www.caldera.com/developers/devspecs/gabi41.pdf}% +{\tts{ELF}} +\footnote{As described in generic ABI document [1] and various processor +specific ABI supplements [2], [3], [4], [5], [6], [7], [8].} +binary format is one of the most flexible binary formats, +its shared libraries are easy to build and there is no need for a central +assignment of virtual address space slots. Shared libraries are position +independent and relocation handling and symbol lookup are done partly +at the time the executable is created and partly at runtime. Symbols in shared +libraries can be overridden at runtime by preloading a new shared +library defining those symbols or without relinking an executable by adding +symbols to a shared library which is searched up earlier during symbol +lookup or by adding new dependent shared libraries to a library used by the +program. All these improvements have their price, which is a slower +program startup, more non-shareable memory per process and runtime cost +associated with position independent code in shared libraries. + +Program startup of \tts{ELF} programs is slower than startup of \tts{a.out} +programs with shared libraries, because the dynamic linker has much more work +to do before calling program's entry point. The cost of loading libraries +is just slightly bigger, as \tts{ELF} shared libraries have typically +separate read-only and writable segments, so the dynamic linker +has to use different memory protection for each segment. +The main difference is in relocation handling and associated symbol lookup. +In the \tts{a.out} format there was no relocation handling or symbol lookup at runtime. +In \tts{ELF}, this cost is much more important today than it used to be +during \tts{a.out} to \tts{ELF} transition in Linux, as especially GUI +programs keep constantly growing and start to use more and more shared +libraries. 5 years ago programs using more than 10 shared libraries +were very rare, these days most of the GUI programs link against around +40 or more shared and in extreme cases programs use even more than 90 +shared libraries. Every shared library adds its set of dynamic relocations +to the cost and enlarges symbol search scope, +\nomenclature{Symbol Search Scope}{The sequence of \tts{ELF} objects in +which a symbol is being looked up. When a symbol definition is found, +the searching stops and the found symbol is returned. Each program +has a global search scope, which starts by the executable, is typically +followed by the immediate dependencies of the executable and then their +dependencies in breadth search order (where only first occurrence +of each shared library is kept). If \tts{DT\_FILTER} +or \tts{DT\_AUXILIARY} dynamic tags are used the order is slightly +different. Each shared library loaded with \tts{dlopen} has its +own symbol search scope which contains that shared library and +its dependencies. \tts{Prelink} operates also with natural +symbol search scope of each shared library, which is the global +symbol search scope the shared library would have if it were started +as the main program} +so in addition to doing more symbol lookups, each symbol +lookup the application has to perform is on average more expensive. +Another factor increasing the cost is the length of symbol names +which have to be compared when finding symbol in the symbol hash table of +a shared library. C++ libraries tend to have extremely long symbol +names and unfortunately the new \href{http://www.codesourcery.com/cxx-abi/}% +{C++ ABI} puts namespaces and class names first and method names last +in the mangled names, so often symbol names differ only in last +few bytes of very long names. + +Every time a relocation is applied the entire memory page +\nomenclature{Page}{Memory block of fixed size which virtual memory +subsystem deals with as a unit. The size of the page depends on +the addressing hardware of the processor, typically pages are 4K or 8K, +in some cases bigger} +containing the address which is written to must be loaded into memory. +The operating system does a copy-on-write operation which also has the +consequence that the physical memory of the memory page cannot anymore +be shared with other processes. +With \tts{ELF}, typically all of program's Global Offset Table, +\nomenclature{Global Offset Table (\tts{GOT})}{When position independent +code needs to build address which requires dynamic relocation, instead +of building it as constant in registers and applying a dynamic relocation +against the read-only segment (which would mean that any pages of the +read-only segment where relocations are applied cannot be shared between +processes anymore), it loads the address from an offset table +private to each shared library, which is created by the linker. +The table is in writable segment and relocations are applied against it. +Position independent code uses on most architectures a special \tts{PIC} +register which points to the start of the Global Offset Table} +constants and variables containing pointers to objects in shared libraries, etc. +are written into before the dynamic linker passes control over to the program. + +On most architectures (with some exceptions like \tts{AMD64} architecture) +position independent code requires that one register needs to be dedicated as +\tts{PIC} register and thus cannot be used in the functions for other purposes. +This especially degrades performance on register-starved +architectures like \tts{IA-32}. Also, there needs to be some code to +set up the \tts{PIC} register, either invoked as part of function prologues, +or when using function descriptors in the calling sequence. + +\tts{Prelink} is a tool which (together with corresponding dynamic linker +and linker changes) attempts to bring back some of the \tts{a.out} +advantages (such as the speed and less COW'd pages) to the \tts{ELF} +binary format while retaining all of its flexibility. In a limited way +it also attempts to decrease number of non-shareable pages created by +relocations. +\tts{Prelink} works closely with the dynamic linker in the GNU C library, +but probably it wouldn't be too hard to port it to some other \tts{ELF} +using platforms where the dynamic linker can be modified in similar +ways. + +\section{Caching of symbol lookup results} + +Program startup can be speeded up by caching of symbol lookup +results\footnote{Initially, this has been implemented in the \tts{prelink} +tool and \tts{glibc} dynamic linker, where \tts{prelink} was sorting +relocation sections of existing executables and shared libraries. +When this has been implemented in the linker as well and most executables +and shared libraries are already built with \tts{-z combreloc}, +the code from \tts{prelink} has been removed, as it was no longer +needed for most objects and just increasing the tool's complexity.}. +Many shared libraries need more than one lookup of a particular symbol. +This is especially true for C++ shared libraries, where e.g. the same method +is present in multiple virtual tables or {\sl RTTI} data structures. +\nomenclature{RTTI}{C++ runtime type identification} +Traditionally, each \tts{ELF} section which needs dynamic relocations has an +associated \tts{.rela*} or \tts{.rel*} section (depending on whether +the architecture is defined to use \tts{RELA} or \tts{REL} relocations). +\nomenclature{RELA}{Type of relocation structure which includes offset, +relocation type, symbol against which the relocation is and an integer +addend which is added to the symbol. Memory at offset is not supposed +to be used by the relocation. Some architectures got this implemented +incorrectly and memory at offset is for some relocation types used +by the relocation, either in addition to addend or addend is not used +at all. \tts{RELA} relocations are generally better for \tts{prelink}, +since when \tts{prelink} stores a pre-computed value into the memory location +at offset, the addend value is not lost} +\nomenclature{REL}{Type of relocation structure which includes just offset, +relocation type and symbol. Addend is taken from memory location at +offset} +The relocations in those sections are typically sorted by ascending +\tts{r\_offset} values. +Symbol lookups are usually the most expensive operation during program +startup, so caching the symbol lookups has potential to decrease time +spent in the dynamic linker. +One way to decrease the cost of symbol lookups is to create a table with the +size equal to number of entries +in dynamic symbol table (\tts{.dynsym}) in the dynamic linker when resolving +a particular shared library, but that would in some cases need a lot of +memory and some time spent in initializing the table. Another option +would be to use a hash table with chained lists, but that needs both +extra memory and would also take extra time for computation of the hash value +and walking up the chains when doing new lookups. +Fortunately, neither of this is really necessary if we modify the linker +to sort relocations so that relocations against the same symbol +are adjacent. This has been done first in the \tts{Sun} linker and dynamic +linker, so the GNU linker and dynamic linker use the same \tts{ELF} extensions +and linker flags. Particularly, the following new \tts{ELF} dynamic tags have been introduced: + +\tts{\#define DT\_RELACOUNT 0x6ffffff9}\\ +\tts{\#define DT\_RELCOUNT 0x6ffffffa} + +New options \tts{-z combreloc} and \tts{-z nocombreloc} have been +added to the linker. The latter causes the previous linker behavior, +i.e. each section requiring relocations has a corresponding relocation section, +which is sorted by ascending \tts{r\_offset}. \tts{-z combreloc} +\footnote{\tts{-z combreloc} is the default in GNU linker versions +2.13 and later.} instructs the linker to create just one relocation +section for dynamic relocations other than symbol jump table (\tts{PLT}) +relocations. +\nomenclature{PLT}{Process Linkage Table. Stubs in \tts{ELF} shared +libraries and executables which allow lazy relocations of function calls. +They initially point to code which will do the symbol lookup. The +result of this symbol lookup is then stored in the Process Linkage Table +and control transfered to the address symbol lookup returned. All +following calls to the \tts{PLT} slot just branch to the already looked +up address directly, no further symbol lookup is needed} +This single relocation section (either \tts{.rela.dyn} or \tts{.rel.dyn}) +is sorted, so that relative relocations come first (sorted by ascending +\tts{r\_offset}), followed by other relocations, sorted again by ascending +\tts{r\_offset}. If more relocations are against the same +symbol, they immediately follow the first relocation against that symbol +with lowest \tts{r\_offset}. +\footnote{In fact the sorting needs to take into account also the type of +lookup. Most of the relocations will resolve to a \tts{PLT} slot in the executable +if there is one for the lookup symbol, because the executable might have a +pointer against that symbol without any dynamic relocations. But e.g. +relocations used for the \tts{PLT} slots must avoid these.}. +\nomenclature{relative relocation}{Relocation, which doesn't need a symbol +lookup, just adds a shared library load offset to certain memory location +(or locations)} +The number of relative relocations at the beginning of the section +is stored in the \tts{DT\_RELACOUNT} resp. \tts{DT\_RELCOUNT} dynamic tag. + +The dynamic linker can use the new dynamic tag for two purposes. +If the shared library is successfully mapped at the same address +as the first \tts{PT\_LOAD} segment's virtual address, the load offset +is zero and the dynamic linker can avoid all the relative relocations which +would just add zero to various memory locations. Normally shared libraries are +linked with first \tts{PT\_LOAD} segment's virtual address set to zero, so +the load offset is non-zero. This can be changed through a linker script or by +using a special \tts{prelink} option \tts{--reloc-only} to change +the base address of a shared library. All prelinked shared libraries +have non-zero base address as well. If the load offset is non-zero, the +dynamic linker can still make use of this dynamic tag, as relative +relocation handling is typically way simpler than handling other +relocations (since symbol lookup is not necessary) and thus it can +handle all relative relocations in a tight loop in one place and +then handle the remaining relocations with the fully featured +relocation handling routine. The second and more important point is +that if relocations against the same symbol are adjacent, the dynamic +linker can use a cache with single entry. + +The dynamic linker in \tts{glibc}, if it sees \tts{statistics} +as part of the \tts{LD\_DEBUG} environment variable, displays statistics +which can show how useful this optimization is. +Let's look at some big C++ application, e.g. konqueror. +If not using the cache, the statistics looks like this: + +\noindent{\small\begin{verbatim} +18000: runtime linker statistics: +18000: total startup time in dynamic loader: 270886059 clock cycles +18000: time needed for relocation: 266364927 clock cycles (98.3%) +18000: number of relocations: 79067 +18000: number of relocations from cache: 0 +18000: number of relative relocations: 31169 +18000: time needed to load objects: 4203631 clock cycles (1.5%) +\end{verbatim}} + +This program run is with hot caches, on non-prelinked system, with lazy +binding. +\nomenclature{Lazy Binding}{A way to postpone symbol lookups for calls until +a function is called for the first time in particular shared library. +This decreases number of symbol lookups done during startup and symbols +which are never called don't need to be looked up at all. Calls requiring +relocations jump into \tts{PLT}, which is initially set up so that a +function in the dynamic linker is called to do symbol lookup. The looked +up address is then stored either into the \tts{PLT} slot directly +(if \tts{PLT} is writable) or into \tts{GOT} entry corresponding +to the \tts{PLT slot} and any subsequent calls already go directly to that +address. Lazy binding can be turned off by setting \tts{LD\_BIND\_NOW=1} +in the environment. Prelinked programs never use lazy binding for the +executable or any shared libraries not loaded using \tts{dlopen}} +The numbers show that the dynamic linker spent most of its time +in relocation handling and especially symbol lookups. If using symbol +lookup cache, the numbers look different: + +\noindent{\small\begin{verbatim} +18013: total startup time in dynamic loader: 132922001 clock cycles +18013: time needed for relocation: 128399659 clock cycles (96.5%) +18013: number of relocations: 25473 +18013: number of relocations from cache: 53594 +18013: number of relative relocations: 31169 +18013: time needed to load objects: 4202394 clock cycles (3.1%) +\end{verbatim}} + +On average, for one real symbol lookup there were two cache hits and total +time spent in the dynamic linker decreased by 50\%. + +\section{Prelink design} + +\tts{Prelink} was designed, so that it requires as few \tts{ELF} extensions +as possible. It should not be tied to a particular architecture, but +should work on all \tts{ELF} architectures. During program startup it +should avoid all symbol lookups which, as has been shown above, are +very expensive. It needs to work in an environment where shared +libraries and executables are changing from time to time, whether it is +because of security updates or feature enhancements. It should avoid big code +duplication between the dynamic linker and the tool. And prelinked +shared libraries need to be usable even in non-prelinked executables, +or when one of the shared libraries is upgraded and the prelinking of the +executable has not been updated. + +To minimize the number of performed relocations during startup, +the shared libraries (and executables) need to be relocated +already as much as possible. For relative relocations this means the library +needs to be loaded always at the same base address, for other relocations +this means all shared libraries with definitions those relocations resolve +to (often this includes all shared libraries the library or executable depends on) +must always be loaded at the same addresses. \tts{ELF} executables +(with the exception of {\sl Position Independent Executables}) +\nomenclature{Position Independent Executable}{A hybrid between +classical \tts{ELF} executables and \tts{ELF} shared libraries. +It has a form of a \tts{ET\_DYN} object like shared libraries and should +contain position independent code, so that the kernel can load +the executable starting at random address to make certain security attacks +harder. Unlike shared libraries it contains \tts{DT\_DEBUG} dynamic +tag, must have \tts{PT\_INTERP} segment with dynamic linker's path, +must have meaningful code at its \tts{e\_entry} and can use symbol +lookup assumptions normal executables can make, particularly that +no symbol defined in the executable can be overridden by a shared +library symbol} have their load address fixed already during linking. +For shared libraries, \tts{prelink} needs something similar to \tts{a.out} +registry of virtual address space slots. Maintaining such registry +across all installations wouldn't scale well, so \tts{prelink} instead +assigns these virtual address space slots on the fly after looking at +all executables it is supposed to speed up and all their dependent shared +libraries. The next step is to actually relocate shared libraries +to the assigned base address. + +When this is done, the actual prelinking of shared libraries can be done. +First, all dependent shared libraries need to be prelinked (\tts{prelink} +doesn't support circular dependencies between shared libraries, will just +warn about them instead of prelinking the libraries in the cycle), then for each +relocation in the shared library \tts{prelink} needs to look up the symbol +in natural symbol search scope of the shared library (the shared library +itself first, then breadth first search of all dependent shared libraries) and +apply the relocation to the symbol's target section. The symbol lookup code +in the dynamic linker is quite complex and big, so to avoid duplicating all +this, \tts{prelink} has chosen to use dynamic linker to do the symbol lookups. +Dynamic linker is told via a special environment variable it should print +all performed symbol lookups and their type and \tts{prelink} reads this +output through a pipe. As one of the requirements was that +prelinked shared libraries must be usable even for non-prelinked executables +(duplicating all shared libraries so that there are pristine and prelinked +copies would be very unfriendly to RAM usage), \tts{prelink} has to ensure +that by applying the relocation no information is lost and thus relocation +processing can be cheaply done at startup time of non-prelinked executables. +For \tts{RELA} architectures this is easier, because the content +of the relocation's target memory is not needed when processing the relocation. +\footnote{Relative relocations on certain \tts{RELA} architectures use +relocation target's memory, either alone or together with \tts{r\_addend} +field.} For \tts{REL} architectures this is not the case. +\tts{prelink} attempts some tricks described +later and if they fail, needs to convert the \tts{REL} relocation section +to \tts{RELA} format where addend is stored in the relocation section +instead of relocation target's memory. + +When all shared libraries an executable (directly or indirectly) depends on +are prelinked, relocations in the executable are handled similarly to +relocations in shared libraries. Unfortunately, not all symbols resolve the +same when looked up in a shared library's natural symbol search scope +(i.e. as it is done at the time the shared library is prelinked) and when +looked up in application's global symbol search scope. Such symbols are +herein called {\sl conflicts} and the relocations against those symbols +{\sl conflicting relocations}. Conflicts depend on the executable, all its +shared libraries and their respective order. They are only computable +for the shared libraries linked to the executable (libraries mentioned in +\tts{DT\_NEEDED} dynamic tags and shared libraries they transitively need). +The set of shared libraries loaded via \tts{dlopen(3)} cannot be predicted +by \tts{prelink}, neither can the order in which this happened, nor the time +when they are unloaded. When the dynamic linker prints symbol lookups +done in the executable, it also prints conflicts. \tts{Prelink} then +takes all relocations against those symbols and builds a special +\tts{RELA} section with conflict fixups and stores it into the +prelinked executable. Also a list of all dependent shared libraries +in the order they appear in the symbol search scope, together +with their checksums and times of prelinking is stored in another special +section. + +The dynamic linker first checks if it is itself prelinked. If yes, +it can avoid its preliminary relocation processing (this one is done +with just the dynamic linker itself in the search scope, so that +all routines in the dynamic linker can be used easily without too many +limitations). When it is about to start a program, it first looks +at the library list section created by \tts{prelink} (if any) and +checks whether they are present in symbol search scope in the same +order, none have been modified since prelinking and that there aren't any +new shared libraries loaded either. If all these conditions are +satisfied, prelinking can be used. In that case the dynamic linker +processes the fixup section and skips all normal relocation handling. +If one or more of the conditions are not met, the dynamic linker continues +with normal relocation processing in the executable and all shared libraries. + +\section{Collecting executables and libraries which should be prelinked} + +Before the actual work can start the \tts{prelink} tool needs to collect the +filenames of executables and libraries it is supposed to prelink. +It doesn't make any sense to prelink a shared library if no executable is +linked against it because the prelinking information will not be used anyway. +Furthermore, when \tts{prelink} needs to do a \tts{REL} to \tts{RELA} +conversion of relocation sections in the shared library (see later) +or when it needs to convert \tts{SHT\_NOBITS} \tts{PLT} section to +\tts{SHT\_PROGBITS}, a prelinked shared library might grow in size and so +prelinking is only desirable if it will speed up startup of some +program. The only change which might be useful even for shared libraries +which are never linked against, only loaded using \tts{dlopen}, is +relocating to a unique address. This is useful if there are many relative +relocations and there are pages in the shared library's writable segment +which are never written into with the exception of those relative +relocations. Such shared libraries are rare, so \tts{prelink} doesn't +handle these automatically, instead the administrator or developer can +use \tts{prelink --reloc-only={\sl ADDRESS}} to relocate it manually. +Prelinking an executable requires all shared libraries it is linked against +to be prelinked already. + +\tts{Prelink} has two main modes in which it collects filenames. +One is {\sl incremental prelinking}, where \tts{prelink} is invoked without +the \tts{-a} option. In this mode, \tts{prelink} queues for prelinking +all executables and shared libraries given on the command line, all executables +in directory trees specified on the command line, and all shared libraries +those executables and shared libraries are linked against. +For the reasons mentioned earlier a shared library is queued only if a +program is linked with it or the user tells the tool to do it anyway +by explicitly mentioning it on the command line. +The second mode is {\sl full prelinking}, where the \tts{-a} option is +given on the command line. This in addition to incremental prelinking +queues all executables found in directory trees specified in \tts{prelink.conf} +(which typically includes all or most directories where system executables +are found). For each directory subtree in the config file the user +can specify whether symbolic links to places outside of the tree are to be followed +or not and whether searching should continue even across filesystem +boundaries. + +There is also an option to blacklist some executables or directory trees +so that the executables or anything in the directory trees will not +be prelinked. This can be specified either on the command line or in +the config file. + +\tts{Prelink} will not attempt to change executables which use a non-standard +dynamic linker +\footnote{Standard dynamic linker path is hardcoded in the executable for each +architecture. It can be overridden from the command line, but only with +one dynamic linker name (normally, multiple standard dynamic linkers are +used when prelinking mixed architecture systems).} +for security reasons, because it actually needs to execute the dynamic +linker for symbol lookup and it needs to avoid executing some random +unknown executable with the permissions with which \tts{prelink} is run +(typically \tts{root}, with the permissions at least for changing all +executables and shared libraries in the system). The administrator should +ensure that \tts{prelink.conf} doesn't contain world-writable directories +and such directories are not given to the tool on the command line either, +but the tool should be distrustful of the objects nevertheless. + +Also, \tts{prelink} will not change shared libraries which are not specified +directly on the command line or located in the directory trees specified on the +command line or in the config file. This is so that +e.g. \tts{prelink} doesn't try to change shared libraries on shared +networked filesystems, or at least it is possible to configure the tool +so that it doesn't do it. + +For each executable and shared library it collects, \tts{prelink} executes +the dynamic linker to list all shared libraries it depends on, checks if +it is already prelinked and whether any of its dependencies changed. +Objects which are already prelinked and have no dependencies which changed +don't have to be prelinked again (with the exception when e.g. virtual +address space layout code finds out it needs to assign new virtual address space slots +for the shared library or one of its dependencies). Running the dynamic +linker to get the symbol lookup information is a quite costly +operation especially on systems with many executables and shared libraries +installed, so \tts{prelink} offers a faster \tts{-q} mode. In all modes, +\tts{prelink} stores modification and change times of each shared library +and executable together with all object dependencies and other information +into \tts{prelink.cache} file. When prelinking in \tts{-q} mode, it +just compares modification and change times of the executables and shared +libraries (and all their dependencies). Change time is needed because +\tts{prelink} preserves modification time when prelinking (as well as +permissions, owner and group). If the times match, it assumes the +file has not changed since last prelinking. Therefore the file can be +skipped if it is already prelinked and none of the dependencies changed. +If any time changed or one of the dependencies changed, it invokes the +dynamic linker the same way as in normal mode to find out real dependencies, +whether it has been prelinked or not etc. The collecting phase in normal +mode can take a few minutes, while in quick mode usually takes just a few +seconds, as the only operation it does is it calls just lots of \tts{stat} +system calls. + +\section{Assigning virtual address space slots} + +\tts{Prelink} has to ensure at least that for all successfully prelinked +executables all shared libraries they are (transitively) linked against +have non-overlapping virtual address space slots (furthermore they +cannot overlap with the virtual address space range used by the executable +itself, its \tts{brk} area, typical stack location and \tts{ld.so.cache} +and other files mmaped by the dynamic linker in early stages of dynamic +linking (before all dependencies are mmaped). If there were any overlaps, +the dynamic linker (which mmaps the shared libraries at the desired location +without \tts{MAP\_FIXED} mmap flag so that it is only soft requirement) would +not manage to mmap them at the assigned locations and the prelinking +information would be invalidated (the dynamic linker would have to do all +normal relocation handling and symbol lookups). Executables are linked against +very wide variety of shared library combinations and that has to be taken +into account. + +The simplest approach is to sort shared libraries by descending +usage count (so that most often used shared libraries like the dynamic +linker, \tts{libc.so} etc. are close to each other) and assign them +consecutive slots starting at some architecture specific base address +(with a page or two in between the shared libraries to allow for a limited +growth of shared libraries without having to reposition them). +\tts{Prelink} has to find out which shared libraries will need +a \tts{REL} to \tts{RELA} conversion of relocation sections +and for those which will need the conversion count with the increased size +of the library's loadable segments. This is \tts{prelink} behavior without +\tts{-m} and \tts{-R} options. + +The architecture specific base address is best located a few megabytes above +the location where \tts{mmap} with \tts{NULL} first argument and without +\tts{MAP\_FIXED} starts allocating memory areas (in Linux this is the value +of \tts{TASK\_UNMAPPED\_BASE} macro). +\footnote{\tts{TASK\_UNMAPPED\_BASE} has been chosen +on each platform so that there is enough virtual memory for both the +\tts{brk} area (between executable's end and this memory address) and \tts{mmap} +area (between this address and bottom of stack).} The reason for not +starting to assign addresses in \tts{prelink} immediately at +\tts{TASK\_UNMAPPED\_BASE} is that \tts{ld.so.cache} and other mappings by +the dynamic linker will end up in the same range and could overlap with +the shared libraries. Also, if some application uses \tts{dlopen} to load +a shared library which has been prelinked, +\footnote{Typically this is because some other executable is linked against that +shared library directly.} +those few megabytes above \tts{TASK\_UNMAPPED\_BASE} increase the probability +that the stack slot will be still unused (it can clash with e.g. +non-prelinked shared libraries loaded by \tts{dlopen} earlier +\footnote{If shared libraries have first \tts{PT\_LOAD} segment's virtual +address zero, the kernel typically picks first empty slot above +\tts{TASK\_UNMAPPED\_BASE} big enough for the mapping.} or other kinds +of mmap calls with \tts{NULL} first argument like \tts{malloc} allocating +big chunks of memory, mmaping of locale database, etc.). + +This simplest approach is unfortunately problematic on 32-bit (or 31-bit) +architectures where the total virtual address space for a process is +somewhere between 2GB (S/390) and almost 4GB (Linux IA-32 4GB/4GB kernel +split, AMD64 running 32-bit processes, etc.). Typical installations these +days contain thousands of shared libraries and if each of them is given a +unique address space slot, on average executables will have pretty sparse +mapping of its shared libraries and there will be less contiguous virtual +memory for application's own use +\footnote{Especially databases look these days for every byte of virtual +address space on 32-bit architectures.}. + +\tts{Prelink} has a special mode, turned on with \tts{-m} option, in which +it computes what shared libraries are ever loaded together in some executable +(not considering \tts{dlopen}). If two shared libraries are ever loaded +together, \tts{prelink} assigns them different virtual address space slots, +but if they never appear together, it can give them overlapping addresses. +For example applications using \tts{KDE} toolkit link typically against many +\tts{KDE} shared libraries, programs written using the \tts{Gtk+} toolkit +link typically against many \tts{Gtk+} shared libraries, but there are just +very few programs which link against both \tts{KDE} and \tts{Gtk+} shared +libraries, and even if they do, they link against very small subset of those +shared libraries. So all \tts{KDE} shared libraries not in that subset can +use overlapping addresses with all \tts{Gtk+} shared libraries but the +few exceptions. This leads to considerably smaller virtual address space +range used by all prelinked shared libraries, but it has its own +disadvantages too. It doesn't work too well with incremental prelinking, +because then not all executables are investigated, just those which are given +on \tts{prelink}'s command line. \tts{Prelink} also considers executables +in \tts{prelink.cache}, but it has no information about executables which have +not been prelinked yet. If a new executable, which links against some shared +libraries which never appeared together before, is prelinked later, +\tts{prelink} has to assign them new, non-overlapping addresses. +This means that any executables, which linked against the library +that has been moved and re-prelinked, need to be prelinked again. +If this happened during incremental prelinking, \tts{prelink} will +fix up only the executables given on the command line, leaving other +executables untouched. The untouched executables would not be able to +benefit from prelinking anymore. + +Although with the above two layout schemes shared library addresses can +vary slightly between different hosts running the same distribution +(depending on the exact set of installed executables and libraries), especially +the most often used shared libraries will have identical base addresses +on different computers. This is often not desirable for security reasons, +because it makes it slightly easier for various exploits to jump to routines +they want. Standard Linux kernels assign always the same addresses to +shared libraries loaded by the application at each run, so with these +kernels \tts{prelink} doesn't make things worse. But there are kernel +patches, such as Red Hat's \tts{Exec-Shield}, which randomize memory +mappings on each run. If shared libraries are prelinked, they cannot +be assigned different addresses on each run (prelinking information can +be only used to speed up startup if they are mapped at the base addresses +which was used during prelinking), which +means prelinking might not be desirable on some edge servers. +\tts{Prelink} can assign different addresses on different hosts though, +which is almost the same as assigning random addresses on each run +for long running processes such as daemons. Furthermore, the administrator +can force full prelinking and assignment of new random addresses every few +days (if he is also willing to restart the services, so that the old +shared libraries and executables don't have to be kept in memory). + +To assign random addresses \tts{prelink} has the \tts{-R} option. +This causes a random starting address somewhere in the architecture specific +range in which shared libraries are assigned, and minor random reshuffling +in the queue of shared libraries which need address assignment (normally +it is sorted by descending usage count, with randomization shared libraries +which are not very far away from each other in the sorted list can be +swapped). The \tts{-R} option should work orthogonally to the \tts{-m} +option. + +Some architectures have special further requirements on shared library +address assignment. On 32-bit PowerPC, if shared libraries are located +close to the executable, so that everything fits into 32MB area, \tts{PLT} +slots resolving to those shared libraries can use the branch relative +instruction instead of more expensive sequences involving memory load +and indirect branch. If shared libraries are located in the +first 32MB of address space, \tts{PLT} slots resolving to those shared +libraries can use the branch absolute instruction (but already \tts{PLT} +slots in those shared libraries resolving to addresses in the executable +cannot be done cheaply). This means for optimization \tts{prelink} +should assign addresses from a 24MB region below the executable first, assuming +most of the executables are smaller than those remaining 8MB. +\tts{prelink} assigns these from higher to lower addresses. When this +region is full, \tts{prelink} starts from address 0x40000 +\footnote{To leave some pages unmapped to catch \tts{NULL} pointer +dereferences.} up till the bottom of the first area. Only when +all these areas are full, \tts{prelink} starts picking addresses high above +the executable, so that sufficient space is left in between to leave room +for \tts{brk}. +When \tts{-R} option is specified, \tts{prelink} needs to honor it, but +in a way which doesn't totally kill this optimization. So it picks up +a random start base within each of the 3 regions separately, splitting +them into 6 regions. + +Another architecture which needs to be handled specially is IA-32 +when using \tts{Exec-Shield}. The IA-32 architecture doesn't have an +bit to disable execution for each page, only for each segment. All readable +pages are normally executable. This means the stack is usually executable, +as is memory allocated by \tts{malloc}. This is undesirable for security reasons, +exploits can then overflow a buffer on the stack to transfer control +to code it creates on the stack. +Only very few programs actually need an executable stack. For example +programs using GCC trampolines for nested functions need it or when +an application itself creates executable code on the stack and calls it. +\tts{Exec-Shield} works around this IA-32 architecture deficiency +by using a separate code segment, which starts at address 0 and spans +address space until its limit, highest page which needs to +be executable. This is dynamically changed when some page with higher +address than the limit needs to be executable (either because of \tts{mmap} +with \tts{PROT\_EXEC} bit set, or \tts{mprotect} with \tts{PROT\_EXEC} +of an existing mapping). This kind of protection is of course only +effective if the limit is as low as possible. The kernel tries to +put all new mappings with \tts{PROT\_EXEC} set and \tts{NULL} address low. +If possible into {\sl ASCII Shield area} (first 16MB of address space) +\nomenclature{ASCII Shield area}{First 16MB of address space on 32-bit +architectures. These addresses have zeros in upper 8 bits, +which on little endian architectures are stored as last byte of the address +and on big endian architectures as first byte of the address. +A zero byte terminates string, so it is hard to control the exact +arguments of a function if they are placed on the stack above the +address. On big endian machines, it is even hard to control the +low 24 bits of the address}, if not, at least below the executable. +If \tts{prelink} detects \tts{Exec-Shield}, it tries to do the same as +kernel when assigning addresses, i.e. prefers to assign addresses in +{\sl ASCII Shield area} and continues with other addresses below +the program. It needs to leave first 1MB plus 4KB of address space +unallocated though, because that range is often used by programs +using \tts{vm86} system call. + +\section{Relocation of libraries} + +When a shared library has a base address assigned, it needs to be relocated +so that the base address is equal to the first \tts{PT\_LOAD} segment's +\tts{p\_vaddr}. The effect of this operation should be bitwise identical +as if the library were linked with that base address originally. +That is, the following scripts should produce identical output: + +\noindent{{\small\begin{verbatim} +$ gcc -g -shared -o libfoo.so.1.0.0 -Wl,-h,libfoo.so.1 \ + input1.o input2.o somelib.a +$ prelink --reloc-only=0x54321000 libfoo.so.1.0.0 +\end{verbatim} +\prelinklistingcaption{Script to relocate a shared library after linking using \tts{prelink}}} + +and: +\noindent{\small\begin{verbatim} +$ gcc -shared -Wl,--verbose 2>&1 > /dev/null \ + | sed -e '/^======/,/^======/!d' \ + -e '/^======/d;s/0\( + SIZEOF_HEADERS\)/0x54321000\1/' \ + > libfoo.so.lds +$ gcc -Wl,-T,libfoo.so.lds -g -shared -o libfoo.so.1.0.0 \ + -Wl,-h,libfoo.so.1 input1.o input2.o somelib.a +\end{verbatim}} +\prelinklistingcaption{Script to link a shared library at non-standard base}} + +The first script creates a normal shared library with the default +base address 0 and then uses \tts{prelink}'s special mode when it just +relocates a library to a given address. The second script first modifies +a built-in GNU linker script for linking of shared libraries, so that +the base address is the one given instead of zero and stores it into a +temporary file. Then it creates a shared library using that linker script. + +The relocation operation involves mostly adding the difference between +old and new base address to all \tts{ELF} fields which contain values +representing virtual addresses of the shared library +(or in the program header table also representing physical addresses). +File offsets need to be unmodified. Most places where the adjustments +need to be done are clear, \tts{prelink} just has to watch \tts{ELF} spec +to see which fields contain virtual addresses. + +One problem is with absolute symbols. \tts{Prelink} has no way to find +out if an absolute symbol in a shared library is really meant as +absolute and thus not changing during relocation, or if it is an address +of some place in the shared library outside of any section or on their +edge. For instance symbols created in the GNU linker's script outside +of section directives have all \tts{SHN\_ABS} section, yet they can be +location in the library (e.g. \tts{symbolfoo~=~.}) or they can be absolute +(e.g. \tts{symbolbar~=~0x12345000}). This distinction is lost at link +time. But the dynamic linker when looking up symbols doesn't make any +distinction between them, all addresses during dynamic lookup have the +load offset added to it. \tts{Prelink} chooses to relocate any absolute +symbols with value bigger than zero, that way \tts{prelink --reloc-only} +gets bitwise identical output with linking directly at the different base +in almost all real-world cases. Thread Local Storage symbols (those with +\tts{STT\_TLS} type) are never relocated, as their values are relative +to start of shared library's thread local area. + +When relocating the dynamic section there are no bits which tell if +a particular dynamic tag uses \tts{d\_un.d\_ptr} (which needs to +be adjusted) or \tts{d\_un.d\_val} (which needs to be left as is). +So \tts{prelink} has to hardcode a list of well known architecture +independent dynamic tags which need adjusting and have a hook for +architecture specific dynamic tag adjustment. Sun came up with +\tts{DT\_ADDRRNGLO} to \tts{DT\_ADDRRNGHI} and \tts{DT\_VALRNGLO} +to \tts{DT\_VALRNGHI} dynamic tag number ranges, so at least as +long as these ranges are used for new dynamic tags \tts{prelink} +can relocate correctly even without listing them all explicitly. + +When relocating \tts{.rela.*} or \tts{.rel.*} sections, which is +done in architecture specific code, relative relocations and on \tts{.got.plt} +using architectures also \tts{PLT} relocations typically need an +adjustment. The adjustment needs to be done in either \tts{r\_addend} field +of the \tts{ElfNN\_Rela} structure, in the memory pointed by \tts{r\_offset}, +or in both locations. +On some architectures what needs adjusting is not even the same for all relative relocations. +Relative relocations against some sections need to have \tts{r\_addend} +adjusted while others need to have memory adjusted. +On many architectures, first few words in \tts{GOT} are special and some +of them need adjustment. + +The hardest part of the adjustment is handling the debugging sections. +These are non-allocated sections which typically have no corresponding +relocation section associated with them. \tts{Prelink} has to match the various +debuggers in what fields it adjusts and what are skipped. +As of this writing \tts{prelink} should handle +\href{http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf}% +{\tts{DWARF 2} [15]} standard as corrected (and extended) by +\href{http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf}% +{\tts{DWARF 3 draft} [16]}, +\href{http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gdb/doc/stabs.texinfo?cvsroot=src}% +{\tts{Stabs} [17]} with GCC extensions and Alpha or MIPS \tts{Mdebug}. + +\tts{DWARF 2} debugging information involves many separate sections, +each of them with a unique format which needs to be relocated differently. +For relocation of the \tts{.debug\_info} section compilation units \tts{prelink} has to +parse the corresponding part of the \tts{.debug\_abbrev} section, adjust all +values of attributes that are using the \tts{DW\_FORM\_addr} form and adjust embedded +location lists. \tts{.debug\_ranges} and \tts{.debug\_loc} section +portions depend on the exact place in \tts{.debug\_info} section from +which they are referenced, so that \tts{prelink} can keep track of their +base address. \tts{DWARF} debugging format is very extendable, so +\tts{prelink} needs to be very conservative when it sees unknown extensions. +It needs to fail prelinking instead of silently break debugging information +if it sees an unknown \tts{.debug\_*} section, unknown attribute form +or unknown attribute with one of the \tts{DW\_FORM\_block*} forms, as +they can potentially embed addresses which would need adjustment. + +For \tts{stabs} \tts{prelink} tried to match GDB behavior. For +\tts{N\_FUN}, it needs to differentiate between function start and +function address which are both encoded with this type, the rest of types +either always need relocating or never. And similarly to \tts{DWARF 2} +handling, it needs to reject unknown types. + +The relocation code in \tts{prelink} is a little bit more generic +than what is described above, as it is used also by other parts of +\tts{prelink}, when growing sections in a middle of the shared library +during \tts{REL} to \tts{RELA} conversion. All adjustment functions +get passed both the offset it should add to virtual addresses and +a start address. Adjustment is only done if the old virtual address +was bigger or equal than the start address. + +\section{REL to RELA conversion} + +On architectures which normally use the \tts{REL} format for relocations instead +of \tts{RELA} (IA-32, ARM and MIPS), if certain relocation types use the +memory \tts{r\_offset} points to during relocation, \tts{prelink} has to +either convert them to a different relocation type which doesn't use +the memory value, or the whole \tts{.rel.dyn} section needs to be converted +to \tts{RELA} format. Let's describe it on an example on IA-32 architecture: + +\noindent{{\small\begin{verbatim} +$ cat > test1.c <<EOF +extern int i[4]; +int *j = i + 2; +EOF +$ cat > test2.c <<EOF +int i[4]; +EOF +$ gcc -nostdlib -shared -fpic -s -o test2.so test2.c +$ gcc -nostdlib -shared -fpic -o test1.so test1.c ./test2.so +$ readelf -l test1.so | grep LOAD | head -1 + LOAD 0x000000 0x00000000 0x00000000 0x002b8 0x002b8 R E 0x1000 +$ readelf -l test2.so | grep LOAD | head -1 + LOAD 0x000000 0x00000000 0x00000000 0x00244 0x00244 R E 0x1000 +$ readelf -r test1.so + +Relocation section '.rel.dyn' at offset 0x2b0 contains 1 entries: + Offset Info Type Sym.Value Sym. Name +000012b8 00000d01 R_386_32 00000000 i +$ objdump -s -j .data test1.so + +test1.so: file format elf32-i386 + +Contents of section .data: + 12b8 08000000 .... +$ readelf -s test2.so | grep i\$ + 11: 000012a8 16 OBJECT GLOBAL DEFAULT 8 i +$ prelink -N ./test1.so ./test2.so +$ readelf -l test1.so | grep LOAD | head -1 + LOAD 0x000000 0x04dba000 0x04dba000 0x002bc 0x002bc R E 0x1000 +$ readelf -l test2.so | grep LOAD | head -1 + LOAD 0x000000 0x04db6000 0x04db6000 0x00244 0x00244 R E 0x1000 +$ readelf -r test1.so + +Relocation section '.rel.dyn' at offset 0x2b0 contains 1 entries: + Offset Info Type Sym.Value Sym. Name + Addend +04dbb2bc 00000d01 R_386_32 00000000 i + 8 +$ objdump -s -j .data test1.so + +test1.so: file format elf32-i386 + +Contents of section .data: + 4dbb2bc b072db04 .r.. +$ readelf -s test2.so | grep i\$ + 11: 04db72a8 16 OBJECT GLOBAL DEFAULT 8 i +\end{verbatim}} +\prelinklistingcaption{\tts{REL} to \tts{RELA} conversion example}} + +This relocation is against {\sl i + 8}, where the addend is stored at the memory +location pointed by \tts{r\_offset}. \tts{Prelink} assigned base address +0x4dba000 to \tts{test1.so} and 0x4db6000 to \tts{test2.so}. +\tts{Prelink} above converted the \tts{REL} section in \tts{test1.so} to +\tts{RELA}, but let's assume it did not. All output containing {\sl 2bc} +above would change to {\sl 2b8} (that changed above only because \tts{.rel.dyn} +section grew up by 4 bytes during the conversion to \tts{RELA} format), +the rest would stay unchanged. +When some program linked against \tts{test1.so} was prelinked, +the (only) relocation in \tts{test1.so} would not be used and {\sl j} would +contain the right value, 0x4db72b0 (address of {\sl i + 8}; note that IA-32 +is little endian, so the values in .data section are harder to read +for a human). Now, let's assume one of the shared libraries the executable +is linked against is upgraded. This means prelink information cannot +be used, as it is out of date. Let's assume it was a library other +than \tts{test2.so}. Normal relocation processing for \tts{test1.so} +needs to happen. Standard \tts{R\_386\_32} calculation is \tts{S~+~A}, +in this case 0x4db72a8 + 0x4db72b0 = 0x9b6e558 and {\sl j} contains wrong +value. Either \tts{test2.so} could change and now the {\sl i} variable would +have different address, or some other shared library linked to the executable +could overload symbol {\sl i}. Without additional information the dynamic +linker cannot find out the addend is 8. + +The original value of a symbol could perhaps be stored in some special +allocated section and the dynamic linker could do some magic to locate it, +but it would mean standard relocation handling code in the dynamic linker +cannot be used for relocation processing of prelinked shared libraries +where prelinking information cannot be used. +So \tts{prelink} in this case converts the whole \tts{.rel.dyn} section +into the \tts{RELA} format, the addend is stored in \tts{r\_addend} field +and when doing relocation processing, it really doesn't matter what +value is at the memory location pointed by \tts{r\_offset}. +The disadvantage of this is that the relocation section +grew by 50\%. If prelinking information can be used, it shouldn't matter much, +since the section is never loaded at runtime because it is not accessed. +If prelinking cannot be used, whether because it is out of date or +because the shared library has been +loaded by \tts{dlopen}, it will increase memory footprint, but it is read-only +memory which is typically not used after startup and can be discarded +as it is backed out by the file containing the shared library. + +At least on IA-32, \tts{REL} to \tts{RELA} conversion is not always +necessary. If \tts{R\_386\_32} added is originally 0, \tts{prelink} +can instead change its type to \tts{R\_386\_GLOB\_DAT}, which is a +similar dynamic relocation, but calculated as \tts{S} instead of +\tts{S~+~A}. There is no similar conversion for \tts{R\_386\_PC32} +possible though, on the other side this relocation type should never +appear in position independent shared libraries, only in position +dependent code. On ARM, the situation is the same, just using +different relocation names (\tts{R\_ARM\_32}, \tts{R\_ARM\_GLOB\_DAT} +and \tts{R\_ARM\_PC24}). + +The \tts{.rel.plt} section doesn't have to be converted to \tts{RELA} +format on either of these architectures, if the conversion is needed, +all other \tts{.rel.*} allocated sections, which have to be adjacent +as they are pointed to by \tts{DT\_REL} and \tts{DT\_RELSZ} dynamic tags, +have to be converted together. The conversion itself is fairly easy, +some architecture specific code just has to fetch the original addend +from memory pointed by the relocation and store it into \tts{r\_addend} +field (or clear \tts{r\_addend} if the particular relocation type +never uses the addend). The main problem is that when the conversion +happens, the \tts{.rel.dyn} section grows by 50\% and there needs to be +room for that in the read-only loadable segment of the shared library. + +In shared libraries it is always possible to grow the first read-only +\tts{PT\_LOAD} segment by adding the additional data at the beginning +of the read-only segment, as the shared library is relocatable. +\tts{Prelink} can relocate the whole shared library to a higher address +than it has assigned for it. The file offsets of all sections +and the section header table file offset need to be increased, +but the \tts{ELF} header and program headers need to stay at the beginning +of the file. The relocation section can then be moved to the newly created +space between the end of the program header table and the first section. + +Moving the section from the old location to the newly created space +would leave often very big gap in virtual address space as well as in +the file at the old location of the relocation section. Fortunately the +linker typically puts special \tts{ELF} sections including allocated +relocation section before the code section and other read-only sections +under user's control. These special sections are intended for dynamic +linking only. Their addresses are stored just in the \tts{.dynamic} section +and \tts{prelink} can easily adjust them there. There is no need for +a shared library to store address of one of the special sections +into its code or data sections and existing linkers in fact don't create +such references. When growing the relocation section, \tts{prelink} +checks whether all sections before the relocation section are +special +\footnote{As special sections \tts{prelink} considers sections with +\tts{SHT\_NOTE}, \tts{SHT\_HASH}, \tts{SHT\_DYNSYM}, \tts{SHT\_STRTAB}, +\tts{SHT\_GNU\_verdef}, \tts{SHT\_GNU\_verneed}, \tts{SHT\_GNU\_versym}, +\tts{SHT\_REL} or \tts{SHT\_RELA} type or the \tts{.interp} section.} +and if they are, just moves them to lower addresses, so that the +newly created space is right above the relocation section. +The advantage is that instead of moving all sections by the size of +the new relocation section they can be adjusted ideally just by the +difference between old and new relocation section size. + +There are two factors which can increase the necessary adjustment of +all higher sections. The first is required section alignment of any +allocated section above the relocation section. \tts{Prelink} needs +to find the highest section alignment among those sections and +increase the adjustment from the difference between old and new +relocation section up to the next multiple of that alignment. + +The second factor is only relevant to shared libraries where linker +optimized the data segment placement. Traditionally linker assigned +the end address of the read-only segment plus the architecture's +maximum \tts{ELF} page size as the start address of the read-write +segment. While this created smallest file sizes of the shared libraries, +it often wasted one page in the read-write segment because of partial +pages. When linker optimizes such that less space is wasted in partial +pages, the distance between read-only and read-write segments can be +smaller than architecture specific maximum \tts{ELF} page size. +\tts{Prelink} has to take this into account, so that when adjusting +the sections the read-only and read-write segment don't end up on the +same page. Unfortunately \tts{prelink} cannot increase or decrease +the distance between the read-only and read-write segments, since +it is possible that the shared library has relative addresses of +any allocated code, data or \tts{.bss} sections +stored in its sections without any relocations which would allow +\tts{prelink} to change them. \tts{Prelink} has to move all sections +starting with the first allocated \tts{SHT\_PROGBITS} section other +than \tts{.interp} up to the last allocated \tts{SHT\_PROGBITS} or +\tts{SHT\_NOBITS} section as a block and thus needs to increase +the adjustment in steps of the highest section alignment as many times +times as needed so that the segments end up in different pages. +Below are 3 examples: + +\noindent{{\small\begin{verbatim} +$ cat > test1.c <<EOF +int i[2] __attribute__((aligned (32))); +#define J1(N) int *j##N = &i[1]; +#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4) +#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4) +#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4) +J4(0) J4(1) J3(2) J3(3) J1(4) +const int l[256] = { [10] = 1 }; +/* Put a zero sized section at the end of read-only segment, + so that the end address of the segment is printed. */ +asm (".section ro_seg_end, \"a\"; .previous"); +EOF +$ gcc -shared -O2 -nostdlib -fpic -o test1.so test1.c +$ readelf -S test1.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 000000b4 0000b4 000930 04 A 2 0 4 + [ 2] .dynsym DYNSYM 000009e4 0009e4 001430 10 A 3 d 4 + [ 3] .dynstr STRTAB 00001e14 001e14 000735 00 A 0 0 1 + [ 4] .rel.dyn REL 0000254c 00254c 000968 08 A 2 0 4 + [ 5] .text PROGBITS 00002eb4 002eb4 000000 00 AX 0 0 4 + [ 6] .rodata PROGBITS 00002ec0 002ec0 000400 00 A 0 0 32 + [ 7] ro_seg_end PROGBITS 000032c0 0032c0 000000 00 A 0 0 1 + [ 8] .data PROGBITS 000042c0 0032c0 0004b4 00 WA 0 0 4 + [ 9] .dynamic DYNAMIC 00004774 003774 000070 08 WA 3 0 4 + [10] .got PROGBITS 000047e4 0037e4 00000c 04 WA 0 0 4 + [11] .bss NOBITS 00004800 003800 000008 00 WA 0 0 32 + [12] .comment PROGBITS 00000000 003800 000033 00 0 0 1 + [13] .shstrtab STRTAB 00000000 003833 000075 00 0 0 1 + [14] .symtab SYMTAB 00000000 003b28 001470 10 15 11 4 + [15] .strtab STRTAB 00000000 004f98 000742 00 0 0 1 +$ readelf -l test1.so | grep LOAD + LOAD 0x000000 0x00000000 0x00000000 0x032c0 0x032c0 R E 0x1000 + LOAD 0x0032c0 0x000042c0 0x000042c0 0x00530 0x00548 RW 0x1000 +$ prelink -N ./test1.so +$ readelf -l test1.so | grep LOAD + LOAD 0x000000 0x02000000 0x02000000 0x03780 0x03780 R E 0x1000 + LOAD 0x003780 0x02004780 0x02004780 0x00530 0x00548 RW 0x1000 +$ readelf -S test1.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 020000b4 0000b4 000930 04 A 2 0 4 + [ 2] .dynsym DYNSYM 020009e4 0009e4 001430 10 A 3 d 4 + [ 3] .dynstr STRTAB 02001e14 001e14 000735 00 A 0 0 1 + [ 4] .rel.dyn RELA 0200254c 00254c 000e1c 0c A 2 0 4 + [ 5] .text PROGBITS 02003374 003374 000000 00 AX 0 0 4 + [ 6] .rodata PROGBITS 02003380 003380 000400 00 A 0 0 32 + [ 7] ro_seg_end PROGBITS 02003780 003780 000000 00 A 0 0 1 + [ 8] .data PROGBITS 02004780 003780 0004b4 00 WA 0 0 4 + [ 9] .dynamic DYNAMIC 02004c34 003c34 000070 08 WA 3 0 4 + [10] .got PROGBITS 02004ca4 003ca4 00000c 04 WA 0 0 4 + [11] .bss NOBITS 02004cc0 003cc0 000008 00 WA 0 0 32 + [12] .comment PROGBITS 00000000 003cc0 000033 00 0 0 1 + [13] .gnu.liblist GNU_LIBLIST 00000000 003cf3 000000 14 14 0 4 + [14] .gnu.libstr STRTAB 00000000 003cf3 000000 00 0 0 1 + [15] .gnu.prelink_undo PROGBITS 00000000 003cf4 00030c 01 0 0 4 + [16] .shstrtab STRTAB 00000000 004003 0000a0 00 0 0 1 + [17] .symtab SYMTAB 00000000 0043a0 001470 10 18 11 4 + [18] .strtab STRTAB 00000000 005810 000742 00 0 0 1 +\end{verbatim}} +\prelinklistingcaption{Growing read-only segment with segment distance one page}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=0.8\textwidth]{dso1} +\caption{Growing read-only segment with segment distance one page} +\end{figure} + +In this example the read-write segment starts at address \tts{0x42c0}, which +is one page above the end of read-only segment. \tts{Prelink} needs to grow +the read-only \tts{PT\_LOAD} segment by 50\% of \tts{.rel.dyn} size, i.e. +\tts{0x4b4} bytes. \tts{Prelink} just needs to round that up for the +highest alignment (32 bytes required by \tts{.rodata} or \tts{.bss} +sections) and moves all sections above \tts{.rel.dyn} by \tts{0x4c0} bytes. + +\noindent{{\small\begin{verbatim} +$ cat > test2.c <<EOF +int i[2] __attribute__((aligned (32))); +#define J1(N) int *j##N = &i[1]; +#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4) +#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4) +#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4) +J4(0) J4(1) J3(2) J3(3) J1(4) +const int l[256] = { [10] = 1 }; +int k[670]; +asm (".section ro_seg_end, \"a\"; .previous"); +EOF +$ gcc -shared -O2 -nostdlib -fpic -o test2.so test2.c +$ readelf -S test2.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 000000b4 0000b4 000934 04 A 2 0 4 + [ 2] .dynsym DYNSYM 000009e8 0009e8 001440 10 A 3 d 4 + [ 3] .dynstr STRTAB 00001e28 001e28 000737 00 A 0 0 1 + [ 4] .rel.dyn REL 00002560 002560 000968 08 A 2 0 4 + [ 5] .text PROGBITS 00002ec8 002ec8 000000 00 AX 0 0 4 + [ 6] .rodata PROGBITS 00002ee0 002ee0 000400 00 A 0 0 32 + [ 7] ro_seg_end PROGBITS 000032e0 0032e0 000000 00 A 0 0 1 + [ 8] .data PROGBITS 00004000 004000 0004b4 00 WA 0 0 4 + [ 9] .dynamic DYNAMIC 000044b4 0044b4 000070 08 WA 3 0 4 + [10] .got PROGBITS 00004524 004524 00000c 04 WA 0 0 4 + [11] .bss NOBITS 00004540 004540 000a88 00 WA 0 0 32 + [12] .comment PROGBITS 00000000 004540 000033 00 0 0 1 + [13] .shstrtab STRTAB 00000000 004573 000075 00 0 0 1 + [14] .symtab SYMTAB 00000000 004868 001480 10 15 11 4 + [15] .strtab STRTAB 00000000 005ce8 000744 00 0 0 1 +$ readelf -l test2.so | grep LOAD + LOAD 0x000000 0x00000000 0x00000000 0x032e0 0x032e0 R E 0x1000 + LOAD 0x004000 0x00004000 0x00004000 0x00530 0x00fc8 RW 0x1000 +$ prelink -N ./test2.so +$ readelf -l test2.so | grep LOAD + LOAD 0x000000 0x02000000 0x02000000 0x037a0 0x037a0 R E 0x1000 + LOAD 0x0044c0 0x020044c0 0x020044c0 0x00530 0x00fc8 RW 0x1000 +$ readelf -S test2.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 020000b4 0000b4 000934 04 A 2 0 4 + [ 2] .dynsym DYNSYM 020009e8 0009e8 001440 10 A 3 d 4 + [ 3] .dynstr STRTAB 02001e28 001e28 000737 00 A 0 0 1 + [ 4] .rel.dyn RELA 02002560 002560 000e1c 0c A 2 0 4 + [ 5] .text PROGBITS 02003388 003388 000000 00 AX 0 0 4 + [ 6] .rodata PROGBITS 020033a0 0033a0 000400 00 A 0 0 32 + [ 7] ro_seg_end PROGBITS 020037a0 0037a0 000000 00 A 0 0 1 + [ 8] .data PROGBITS 020044c0 0044c0 0004b4 00 WA 0 0 4 + [ 9] .dynamic DYNAMIC 02004974 004974 000070 08 WA 3 0 4 + [10] .got PROGBITS 020049e4 0049e4 00000c 04 WA 0 0 4 + [11] .bss NOBITS 02004a00 004a00 000a88 00 WA 0 0 32 + [12] .comment PROGBITS 00000000 004a00 000033 00 0 0 1 + [13] .gnu.liblist GNU_LIBLIST 00000000 004a33 000000 14 14 0 4 + [14] .gnu.libstr STRTAB 00000000 004a33 000000 00 0 0 1 + [15] .gnu.prelink_undo PROGBITS 00000000 004a34 00030c 01 0 0 4 + [16] .shstrtab STRTAB 00000000 004d43 0000a0 00 0 0 1 + [17] .symtab SYMTAB 00000000 0050e0 001480 10 18 11 4 + [18] .strtab STRTAB 00000000 006560 000744 00 0 0 1 +\end{verbatim}} +\prelinklistingcaption{Growing read-only segment not requiring additional padding}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=0.8\textwidth]{dso2} +\caption{Growing read-only segment not requiring additional padding} +\end{figure} + +In the second example \tts{prelink} can grow by just \tts{0x4c0} bytes as +well, eventhough the distance between read-write and read-only segment +is just \tts{0xd20} bytes. With this distance, hypothetical adjustment +by any size less than \tts{0xd21} bytes (modulo 4096) would need just +rounding up to the next multiple of 32 bytes, while adjustments +from \tts{0xd21} up to \tts{0xfe0} would require adjustments in +multiples of 4096 bytes. + +\noindent{{\small\begin{verbatim} +$ cat > test3.c <<EOF +int i[2] __attribute__((aligned (32))); +#define J1(N) int *j##N = &i[1]; +#define J2(N) J1(N##0) J1(N##1) J1(N##2) J1(N##3) J1(N##4) +#define J3(N) J2(N##0) J2(N##1) J2(N##2) J2(N##3) J2(N##4) +#define J4(N) J3(N##0) J3(N##1) J3(N##2) J3(N##3) J3(N##4) +J4(0) J4(1) J3(2) J3(3) J1(4) +int k[670]; +asm (".section ro_seg_end, \"a\"; .previous"); +EOF +$ gcc -shared -O2 -nostdlib -fpic -o test3.so test3.c +$ readelf -S test3.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 000000b4 0000b4 00092c 04 A 2 0 4 + [ 2] .dynsym DYNSYM 000009e0 0009e0 001420 10 A 3 c 4 + [ 3] .dynstr STRTAB 00001e00 001e00 000735 00 A 0 0 1 + [ 4] .rel.dyn REL 00002538 002538 000968 08 A 2 0 4 + [ 5] .text PROGBITS 00002ea0 002ea0 000000 00 AX 0 0 4 + [ 6] ro_seg_end PROGBITS 00002ea0 002ea0 000000 00 A 0 0 1 + [ 7] .data PROGBITS 00003000 003000 0004b4 00 WA 0 0 4 + [ 8] .dynamic DYNAMIC 000034b4 0034b4 000070 08 WA 3 0 4 + [ 9] .got PROGBITS 00003524 003524 00000c 04 WA 0 0 4 + [10] .bss NOBITS 00003540 003540 000a88 00 WA 0 0 32 + [11] .comment PROGBITS 00000000 003540 000033 00 0 0 1 + [12] .shstrtab STRTAB 00000000 003573 00006d 00 0 0 1 + [13] .symtab SYMTAB 00000000 003838 001460 10 14 10 4 + [14] .strtab STRTAB 00000000 004c98 000742 00 0 0 1 +$ readelf -l test3.so | grep LOAD + LOAD 0x000000 0x00000000 0x00000000 0x02ea0 0x02ea0 R E 0x1000 + LOAD 0x003000 0x00003000 0x00003000 0x00530 0x00fc8 RW 0x1000 +$ prelink -N ./test3.so +$ readelf -l test3.so | grep LOAD + LOAD 0x000000 0x02000000 0x02000000 0x03ea0 0x03ea0 R E 0x1000 + LOAD 0x004000 0x02004000 0x02004000 0x00530 0x00fc8 RW 0x1000 +$ readelf -S test3.so | grep '^ \[' + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .hash HASH 020000b4 0000b4 00092c 04 A 2 0 4 + [ 2] .dynsym DYNSYM 020009e0 0009e0 001420 10 A 3 c 4 + [ 3] .dynstr STRTAB 02001e00 001e00 000735 00 A 0 0 1 + [ 4] .rel.dyn RELA 02002538 002538 000e1c 0c A 2 0 4 + [ 5] .text PROGBITS 02003ea0 003ea0 000000 00 AX 0 0 4 + [ 6] ro_seg_end PROGBITS 02003ea0 003ea0 000000 00 A 0 0 1 + [ 7] .data PROGBITS 02004000 004000 0004b4 00 WA 0 0 4 + [ 8] .dynamic DYNAMIC 020044b4 0044b4 000070 08 WA 3 0 4 + [ 9] .got PROGBITS 02004524 004524 00000c 04 WA 0 0 4 + [10] .bss NOBITS 02004540 004540 000a88 00 WA 0 0 32 + [11] .comment PROGBITS 00000000 004540 000033 00 0 0 1 + [12] .gnu.liblist GNU_LIBLIST 00000000 004573 000000 14 13 0 4 + [13] .gnu.libstr STRTAB 00000000 004573 000000 00 0 0 1 + [14] .gnu.prelink_undo PROGBITS 00000000 004574 0002e4 01 0 0 4 + [15] .shstrtab STRTAB 00000000 00485b 000098 00 0 0 1 + [16] .symtab SYMTAB 00000000 004bc8 001460 10 17 10 4 + [17] .strtab STRTAB 00000000 006028 000742 00 0 0 1 +\end{verbatim}} +\prelinklistingcaption{Growing read-only segment if page padding needed}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=0.8\textwidth]{dso3} +\caption{Growing read-only segment if page padding needed} +\end{figure} + +In the last example the distance between \tts{PT\_LOAD} segments is very +small, just \tts{0x160} bytes and the adjustment had to be done by 4096 +bytes. + +% Fortunately, shared libraries are position independent, so all absolute +% values in them are either stored in well known \tts{ELF} structures, +% or have corresponding dynamic relocations. The only problem might be +% with relative relocations, which are resolved at link time. +% The start of read-only \tts{PT\_LOAD} segment of shared libraries is +% typically used by special sections used by the dynamic linker +% (\tts{.hash}, \tts{.dynsym}, \tts{.dynstr}, \tts{.gnu.version*}, +% \tts{.rel*}, \tts{.note*}). It makes no sense for a shared library to +% have relocations against these sections or some addresses inside of them, +% furthermore it is impossible to do it without specially crafted +% linker script. So \tts{prelink} makes the assumption that it can grow +% freely the shared library after \tts{.rel.dyn} section, as long +% as only sections mentioned above come before \tts{.rel.dyn} (it actually +% checks section types, not names). \tts{Prelink} certainly can grow the shared library +% size in multiplies of \tts{ELF} architecture specific maximum page size, +% but usually it can do better. Particularly, \tts{prelink} can grow by the 50\% size +% of \tts{.rel.dyn} section rounded up to the largest section alignment +% in all sections following it, but it has to make sure that two +% different \tts{PT\_LOAD} segments (typically the read-only and read-write) +% will not share the same page, otherwise it needs to grow it more in +% multiplies of the maximum section alignment until they are on different +% pages. Growing is done by using the shared library relocation code with +% start address set to end of \tts{.rel.dyn} section. \tts{.rel.plt} +% section is then moved right to the end of \tts{.rel.dyn} section, +% \tts{.dynamic} section needs updating all addresses, type of +% relocation section, segment table needs to be adjusted accordingly +% and file offsets in section header table as well. + +\section{Conflicts} + +As said earlier, if symbol lookup of some symbol in particular shared +library results in different values when that shared library's natural +search scope is used and when using search scope of the application the +DSO is used in, this is considered a {\sl conflict}. +Here is an example of a conflict on IA-32: + +\noindent{{\small\begin{verbatim} +$ cat > test1.c <<EOF +int i; +int *j = &i; +int *foo (void) { return &i; } +EOF +$ cat > test2.c <<EOF +int i; +int *k = &i; +int *bar (void) { return &i; } +EOF +$ cat > test.c <<EOF +#include <stdio.h> +extern int i, *j, *k, *foo (void), bar (void); +int main (void) +{ +#ifdef PRINT_I + printf ("%p\n", &i); +#endif + printf ("%p %p %p %p\n", j, k, foo (), bar ()); +} +EOF +$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c +$ gcc -nostdlib -shared -fpic -o test2.so test2.c ./test1.so +$ gcc -o test test.c ./test2.so ./test1.so +$ ./test +0x16137c 0x16137c 0x16137c 0x16137c +$ readelf -r ./test1.so + +Relocation section '.rel.dyn' at offset 0x2bc contains 2 entries: + Offset Info Type Sym.Value Sym. Name +000012e4 00000d01 R_386_32 00001368 i +00001364 00000d06 R_386_GLOB_DAT 00001368 i +$ prelink -N ./test ./test1.so ./test2.so +$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test1.so + ./test1.so => ./test1.so (0x04db6000, 0x00000000) +$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test2.so + ./test2.so => ./test2.so (0x04dba000, 0x00000000) + ./test1.so => ./test1.so (0x04db6000, 0x00000000) +$ LD_WARN= LD_TRACE_PRELINKING=1 LD_BIND_NOW=1 /lib/ld-linux.so.2 ./test \ + | sed 's/^[[:space:]]*/ /' + ./test => ./test (0x08048000, 0x00000000) + ./test2.so => ./test2.so (0x04dba000, 0x00000000) + ./test1.so => ./test1.so (0x04db6000, 0x00000000) + libc.so.6 => /lib/tls/libc.so.6 (0x00b22000, 0x00000000) TLS(0x1, 0x00000028) + /lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x00b0a000, 0x00000000) +$ readelf -S ./test1.so | grep '\.data\|\.got' + [ 6] .data PROGBITS 04db72e4 0002e4 000004 00 WA 0 0 4 + [ 8] .got PROGBITS 04db7358 000358 000010 04 WA 0 0 4 +$ readelf -r ./test1.so + +Relocation section '.rel.dyn' at offset 0x2bc contains 2 entries: + Offset Info Type Sym.Value Sym. Name +04db72e4 00000d06 R_386_GLOB_DAT 04db7368 i +04db7364 00000d06 R_386_GLOB_DAT 04db7368 i +$ objdump -s -j .got -j .data test1.so + +test1.so: file format elf32-i386 + +Contents of section .data: + 4db72e4 6873db04 hs.. +Contents of section .got: + 4db7358 e8120000 00000000 00000000 6873db04 ............hs.. +$ readelf -r ./test | sed '/\.gnu\.conflict/,$!d' +Relocation section '.gnu.conflict' at offset 0x7ac contains 18 entries: + Offset Info Type Sym.Value Sym. Name + Addend +04db72e4 00000001 R_386_32 04dbb37c +04db7364 00000001 R_386_32 04dbb37c +00c56874 00000001 R_386_32 fffffff0 +00c56878 00000001 R_386_32 00000001 +00c568bc 00000001 R_386_32 fffffff4 +00c56900 00000001 R_386_32 ffffffec +00c56948 00000001 R_386_32 ffffffdc +00c5695c 00000001 R_386_32 ffffffe0 +00c56980 00000001 R_386_32 fffffff8 +00c56988 00000001 R_386_32 ffffffe4 +00c569a4 00000001 R_386_32 ffffffd8 +00c569c4 00000001 R_386_32 ffffffe8 +00c569d8 00000001 R_386_32 080485b8 +00b1f510 00000007 R_386_JUMP_SLOT 00b91460 +00b1f514 00000007 R_386_JUMP_SLOT 00b91080 +00b1f518 00000007 R_386_JUMP_SLOT 00b91750 +00b1f51c 00000007 R_386_JUMP_SLOT 00b912c0 +00b1f520 00000007 R_386_JUMP_SLOT 00b91200 +$ ./test +0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c +\end{verbatim}} +\prelinklistingcaption{Conflict example}} + +In the example, among some conflicts caused by the dynamic linker and the C library, +\footnote{Particularly in the example, the 5 \tts{R\_386\_JUMP\_SLOT} fixups +are \tts{PLT} slots in the dynamic linker for memory allocator functions +resolving to C library functions instead of dynamic linker's own trivial +implementation. First 10 \tts{R\_386\_32} fixups at offsets 0xc56874 +to 0xc569c4 are Thread Local Storage fixups in the C library and +the fixup at 0xc569d8 is for {\sl \_IO\_stdin\_used} weak undefined symbol +in the C library, resolving to a symbol with the same name in the executable.} +there is a conflict for the symbol {\sl i} in \tts{test1.so} shared library. +\tts{test1.so} has just itself in its natural symbol lookup scope (as proved +by + +\tts{LD\_WARN= LD\_TRACE\_PRELINKING=1 LD\_BIND\_NOW=1 /lib/ld-linux.so.2 ./test1.so} + +command output), so when looking up symbol {\sl i} in this +scope the definition in \tts{test1.so} is chosen. \tts{test1.so} has two +relocations against the symbol {\sl i}, one \tts{R\_386\_32} against \tts{.data} +section and one \tts{R\_386\_GLOB\_DAT} against \tts{.got} section. When +prelinking \tts{test1.so} library, the dynamic linker stores the address of +{\sl i} (0x4db7368) into both locations (at offsets 0x4db72e4 and 0x4db7364). +The global symbol search scope in \tts{test} executable contains the executable +itself, \tts{test2.so} and \tts{test1.so} libraries, \tts{libc.so.6} and +the dynamic linker in the listed order. +When doing symbol lookup for symbol {\sl i} +in \tts{test1.so} when doing relocation processing of the whole executable, +address of {\sl i} in \tts{test2.so} is returned as that symbol comes earlier +in the global search scope. So, when none of the libraries nor the executable +is prelinked, the program prints 4 identical addresses. If prelink didn't +create conflict fixups for the two relocations against the symbol {\sl i} +in \tts{test1.so}, prelinked executable (which bypasses normal relocation +processing on startup) would print instead of the desired + +\tts{0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c} + +different addresses, + +\tts{0x4db7368 0x4dbb37c 0x4db7368 0x4dbb37c} + +That is a functionality change that \tts{prelink} cannot be permitted to +make, so instead it fixes up the two locations by storing the desired +value in there. In this case \tts{prelink} really cannot avoid that +- \tts{test1.so} shared library could be also used without \tts{test2.so} +in some other executable's symbol search scope. +Or there could be some executable linked with: + +\noindent{{\small\begin{verbatim} +$ gcc -o test2 test.c ./test1.so ./test2.so +\end{verbatim}} +\prelinklistingcaption{Conflict example with swapped order of libraries}} + +where {\sl i} lookup in \tts{test1.so} and \tts{test2.so} is supposed +to resolve to {\sl i} in \tts{test1.so}. + +Now consider what happens if the executable is linked with \tts{-DPRINT\_I}: + +\noindent{{\small\begin{verbatim} +$ gcc -DPRINT_I -o test3 test.c ./test2.so ./test1.so +$ ./test3 +0x804972c +0x804972c 0x804972c 0x804972c 0x804972c +$ prelink -N ./test3 ./test1.so ./test2.so +$ readelf -S ./test2.so | grep '\.data\|\.got' + [ 6] .data PROGBITS 04dbb2f0 0002f0 000004 00 WA 0 0 4 + [ 8] .got PROGBITS 04dbb36c 00036c 000010 04 WA 0 0 4 +$ readelf -r ./test2.so + +Relocation section '.rel.dyn' at offset 0x2c8 contains 2 entries: + Offset Info Type Sym.Value Sym. Name +04dbb2f0 00000d06 R_386_GLOB_DAT 04dbb37c i +04dbb378 00000d06 R_386_GLOB_DAT 04dbb37c i +$ objdump -s -j .got -j .data test2.so + +test2.so: file format elf32-i386 + +Contents of section .data: + 4dbb2f0 7cb3db04 |... +Contents of section .got: + 4dbb36c f4120000 00000000 00000000 7cb3db04 ............|... +$ readelf -r ./test3 + +Relocation section '.rel.dyn' at offset 0x370 contains 4 entries: + Offset Info Type Sym.Value Sym. Name +08049720 00000e06 R_386_GLOB_DAT 00000000 __gmon_start__ +08049724 00000105 R_386_COPY 08049724 j +08049728 00000305 R_386_COPY 08049728 k +0804972c 00000405 R_386_COPY 0804972c i + +Relocation section '.rel.plt' at offset 0x390 contains 4 entries: + Offset Info Type Sym.Value Sym. Name +08049710 00000607 R_386_JUMP_SLOT 080483d8 __libc_start_main +08049714 00000707 R_386_JUMP_SLOT 080483e8 printf +08049718 00000807 R_386_JUMP_SLOT 080483f8 foo +0804971c 00000c07 R_386_JUMP_SLOT 08048408 bar + +Relocation section '.gnu.conflict' at offset 0x7f0 contains 20 entries: + Offset Info Type Sym.Value Sym. Name + Addend +04dbb2f0 00000001 R_386_32 0804972c +04dbb378 00000001 R_386_32 0804972c +04db72e4 00000001 R_386_32 0804972c +04db7364 00000001 R_386_32 0804972c +00c56874 00000001 R_386_32 fffffff0 +00c56878 00000001 R_386_32 00000001 +00c568bc 00000001 R_386_32 fffffff4 +00c56900 00000001 R_386_32 ffffffec +00c56948 00000001 R_386_32 ffffffdc +00c5695c 00000001 R_386_32 ffffffe0 +00c56980 00000001 R_386_32 fffffff8 +00c56988 00000001 R_386_32 ffffffe4 +00c569a4 00000001 R_386_32 ffffffd8 +00c569c4 00000001 R_386_32 ffffffe8 +00c569d8 00000001 R_386_32 080485f0 +00b1f510 00000007 R_386_JUMP_SLOT 00b91460 +00b1f514 00000007 R_386_JUMP_SLOT 00b91080 +00b1f518 00000007 R_386_JUMP_SLOT 00b91750 +00b1f51c 00000007 R_386_JUMP_SLOT 00b912c0 +00b1f520 00000007 R_386_JUMP_SLOT 00b91200 +$ ./test3 +0x804972c +0x804972c 0x804972c 0x804972c 0x804972c +\end{verbatim}} +\prelinklistingcaption{Conflict example with COPY relocation for conflicting symbol}} + +Because the executable is not compiled as position independent code and +\tts{main} function takes address of {\sl i} variable, the object +file for \tts{test3.c} contains a \tts{R\_386\_32} relocation against +{\sl i}. The linker cannot make dynamic relocations against read-only +segment in the executable, so the address of {\sl i} must be constant. +This is accomplished by creating a new object {\sl i} in the executable's +\tts{.dynbss} section and creating a dynamic \tts{R\_386\_COPY} relocation +for it. The relocation ensures that during startup the content of +{\sl i} object earliest in the search scope without the executable +is copied to this {\sl i} object in executable. Now, unlike \tts{test} +executable, in \tts{test3} executable {\sl i} lookups in both \tts{test1.so} +and \tts{test2.so} libraries result in address of {\sl i} in the executable +(instead of \tts{test2.so}). This means that two conflict fixups +are needed again for \tts{test1.so} (but storing 0x804972c instead of +0x4dbb37c) and two new fixups are needed for \tts{test2.so}. + +If the executable is compiled as position independent code, + +\noindent{{\small\begin{verbatim} +$ gcc -fpic -DPRINT_I -o test4 test.c ./test2.so ./test1.so +$ ./test4 +0x4dbb37c +0x4dbb37c 0x4dbb37c 0x4dbb37c 0x4dbb37c +\end{verbatim}} +\prelinklistingcaption{Conflict example with position independent code in the executable}} + +the address of {\sl i} is stored in executable's \tts{.got} section, +which is writable and thus can have dynamic relocation against it. +So the linker creates a \tts{R\_386\_GLOB\_DAT} relocation against +the \tts{.got} section, the symbol {\sl i} is undefined in the executable +and no copy relocations are needed. In this case, only \tts{test1.so} +will need 2 fixups, \tts{test2.so} will not need any. + +There are various reasons for conflicts: +\begin{itemize} +\item Improperly linked shared libraries. If a shared library always needs +symbols from some particular shared library, it should be linked against +that library, usually by adding \tts{-lLIBNAME} to \tts{gcc -shared} command +line used during linking of the shared library. This both reduces conflict +fixups in \tts{prelink} and makes the library easier to load using +\tts{dlopen}, because applications don't have to remember that they have +to load some other library first. The best place to record the dependency +is in the shared library itself. Another reason is if the needed library +uses symbol versioning for its symbols. Not linking against that library +can result in malfunctioning shared library. \tts{Prelink} issues a warning for +such libraries - \tts{Warning: {\sl library} has undefined non-weak symbols}. +When linking a shared library, the \tts{-Wl,-z,defs} option can be used to +ensure there are no such undefined non-weak symbols. There are exceptions, +when undefined non-weak symbols in shared libraries are desirable. +One exception is when there are multiple shared libraries providing the +same functionality, and a shared library doesn't care which one is used. +An example can be e.g. \tts{libreadline.so.4}, which needs some terminal +handling functions, which are provided be either \tts{libtermcap.so.2}, +or \tts{libncurses.so.5}. Another exception is with plugins or other +shared libraries which expect some symbols to be resolved to symbols +defined in the executable. +\item A library overriding functionality of some other library. One example +is e.g. C library and POSIX thread library. Older versions of the GNU C library +did not provide cancelable entry points required by the standard. This is +not needed for non-threaded applications. So only the \tts{libpthread.so.0} shared +library which provides POSIX threading support then overrode the +cancellation entry points required by the standard by wrapper functions +which provided the required functionality. Although most recent versions +of the GNU C library handle cancellation even in entry points in \tts{libc.so.6} +(this was needed for cases when \tts{libc.so.6} comes earlier before +\tts{libpthread.so.0} in symbol search scope and used to be worked around +by non-standard handling of weak symbols in the dynamic linker), because +of symbol versioning the symbols had to stay in \tts{libpthread.so.0} +as well as in \tts{libc.so.6}. This means every program using POSIX +threads on Linux will have a couple of conflict fixups because of this. +\item Programs which need copy relocations. Although \tts{prelink} will +resolve the copy relocations at prelinking time, if any shared library +has relocations against the symbol which needed copy relocation, all such +relocations will need conflict fixups. Generally, it is better to not +export variables from shared libraries in their APIs, instead provide +accessor functions. +\item Function pointer equality requirement for functions called from +executables. When address of some global function is taken, at least +C and C++ require that this pointer is the same in the whole program. +Executables typically contain position dependent code, so when code in the +executable takes address of some function not defined in the executable itself, +that address must be link time constant. Linker accomplishes this by +creating a \tts{PLT} slot for the function unless there was one already +and resolving to the address of \tts{PLT} slot. The symbol for the function +is created with \tts{st\_value} equal to address of the \tts{PLT} slot, +but \tts{st\_shndx} set to \tts{SHN\_UNDEF}. Such symbols are treated +specially by the dynamic linker, in that \tts{PLT} relocations +resolve to first symbol in the global search scope after the executable, +while symbol lookups for all other relocation types return the +address of the symbol in the executable. Unfortunately, GNU linker doesn't +differentiate between taking address of a function in an executable (especially +one for which no dynamic relocation is possible in case it is in read-only +segment) and just calling the function, but never taking its address. +If it cleared the \tts{st\_value} field of the \tts{SHN\_UNDEF} function symbols +in case nothing in the executable takes the function's address, several \tts{prelink} +conflict could disappear (\tts{SHN\_UNDEF} symbols with \tts{st\_value} set +to 0 are treated always as real undefined symbols by the dynamic linker). +\item \tts{COMDAT} code and data in C++. C++ language has several places where +it may need to emit some code or data without a clear unique +compilation unit owning it. Examples include taking address of an +\tts{inline} function, local static variable in \tts{inline} functions, +virtual tables for some classes (this depends on \tts{\#pragma interface} +or \tts{\#pragma implementation} presence, presence of non-inline +non-pure-virtual member function in the class, etc.), {\sl RTTI} info for them. +Compilers and linkers handle these using various \tts{COMDAT} schemes, +e.g. GNU linker's \tts{.gnu.linkonce*} special sections or using +\tts{SHT\_GROUP}. Unfortunately, all these duplicate merging schemes +work only during linking of shared libraries or executables, no duplicate +removal is done across shared libraries. Shared libraries typically +have relocations against their \tts{COMDAT} code or data objects (otherwise +they wouldn't be at least in most cases emitted at all), so if there are +\tts{COMDAT} duplicates across shared libraries or the executable, they +lead to conflict fixups. The linker theoretically could try to +merge \tts{COMDAT} duplicates across shared libraries if specifically +requested by the user (if a \tts{COMDAT} symbol is already present in +one of the dependent shared libraries and is \tts{STB\_WEAK}, the linker +could skip it). Unfortunately, this only works as long as the user has +full control over the dependent shared libraries, because the \tts{COMDAT} +symbol could be exported from them just as a side effect of their +implementation (e.g. they use some class internally). When such libraries +are rebuilt even with minor changes in their implementation (unfortunately +with C++ shared libraries it is usually not very clear what part is exported +ABI and what is not), some of those \tts{COMDAT} symbols in them could go +away (e.g. because suddenly they use a different class internally and +the previously used class is not referenced anywhere). When \tts{COMDAT} +objects are not merged across shared libraries, this makes no problems, +as each library which needs the \tts{COMDAT} has its own copy. But with +\tts{COMDAT} duplicate removal between shared libraries there could suddenly +be unresolved references and the shared libraries would need to be relinked. +The only place where this could work safely is when a single package +includes several C++ shared libraries which depend on each other. They are +then shipped always together and when one changes, all others need changing +too. +\end{itemize} + +\section{Prelink optimizations to reduce number of conflict fixups} + +\tts{Prelink} can optimize out some conflict fixups if it can prove that +the changes are not observable by the application at runtime (opening its +executable and reading it doesn't count). If there is a data object in some +shared library with a symbol that is overridden by a symbol in a different +shared library earlier in global symbol lookup scope or in the executable, then +that data object is likely never referenced and it shouldn't matter what it +contains. Examine the following example: + +\noindent{{\small\begin{verbatim} +$ cat > test1.c <<EOF +int i, j, k; +struct A { int *a; int *b; int *c; } x = { &i, &j, &k }; +struct A *y = &x; +EOF +$ cat > test2.c <<EOF +int i, j, k; +struct A { int *a; int *b; int *c; } x = { &i, &j, &k }; +struct A *z = &x; +EOF +$ cat > test.c <<EOF +#include <stdio.h> +extern struct A { int *a; int *b; int *c; } *y, *z; +int main (void) +{ + printf ("%p: %p %p %p\n", y, y->a, y->b, y->c); + printf ("%p: %p %p %p\n", z, z->a, z->b, z->c); +} +EOF +$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c +$ gcc -nostdlib -shared -fpic -o test2.so test2.c ./test1.so +$ gcc -o test test.c ./test2.so ./test1.so +$ ./test +0xaf3314: 0xaf33b0 0xaf33a8 0xaf33ac +0xaf3314: 0xaf33b0 0xaf33a8 0xaf33ac +\end{verbatim}} +\prelinklistingcaption{C example where conflict fixups could be optimized out}} + +In this example there are 3 conflict fixups pointing into the 12 byte +long {\sl x} object in \tts{test1.so} shared library (among other +conflicts). And nothing in the program can poke at {\sl x} content +in \tts{test1.so}, simply because it has to look at it through +{\sl x} symbol which resolves to \tts{test2.so}. So in this +case \tts{prelink} could skip those 3 conflicts. Unfortunately +it is not that easy: + +\noindent{{\small\begin{verbatim} +$ cat > test3.c <<EOF +int i, j, k; +static struct A { int *a; int *b; int *c; } local = { &i, &j, &k }; +extern struct A x; +struct A *y = &x; +struct A *y2 = &local; +extern struct A x __attribute__((alias ("local"))); +EOF +$ cat > test4.c <<EOF +#include <stdio.h> +extern struct A { int *a; int *b; int *c; } *y, *y2, *z; +int main (void) +{ + printf ("%p: %p %p %p\n", y, y->a, y->b, y->c); + printf ("%p: %p %p %p\n", y2, y2->a, y2->b, y2->c); + printf ("%p: %p %p %p\n", z, z->a, z->b, z->c); +} +EOF +$ gcc -nostdlib -shared -fpic -s -o test3.so test3.c +$ gcc -nostdlib -shared -fpic -o test4.so test2.c ./test3.so +$ gcc -o test4 test4.c ./test4.so ./test3.so +$ ./test4 +0x65a314: 0x65a3b0 0x65a3a8 0x65a3ac +0xbd1328: 0x65a3b0 0x65a3a8 0x65a3ac +0x65a314: 0x65a3b0 0x65a3a8 0x65a3ac +\end{verbatim}} +\prelinklistingcaption{Modified C example where conflict fixups cannot be removed}} + +In this example, there are again 3 conflict fixups pointing into the +12 byte long {\sl x} object in \tts{test3.so} shared library. +The fact that variable local is located at the same 12 bytes +is totally invisible to prelink, as local is a \tts{STB\_LOCAL} +symbol which doesn't show up in \tts{.dynsym} section. But if those +3 conflict fixups are removed, then suddenly program's observable +behavior changes (the last 3 addresses on second line would be +different than those on first or third line). + +Fortunately, there are at least some objects where \tts{prelink} +can be reasonably sure they will never be referenced through some +local alias. Those are various compiler generated objects with +well defined meaning which is \tts{prelink} able to identify +in shared libraries. The most important ones are C++ virtual tables +and {\sl RTTI} data. They are emitted as COMDAT data by the compiler, +in GCC into \tts{.gnu.linkonce.d.*} sections. Data or code in these +sections can be accessed only through global symbols, otherwise linker +might create unexpected results when two or more of these sections +are merged together (all but one deleted). When \tts{prelink} is checking +for such data, it first checks whether the shared library in question +is linked against \tts{libstdc++.so}. If not, it is not a C++ library +(or incorrectly built one) and thus it makes no sense to search any further. +It looks only in \tts{.data} section, for \tts{STB\_WEAK} \tts{STT\_OBJECT} +symbols whose names start with certain prefixes +\footnote{\tts{\_\_vt\_} for GCC 2.95.x and 2.96-RH virtual tables, +\tts{\_ZTV} for GCC 3.x virtual tables and \tts{\_ZTI} for GCC 3.x {\sl RTTI} data.} +and where no other symbols (in dynamic symbol table) point into the objects. +If these objects are unused because there is a conflict on their symbol, +all conflict fixups pointing into the virtual table or {\sl RTTI} structure +can be discarded. + +Another possible optimization is again related to C++ virtual tables. +Function addresses in them are not intended for pointer comparisons. +C++ code only loads them from the virtual tables and calls through +the pointer. Pointers to member functions are handled differently. +As pointer equivalence is the only reason why all function pointers +resolve to \tts{PLT} slots in the executable even when the executable doesn't +include implementation of the function (i.e. has \tts{SHN\_UNDEF} symbol +with non-zero \tts{st\_value} pointing at the \tts{PLT} slot in the +executable), \tts{prelink} can resolve method addresses in virtual tables +to the actual method implementation. In many cases this is in the same +library as the virtual table (or in one of libraries in its natural +symbol lookup scope), so a conflict fixup is unnecessary. +This optimization speeds up programs also after control is transfered +to the application and not just the time to start up the application, +although just a few cycles per method call. + +The conflict fixup reduction is quite big on some programs. +Below is statistics for \tts{kmail} program on completely unprelinked box: + +\noindent{{\small\begin{verbatim} +$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//' +10621: total startup time in dynamic loader: 240724867 clock cycles +10621: time needed for relocation: 234049636 clock cycles (97.2%) +10621: number of relocations: 34854 +10621: number of relocations from cache: 74364 +10621: number of relative relocations: 35351 +10621: time needed to load objects: 6241678 clock cycles (2.5%) +$ ls -l /usr/bin/kmail +-rwxr-xr-x 1 root root 2149084 Oct 2 12:05 /usr/bin/kmail +$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20 +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10 +$ cat /proc/`/sbin/pidof kmail`/statm +4164 4164 3509 224 33 3907 655 +$ killall Xvfb kdeinit kmail +\end{verbatim}} +\prelinklistingcaption{Statistics for unprelinked \tts{kmail}}} + +\tts{statm} special file for a process contains its memory statistics. +The numbers in it mean in order total number of used pages (on IA-32 +Linux a page is 4KB), number of resident pages (i.e. not swapped out), +number of shared pages, number of text pages, number of library pages, +number of stack and other pages and number of dirty pages used by the +process. Distinction between text and library pages is very rough, +so those numbers aren't that much useful. Of interest are mainly +first number, third number and last number. + +Statistics for \tts{kmail} on completely prelinked box: + +\noindent{{\small\begin{verbatim} +$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//' +14864: total startup time in dynamic loader: 8409504 clock cycles +14864: time needed for relocation: 3024720 clock cycles (35.9%) +14864: number of relocations: 0 +14864: number of relocations from cache: 8961 +14864: number of relative relocations: 0 +14864: time needed to load objects: 4897336 clock cycles (58.2%) +$ ls -l /usr/bin/kmail +-rwxr-xr-x 1 root root 2269500 Oct 2 12:05 /usr/bin/kmail +$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20 +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10 +$ cat /proc/`/sbin/pidof kmail`/statm +3803 3803 3186 249 33 3521 617 +$ killall Xvfb kdeinit kmail +\end{verbatim}} +\prelinklistingcaption{Statistics for prelinked \tts{kmail}}} + +Statistics for \tts{kmail} on completely prelinked box with C++ conflict fixup +optimizations turned off: + +\noindent{{\small\begin{verbatim} +$ LD_DEBUG=statistics /usr/bin/kmail 2>&1 | sed '2,8!d;s/^ *//' +20645: total startup time in dynamic loader: 9704168 clock cycles +20645: time needed for relocation: 4734715 clock cycles (48.7%) +20645: number of relocations: 0 +20645: number of relocations from cache: 59871 +20645: number of relative relocations: 0 +20645: time needed to load objects: 4487971 clock cycles (46.2%) +ls -l /usr/bin/kmail +-rwxr-xr-x 1 root root 2877360 Oct 2 12:05 /usr/bin/kmail +$ ( Xvfb :3 & ) >/dev/null 2>&1 </dev/null; sleep 20 +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10; killall kmail +$ ( DISPLAY=:3 kmail& ) >/dev/null 2>&1 </dev/null; sleep 10 +$ cat /proc/`/sbin/pidof kmail`/statm +3957 3957 3329 398 33 3526 628 +$ killall Xvfb kdeinit kmail +\end{verbatim}} +\prelinklistingcaption{Statistics for prelinked \tts{kmail} without conflict fixup reduction}} + +On this application, C++ conflict fixup optimizations saved 50910 unneeded +conflict fixups, speeded up startup by 13.3\% and decreased number of dirty +pages by 11, which means the application needs 44KB less memory per-process. + +\section{Thread Local Storage support} + +Thread Local Storage ([12], [13], [14]) support has been recently added to +GCC, GNU binutils and GNU C Library. \tts{TLS} support is a set of new +relocations which together with dynamic linker and POSIX thread library +additions provide faster and easier to use alternative to traditional +POSIX thread local data API (\tts{pthread\_getspecific}, +\tts{pthread\_setspecific}, \tts{pthread\_key\_*}). + +\tts{TLS} necessitated several changes to \tts{prelink}. Thread Local +symbols (with type \tts{STT\_TLS}) must not be relocated, as they are +relative to the start of \tts{PT\_TLS} segment and thus not virtual +addresses. The dynamic linker had to be enhanced so that it tells +\tts{prelink} at \tts{LD\_TRACE\_PRELINKING} time what \tts{TLS} module +IDs have been assigned and what addresses relative to start of \tts{TLS} +block have been given to \tts{PT\_TLS} segment of each library or executable. +There are 3 classes of new \tts{TLS} dynamic relocations \tts{prelink} +is interested in (with different names on different architectures). + +In first class are module ID relocations, which are used for \tts{TLS} +Global Dynamic and Local Dynamic models (for Global Dynamic model +they are supposed to resolve to module ID of the executable or shared library +of particular \tts{STT\_TLS} symbol, for Local Dynamic model this +resolves to module ID of the containing shared library). These +relocations are hard to prelink in any useful way without moving +\tts{TLS} module ID assignment from the dynamic linker to \tts{prelink}. +Although \tts{prelink} can find out what shared library will contain +particular \tts{STT\_TLS} symbol unless there will be conflicts +for that symbol, it doesn't know how many shared libraries with +\tts{PT\_TLS} segment will precede it or whether executable will or +will not have \tts{PT\_TLS} segment. Until \tts{TLS} is widely +deployed by many libraries, \tts{prelink} could guess that +only \tts{libc.so} will have \tts{PT\_TLS} and store 1 (first module ID +the dynamic linker assigns), but given that \tts{libc.so} uses just +one such relocation it is not probably worth doing this when soon other +shared libraries besides \tts{libc.so} and \tts{libGL.so} start using +it heavily. Because of this \tts{prelink} doesn't do anything special +when prelinking shared libraries with these relocations and for each +relocations in this class creates one conflict fixup. + +In second class are relocations which resolve to \tts{st\_value} +of some \tts{STT\_TLS} symbol. These relocations are used in +Global Dynamic \tts{TLS} model (in Local Dynamic they are resolved +at link time already) and from \tts{prelink} point of view they are +much more similar to normal relocations than the other two classes. +When the \tts{STT\_TLS} symbol is looked up successfully in shared library's +natural search scope, \tts{prelink} just stores its \tts{st\_value} +into the relocation. The chances there will be a conflict are even +smaller than with normal symbol lookups, since overloading \tts{TLS} +symbols means wasted memory in each single thread and thus library +writers will try to avoid it if possible. + +The third class includes relocations which resolve to offsets within +program's initial \tts{TLS} block +\footnote{Negative on architectures which have +\tts{TLS} block immediately below thread pointer (e.g. IA-32, AMD64, +SPARC, S/390) and positive on architectures which have \tts{TLS} block +at thread pointer or a few bytes above it (e.g. PowerPC, Alpha, IA-64, +SuperH).} +Relocation in this class are used in Initial Exec \tts{TLS} model +(or in Local Exec model if this model is supported in shared libraries). +These offsets are even harder to predict than module IDs and unlike +module IDs it wouldn't be very helpful if they were assigned by +\tts{prelink} instead of dynamic linker (which would just read them +from some dynamic tag). That's because \tts{TLS} block needs to be +packed tightly and any assignments in \tts{prelink} couldn't take +into account other shared libraries linked into the same executable +and the executable itself. Similarly to module ID relocations, +\tts{prelink} doesn't do anything about them when prelinking shared +libraries and for each such relocation creates a conflict fixup. + +\section{Prelinking of executables and shared libraries} + +Rewriting of executables is harder than for shared libraries, both because +there are more changes necessary and because shared libraries are +relocatable and thus have dynamic relocations for all absolute addresses. + +After collecting all information from the dynamic linker and assigning +virtual address space slots to all shared libraries, prelinking of shared +libraries involves following steps: +\begin{itemize} +\item Relocation of the shared library to the assigned base address. +\item \tts{REL} to \tts{RELA} conversion if needed (the only step which +changes sizes of allocated sections in the middle). +\item On architectures which have \tts{SHT\_NOBITS} \tts{.plt} sections, +before relocations are applied the section needs to be converted to +\tts{SHT\_PROGBITS}. As the section needs to be at the end (or after it) +of file backed part of some \tts{PT\_LOAD} segment, this just means that +the file backed up part needs to be enlarged, the file filled with zeros +and all following section file offsets or program header entry file +offsets adjusted. All \tts{SHT\_NOBITS} sections in the same \tts{PT\_LOAD} +segment with virtual addresses lower than the \tts{.plt} start address +need to be converted from \tts{SHT\_NOBITS} to \tts{SHT\_PROGBITS} too. +Without making the section \tts{SHT\_PROGBITS}, \tts{prelink} cannot +apply relocations against it as such sections contain only zeros. +Architectures with \tts{SHT\_NOBITS} \tts{.plt} section supported by +\tts{prelink} are PowerPC and PowerPC64. +\item Applying relocations. For each dynamic relocation in the shared +library, address of relocation's symbol looked up in natural symbol lookup +search scope of the shared library (or 0 if the symbol is not found in +that search scope) is stored in an architecture and relocation type +dependent way to memory pointed by \tts{r\_offset} field of the relocation. +This step uses symbol lookup information provided by dynamic linker. +\item Addition or modification of \tts{DT\_CHECKSUM} and +\tts{DT\_GNU\_PRELINKED} dynamic tags. +\footnote{\tts{Prelink} is not able to grow \tts{.dynamic} section, so it +needs some spare dynamic tags (DT\_NULL) at the end of \tts{.dynamic} +section. GNU linker versions released after August 2001 leave space by +default.} The former is set to checksum of allocated sections in the +shared library, the latter to time of prelinking. +\item On architectures which don't use writable \tts{.plt}, but instead use +\tts{.got.plt} (this section is merged during linking into \tts{.got}) +section, \tts{prelink} typically stores address into the first PLT slot +in \tts{.plt} section to the reserved second word of \tts{.got} section. +On these architectures, the dynamic linker has to initialize \tts{.plt} +section if lazy binding. On non-prelinked executables or shared libraries +this typically means adding load offset to the values in \tts{.got.plt} +section, for prelinked shared libraries or executables if prelinking +information cannot be used it needs to compute the right values in +\tts{.got.plt} section without looking at this section's content +(since it contains prelinking information). The second word in \tts{.got} +section is used for this computation. +\item Addition of \tts{.gnu\_prelink\_undo} unallocated section if not +present yet. This section is used by \tts{prelink} internally during +undo operation. +\item Addition of \tts{.gnu\_liblist} and \tts{.gnu\_libstr} unallocated +sections or, if they are already present, their update including possible +growing or shrinking. These sections are used only by \tts{prelink} to +compare the dependent libraries (and their order) at the time when the +shared library was prelinked against current dependencies. If a shared +library has no dependencies (e.g. dynamic linker), these sections are not +present. +\end{itemize} + +Adding or resizing unallocated section needs just file offsets of following +unallocated sections recomputed (ensuring proper alignment), growing section +header table and \tts{.shstrtab} and adding new section names to that section. + +Prelinking of executables involves following steps: +\begin{itemize} +\item \tts{REL} to \tts{RELA} conversion if needed. +\item \tts{SHT\_NOBITS} to \tts{SHT\_PROGBITS} conversion of \tts{.plt} section +if needed. +\item Applying relocations. +\item Addition or resizing of allocated \tts{.gnu.conflict} section containing +list of conflict fixups. +\item Addition or resizing of allocated \tts{.gnu.liblist} section which is used +by the dynamic linker at runtime to see if none of the dependencies changed +or were reordered. If they were, it continues normal relocation processing, +otherwise they can be skipped and only conflict fixups applied. +\item Growing of allocated \tts{.dynstr} section, where strings referenced from +\tts{.gnu.liblist} section need to be added. +\item If there are any COPY relocations (which \tts{prelink} wants to handle +rather than deferring them as conflict fixups to runtime), they need to be applied. +\item Modifying second word in \tts{.got} section for \tts{.got.plt} using +architectures. +\item Addition or adjusting of dynamic tags which allow the dynamic linker +to find the \tts{.gnu.liblist} and \tts{.gnu.conflict} sections and their +sizes. \tts{DT\_GNU\_CONFLICT} and \tts{DT\_GNU\_CONFLICTSZ} should be present +if there are any conflict fixups. It should contain the virtual address of +the \tts{.gnu.conflict} section start resp. its size in bytes. +\tts{DT\_GNU\_LIBLIST} and \tts{DT\_GNU\_LIBLISTSZ} need to be present in +all prelinked executables and must be equal the to virtual address of +the \tts{.gnu.liblist} section and its size in bytes. +\item Addition of \tts{.gnu\_prelink\_undo} unallocated section if not present. +\end{itemize} + +Executables can have absolute relocations already applied (and without a +dynamic relocation) to virtually any allocated \tts{SHT\_PROGBITS} section +\footnote{One exception is \tts{.interp} special section. It shouldn't have +relocations applied to it, nor any other section should reference it.}, +against almost all allocated \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS} +sections. This means that when growing, adding or shrinking allocated +sections in executables, all \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS} section +must keep their original virtual addresses and sizes +\footnote{With a notable exception of splitting one section into two +covering the same virtual address range.}. \tts{Prelink} tries various +places where to put allocated sections which were added or grew: +\begin{itemize} +\item In the unlikely case if there is already some gap between +sections in read-only \tts{PT\_LOAD} segment where the section fits. +\item If the \tts{SHT\_NOBITS} sections are small enough to fit +into a page together with the preceding \tts{SHT\_PROGBITS} section and there +is still some space in the page after the \tts{SHT\_NOBITS} sections. +In this case, \tts{prelink} converts the \tts{SHT\_NOBITS} sections into +\tts{SHT\_PROGBITS} sections, fills them with zeros and adds the new section +after it. This doesn't increase number of \tts{PT\_LOAD} segments, but +unfortunately those added sections are writable. This doesn't matter +much for e.g. \tts{.gnu.conflict} section which is only used before control +is transfered to the program, but could matter for \tts{.dynstr} which is +used even during \tts{dlopen}. +\item On IA-32, executables have for historical reasons base address 0x8048000. +The reason for this was that when stack was put immediately below executables, +stack and the executable could coexist in the same second level page table. +Linux puts the stack typically at the end of virtual address space and so +keeping this exact base address is not really necessary. \tts{Prelink} can +decrease the base address and thus increase size of read-only \tts{PT\_LOAD} +segment while \tts{SHT\_PROGBITS} and \tts{SHT\_NOBITS} section can stay +at their previous addresses. Just their file offsets need to be increased. +All these segment header adjustments need to be done in multiplies of +\tts{ELF} page sizes, so even if \tts{prelink} chose to do similar things +on architectures other than IA-32 which typically start executables on some address +which is a power of 2, it would be only reasonable if \tts{ELF} page size +on that architecture (which can be much bigger than page size used by the +operating system) is very small. +\item Last possibility is to create a new \tts{PT\_LOAD} segment. +\footnote{Linux kernels before 2.4.10 loaded executables which had middle \tts{PT\_LOAD} +segment with \tts{p\_memsz} bigger than \tts{p\_filesz} incorrectly, so +\tts{prelink} should be only used on systems with 2.4.10 or later kernels.} +Section immediately above program header table (typically \tts{.interp}) +has to be moved somewhere else, but if possible close to the beginning +of the executable. The new \tts{PT\_LOAD} segment is then added after the +last \tts{PT\_LOAD} segment. The segment has to be writable even when +all the sections in it are read-only, unless it ends exactly on a page +boundary, because \tts{brk} area starts immediately after the end of last +\tts{PT\_LOAD} segment and the executable expects it to be writable. +\end{itemize} + +So that verification works properly, if there is \tts{.gnu.prelink\_undo} +section in the executable, \tts{prelink} first reshuffles the sections and +segments for the purpose of finding places for the sections to the original +sequence as recorded in the \tts{.gnu.prelink\_undo} section. +Examples of the above mentioned cases: + +\noindent{{\small\begin{verbatim} +$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d' +$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d' +$ cat > test1.c <<EOF +int main (void) { return 0; } +EOF +$ gcc -Wl,--verbose 2>&1 \ + | sed '/^===/,/^===/!d;/^===/d;s/\.rel\.dyn/. += 512; &/' > test1.lds +$ gcc -s -O2 -o test1 test1.c -Wl,-T,test1.lds +$ readelf -Sl ./test1 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4 + [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1 + [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4 + [ 8] .rel.dyn REL 0804841c 00041c 000008 08 A 4 0 4 + [ 9] .rel.plt REL 08048424 000424 000008 08 A 4 b 4 + [10] .init PROGBITS 0804842c 00042c 000017 00 AX 0 0 4 +... + [22] .bss NOBITS 080496f8 0006f8 000004 00 WA 0 0 4 + [23] .comment PROGBITS 00000000 0006f8 000132 00 0 0 1 + [24] .shstrtab STRTAB 00000000 00082a 0000be 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08048000 0x08048000 0x005fc 0x005fc R E 0x1000 + LOAD 0x0005fc 0x080495fc 0x080495fc 0x000fc 0x00100 RW 0x1000 + DYNAMIC 0x000608 0x08049608 0x08049608 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +$ prelink -N ./test1 +$ readelf -Sl ./test1 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 8 1 4 + [ 5] .gnu.liblist GNU_LIBLIST 080481ac 0001ac 000028 14 A 8 0 4 + [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 8 1 4 + [ 8] .dynstr STRTAB 0804821c 00021c 000058 00 A 0 0 1 + [ 9] .gnu.conflict RELA 08048274 000274 0000c0 0c A 4 0 4 + [10] .rel.dyn REL 0804841c 00041c 000008 08 A 4 0 4 + [11] .rel.plt REL 08048424 000424 000008 08 A 4 d 4 + [12] .init PROGBITS 0804842c 00042c 000017 00 AX 0 0 4 +... + [24] .bss NOBITS 080496f8 0006f8 000004 00 WA 0 0 4 + [25] .comment PROGBITS 00000000 0006f8 000132 00 0 0 1 + [26] .gnu.prelink_undo PROGBITS 00000000 00082c 0004d4 01 0 0 4 + [27] .shstrtab STRTAB 00000000 000d00 0000eb 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08048000 0x08048000 0x005fc 0x005fc R E 0x1000 + LOAD 0x0005fc 0x080495fc 0x080495fc 0x000fc 0x00100 RW 0x1000 + DYNAMIC 0x000608 0x08049608 0x08049608 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +\end{verbatim}} +\prelinklistingcaption{Reshuffling of an executable with a gap between sections}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=\textwidth]{gap} +\caption{Reshuffling of an executable with a gap between sections} +\end{figure} + +In the above sample, there was enough space between sections (particularly +between the end of the \tts{.gnu.version\_r} section and the start of \tts{.rel.dyn}) +that the new sections could be added there. + +\noindent{{\small\begin{verbatim} +$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d' +$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d' +$ cat > test2.c <<EOF +int main (void) { return 0; } +EOF +$ gcc -s -O2 -o test2 test2.c +$ readelf -Sl ./test2 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4 + [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1 + [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4 + [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4 + [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4 + [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4 +... + [22] .bss NOBITS 080494f8 0004f8 000004 00 WA 0 0 4 + [23] .comment PROGBITS 00000000 0004f8 000132 00 0 0 1 + [24] .shstrtab STRTAB 00000000 00062a 0000be 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000 + LOAD 0x0003fc 0x080493fc 0x080493fc 0x000fc 0x00100 RW 0x1000 + DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +$ prelink -N ./test2 +$ readelf -Sl ./test2 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 23 1 4 + [ 5] .gnu.liblist GNU_LIBLIST 080481ac 0001ac 000028 14 A 23 0 4 + [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 23 1 4 + [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4 + [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4 + [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4 +... + [22] .bss PROGBITS 080494f8 0004f8 000004 00 WA 0 0 4 + [23] .dynstr STRTAB 080494fc 0004fc 000058 00 A 0 0 1 + [24] .gnu.conflict RELA 08049554 000554 0000c0 0c A 4 0 4 + [25] .comment PROGBITS 00000000 000614 000132 00 0 0 1 + [26] .gnu.prelink_undo PROGBITS 00000000 000748 0004d4 01 0 0 4 + [27] .shstrtab STRTAB 00000000 000c1c 0000eb 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000 + LOAD 0x0003fc 0x080493fc 0x080493fc 0x00218 0x00218 RW 0x1000 + DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +\end{verbatim}} +\prelinklistingcaption{Reshuffling of an executable with small \tts{.bss}}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=\textwidth]{bss} +\caption{Reshuffling of an executable with small \tts{.bss}} +\end{figure} + +In this case \tts{.bss} section was small enough that \tts{prelink} +converted it to \tts{SHT\_PROGBITS}. + +\noindent{{\small\begin{verbatim} +$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d' +$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d' +$ cat > test3.c <<EOF +int foo [4096]; +int main (void) { return 0; } +EOF +$ gcc -s -O2 -o test3 test3.c +$ readelf -Sl ./test3 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08048114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08048128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08048148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0804816c 00016c 000040 10 A 5 1 4 + [ 5] .dynstr STRTAB 080481ac 0001ac 000045 00 A 0 0 1 + [ 6] .gnu.version VERSYM 080481f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080481fc 0001fc 000020 00 A 5 1 4 + [ 8] .rel.dyn REL 0804821c 00021c 000008 08 A 4 0 4 + [ 9] .rel.plt REL 08048224 000224 000008 08 A 4 b 4 + [10] .init PROGBITS 0804822c 00022c 000017 00 AX 0 0 4 +... + [22] .bss NOBITS 08049500 000500 004020 00 WA 0 0 32 + [23] .comment PROGBITS 00000000 000500 000132 00 0 0 1 + [24] .shstrtab STRTAB 00000000 000632 0000be 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08048034 0x08048034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08048114 0x08048114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08048000 0x08048000 0x003fc 0x003fc R E 0x1000 + LOAD 0x0003fc 0x080493fc 0x080493fc 0x000fc 0x04124 RW 0x1000 + DYNAMIC 0x000408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08048128 0x08048128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +$ prelink -N ./test3 +$ readelf -Sl ./test3 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08047114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08047128 000128 000020 00 A 0 0 4 + [ 3] .dynstr STRTAB 08047148 000148 000058 00 A 0 0 1 + [ 4] .gnu.liblist GNU_LIBLIST 080471a0 0001a0 000028 14 A 3 0 4 + [ 5] .gnu.conflict RELA 080471c8 0001c8 0000c0 0c A 7 0 4 + [ 6] .hash HASH 08048148 001148 000024 04 A 7 0 4 + [ 7] .dynsym DYNSYM 0804816c 00116c 000040 10 A 3 1 4 + [ 8] .gnu.version VERSYM 080481f2 0011f2 000008 02 A 7 0 2 + [ 9] .gnu.version_r VERNEED 080481fc 0011fc 000020 00 A 3 1 4 + [10] .rel.dyn REL 0804821c 00121c 000008 08 A 7 0 4 + [11] .rel.plt REL 08048224 001224 000008 08 A 7 d 4 + [12] .init PROGBITS 0804822c 00122c 000017 00 AX 0 0 4 +... + [24] .bss NOBITS 08049500 0014f8 004020 00 WA 0 0 32 + [25] .comment PROGBITS 00000000 0014f8 000132 00 0 0 1 + [26] .gnu.prelink_undo PROGBITS 00000000 00162c 0004d4 01 0 0 4 + [27] .shstrtab STRTAB 00000000 001b00 0000eb 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08047034 0x08047034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08047114 0x08047114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08047000 0x08047000 0x013fc 0x013fc R E 0x1000 + LOAD 0x0013fc 0x080493fc 0x080493fc 0x000fc 0x04124 RW 0x1000 + DYNAMIC 0x001408 0x08049408 0x08049408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08047128 0x08047128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +\end{verbatim}} +\prelinklistingcaption{Reshuffling of an executable with decreasing of base address}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=\textwidth]{basemove} +\caption{Reshuffling of an executable with decreasing of the base address} +\end{figure} + +In \tts{test3} the base address of the executable was decreased by one page and +the new sections added there. + +\noindent{{\small\begin{verbatim} +$ SEDCMD='s/^.* \.plt.*$/.../;/\[.*\.text/,/\[.*\.got/d' +$ SEDCMD2='/Section to Segment/,$d;/^Key to/,/^Program/d;/^[A-Z]/d;/^ *$/d' +$ cat > test4.c <<EOF +int foo [4096]; +int main (void) { return 0; } +EOF +$ gcc -Wl,--verbose 2>&1 \ + | sed '/^===/,/^===/!d;/^===/d;s/0x08048000/0x08000000/' > test4.lds +$ gcc -s -O2 -o test4 test4.c -Wl,-T,test4.lds +$ readelf -Sl ./test4 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08000114 000114 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08000128 000128 000020 00 A 0 0 4 + [ 3] .hash HASH 08000148 000148 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0800016c 00016c 000040 10 A 5 1 4 + [ 5] .dynstr STRTAB 080001ac 0001ac 000045 00 A 0 0 1 + [ 6] .gnu.version VERSYM 080001f2 0001f2 000008 02 A 4 0 2 + [ 7] .gnu.version_r VERNEED 080001fc 0001fc 000020 00 A 5 1 4 + [ 8] .rel.dyn REL 0800021c 00021c 000008 08 A 4 0 4 + [ 9] .rel.plt REL 08000224 000224 000008 08 A 4 b 4 + [10] .init PROGBITS 0800022c 00022c 000017 00 AX 0 0 4 +... + [22] .bss NOBITS 08001500 000500 004020 00 WA 0 0 32 + [23] .comment PROGBITS 00000000 000500 000132 00 0 0 1 + [24] .shstrtab STRTAB 00000000 000632 0000be 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08000034 0x08000034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000114 0x08000114 0x08000114 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08000000 0x08000000 0x003fc 0x003fc R E 0x1000 + LOAD 0x0003fc 0x080013fc 0x080013fc 0x000fc 0x04124 RW 0x1000 + DYNAMIC 0x000408 0x08001408 0x08001408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000128 0x08000128 0x08000128 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +$ prelink -N ./test4 +$ readelf -Sl ./test4 | sed -e "$SEDCMD" -e "$SEDCMD2" + [Nr] Name Type Addr Off Size ES Flg Lk Inf Al + [ 0] NULL 00000000 000000 000000 00 0 0 0 + [ 1] .interp PROGBITS 08000134 000134 000013 00 A 0 0 1 + [ 2] .note.ABI-tag NOTE 08000148 000148 000020 00 A 0 0 4 + [ 3] .hash HASH 08000168 000168 000024 04 A 4 0 4 + [ 4] .dynsym DYNSYM 0800018c 00018c 000040 10 A 22 1 4 + [ 5] .gnu.version VERSYM 080001f2 0001f2 000008 02 A 4 0 2 + [ 6] .gnu.version_r VERNEED 080001fc 0001fc 000020 00 A 22 1 4 + [ 7] .rel.dyn REL 0800021c 00021c 000008 08 A 4 0 4 + [ 8] .rel.plt REL 08000224 000224 000008 08 A 4 a 4 + [ 9] .init PROGBITS 0800022c 00022c 000017 00 AX 0 0 4 +... + [21] .bss NOBITS 08001500 0004f8 004020 00 WA 0 0 32 + [22] .dynstr STRTAB 080064f8 0004f8 000058 00 A 0 0 1 + [23] .gnu.liblist GNU_LIBLIST 08006550 000550 000028 14 A 22 0 4 + [24] .gnu.conflict RELA 08006578 000578 0000c0 0c A 4 0 4 + [25] .comment PROGBITS 00000000 000638 000132 00 0 0 1 + [26] .gnu.prelink_undo PROGBITS 00000000 00076c 0004d4 01 0 0 4 + [27] .shstrtab STRTAB 00000000 000c40 0000eb 00 0 0 1 + Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align + PHDR 0x000034 0x08000034 0x08000034 0x000e0 0x000e0 R E 0x4 + INTERP 0x000134 0x08000134 0x08000134 0x00013 0x00013 R 0x1 + [Requesting program interpreter: /lib/ld-linux.so.2] + LOAD 0x000000 0x08000000 0x08000000 0x003fc 0x003fc R E 0x1000 + LOAD 0x0003fc 0x080013fc 0x080013fc 0x000fc 0x04124 RW 0x1000 + LOAD 0x0004f8 0x080064f8 0x080064f8 0x00140 0x00140 RW 0x1000 + DYNAMIC 0x000408 0x08001408 0x08001408 0x000c8 0x000c8 RW 0x4 + NOTE 0x000148 0x08000148 0x08000148 0x00020 0x00020 R 0x4 + STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x4 +\end{verbatim}} +\prelinklistingcaption{Reshuffling of an executable with addition of a new segment}} + +\begin{figure}[!ht] +\centering +\includegraphics[width=\textwidth]{newseg} +\caption{Reshuffling of an executable with addition of a new segment} +\end{figure} + +In the last example, base address was not decreased but instead a new +\tts{PT\_LOAD} segment has been added. + +\tts{R\_<arch>\_COPY} relocations are typically against first part of the +\tts{SHT\_NOBITS} \tts{.bss} section. So that \tts{prelink} can apply them, +it needs to first change their section to \tts{SHT\_PROGBITS}, but as \tts{.bss} +section typically occupies much larger part of memory, it is not desirable +to convert \tts{.bss} section into \tts{SHT\_PROGBITS} as whole. A section +cannot be partly \tts{SHT\_PROGBITS} and partly \tts{SHT\_NOBITS}, so \tts{prelink} +first splits the section into two parts, first \tts{.dynbss} which covers area +from the start of \tts{.bss} section up to highest byte to which some COPY +relocation is applied and then the old \tts{.bss}. The first is converted +to \tts{SHT\_PROGBITS} and its size is decreased, the latter stays \tts{SHT\_NOBITS} +and its start address and file offset are adjusted as well as its size decreased. +The dynamic linker handles relocations in the executable last, so \tts{prelink} +cannot just copy memory from the shared library where the symbol of the COPY +relocation has been looked up in. There might be relocations applied by the +dynamic linker in normal relocation processing to the objects, so \tts{prelink} +has to first process the relocations against that memory area. Relocations +which don't need conflict fixups are already applied, so \tts{prelink} just +needs to apply conflict fixups against the memory area, then copy it +to the newly created \tts{.dynbss} section. + +Here is an example which shows various things which COPY relocation handling +in \tts{prelink} needs to deal with: + +\noindent{{\small\begin{verbatim} +$ cat > test1.c <<EOF +struct A { char a; struct A *b; int *c; int *d; }; +int bar, baz; +struct A foo = { 1, &foo, &bar, &baz }; +int *addr (void) { return &baz; } +EOF +$ cat > test.c <<EOF +#include <stdio.h> +struct A { char a; struct A *b; int *c; int *d; }; +int bar, *addr (void), big[8192]; +extern struct A foo; +int main (void) +{ + printf ("%p: %d %p %p %p %p %p\n", &foo, foo.a, foo.b, foo.c, foo.d, + &bar, addr ()); +} +EOF +$ gcc -nostdlib -shared -fpic -s -o test1.so test1.c +$ gcc -s -o test test.c ./test1.so +$ ./test +0x80496c0: 1 0x80496c0 0x80516e0 0x4833a4 0x80516e0 0x4833a4 +$ readelf -r test | sed '/\.rel\.dyn/,/\.rel\.plt/!d;/^0/!d' +080496ac 00000c06 R_386_GLOB_DAT 00000000 __gmon_start__ +080496c0 00000605 R_386_COPY 080496c0 foo +$ readelf -S test | grep bss + [22] .bss NOBITS 080496c0 0006c0 008024 00 WA 0 0 32 +$ prelink -N ./test ./test1.so +$ readelf -s test | grep foo + 6: 080496c0 16 OBJECT GLOBAL DEFAULT 25 foo +$ readelf -s test1.so | grep foo + 15: 004a9314 16 OBJECT GLOBAL DEFAULT 6 foo +$ readelf -r test | sed '/.gnu.conflict/,/\.rel\.dyn/!d;/^0/!d' +004a9318 00000001 R_386_32 080496c0 +004a931c 00000001 R_386_32 080516e0 +005f9874 00000001 R_386_32 fffffff0 +005f9878 00000001 R_386_32 00000001 +005f98bc 00000001 R_386_32 fffffff4 +005f9900 00000001 R_386_32 ffffffec +005f9948 00000001 R_386_32 ffffffdc +005f995c 00000001 R_386_32 ffffffe0 +005f9980 00000001 R_386_32 fffffff8 +005f9988 00000001 R_386_32 ffffffe4 +005f99a4 00000001 R_386_32 ffffffd8 +005f99c4 00000001 R_386_32 ffffffe8 +005f99d8 00000001 R_386_32 08048584 +004c2510 00000007 R_386_JUMP_SLOT 00534460 +004c2514 00000007 R_386_JUMP_SLOT 00534080 +004c2518 00000007 R_386_JUMP_SLOT 00534750 +004c251c 00000007 R_386_JUMP_SLOT 005342c0 +004c2520 00000007 R_386_JUMP_SLOT 00534200 +$ objdump -s -j .dynbss test + +test: file format elf32-i386 + +Contents of section .dynbss: + 80496c0 01000000 c0960408 e0160508 a4934a00 ..............J. +$ objdump -s -j .data test1.so + +test1.so: file format elf32-i386 + +Contents of section .data: + 4a9314 01000000 14934a00 a8934a00 a4934a00 ......J...J...J. +$ readelf -S test | grep bss + [24] .dynbss PROGBITS 080496c0 0016c0 000010 00 WA 0 0 32 + [25] .bss NOBITS 080496d0 0016d0 008014 00 WA 0 0 32 +$ sed 's/8192/1/' test.c > test2.c +$ gcc -s -o test2 test2.c ./test1.so +$ readelf -S test2 | grep bss + [22] .bss NOBITS 080496b0 0006b0 00001c 00 WA 0 0 8 +$ prelink -N ./test2 ./test1.so +$ readelf -S test2 | grep bss + [22] .dynbss PROGBITS 080496b0 0006b0 000010 00 WA 0 0 8 + [23] .bss PROGBITS 080496c0 0006c0 00000c 00 WA 0 0 8 +\end{verbatim}} +\prelinklistingcaption{Relocation handling of \tts{.dynbss} objects}} + +Because \tts{test.c} executable is not compiled as position independent code and +takes address of {\sl foo} variable, a COPY relocation is needed to avoid +dynamic relocation against executable's read-only \tts{PT\_LOAD} segment. +The {\sl foo} object in \tts{test1.so} has one field with no relocations +applied at all, one relocation against the variable itself, one relocation +which needs a conflict fixup (as it is overridden by the variable in the +executable) and one with relocation which doesn't need any fixups. +The first and last field contain already the right values in prelinked +\tts{test1.so}, while second and third one need to be changed for symbol +addresses in the executable (as shown in the \tts{objdump} output). +The conflict fixups against {\sl foo} in \tts{test1.so} need to stay +(unless it is a C++ virtual table or {\sl RTTI} data, i.e. not in this testcase). +In \tts{test}, \tts{prelink} changed \tts{.dynbss} to \tts{SHT\_PROGBITS} +and kept \tts{SHT\_NOBITS} \tts{.bss}, while in slightly modified testcase +(\tts{test2}) the size of \tts{.bss} was small enough that \tts{prelink} +chose to make it \tts{SHT\_PROGBITS} too and grow the read-write +\tts{PT\_LOAD} segment and put \tts{.dynstr} and \tts{.gnu.conflict} +sections after it. + +\section{Prelink undo operation} + +Prelinking of shared libraries and executables is designed to be reversible, +so that prelink operation followed by undo operation generates bitwise +identical file to the original before prelinking. For this operation +\tts{prelink} stores the original \tts{ELF} header, all the program and +all section headers into a \tts{.gnu.prelink\_undo} section before it starts prelinking +an unprelinked executable or shared library. When undoing the modifications, +\tts{prelink} has to convert \tts{RELA} back to \tts{REL} first if \tts{REL} +to \tts{RELA} conversion was done during prelinking and all allocated +sections above it relocated down to adjust for the section shrink. +Relocation types which were changed when trying to avoid \tts{REL} to +\tts{RELA} conversion need to be changed back (e.g. on IA-32, it is +assumed \tts{R\_386\_GLOB\_DAT} relocations should be only those +against \tts{.got} section and \tts{R\_386\_32} relocations in the +remaining places). On \tts{RELA} architectures, the memory pointed +by \tts{r\_offset} field of the relocations needs to be reinitialized +to the values stored there by the linker originally. +For \tts{prelink} it doesn't matter much what this value is (e.g. +always 0, copy of \tts{r\_addend}, etc.), as long as it is computable +from the information \tts{prelink} has during undo operation +\footnote{Such as relocation type, \tts{r\_addend} value, +type, binding, flags or other attributes of relocation's symbol, +what section the relocation points into or the offset within +section it points to.}. The GNU linker had to be changed on several +architectures, so that it stores there such a value, as in several places +the value e.g. depended on original addend before final link (which is +not available anywhere after final link time, since \tts{r\_addend} +field could be adjusted during the final link). +If second word of \tts{.got} section has been modified, it needs +to be reverted back to the original value (on most architectures zero). +In executables, sections which were moved during prelinking need to be +put back and segments added while prelinking must be removed. + +There are 3 different ways how an undo operation can be performed: +\begin{itemize} +\item Undoing individual executables or shared libraries specified on the +command line in place (i.e. when the undo operation is successful, +the prelinked executable or library is atomically replaced with the +undone object). +\item With \tts{-o} option, only a single executable or shared library +given on the command line is undone and stored to the file specified +as \tts{-o} option's argument. +\item With \tts{-ua} options, \tts{prelink} builds a list of executables +in paths written in its config file (plus directories and executables +or libraries from command line) and all shared libraries these executables +depend on. All executables and libraries in the list are then unprelinked. +This option is used to unprelink the whole system. It is not perfect +and needs to be worked on, since e.g. if some executable uses some shared +library which no other executable links against, this executable (and shared +library) is prelinked, then the executable is removed (e.g. uninstalled) +but the shared library is kept, then the shared library is not +unprelinked unless specifically mentioned on the command line. +\end{itemize} + +\section{Verification of prelinked files} + +As \tts{prelink} needs to modify executables and shared libraries installed +on a system, it complicates system integrity verification (e.g. \tts{rpm -V}, +TripWire). These systems store checksums of installed files into some +database and during verification compute them again and compare to the +values stored in the database. On a prelinked system most of the executables +and shared libraries would be reported as modified. \tts{Prelink} offers +a special mode for these systems, in which it verifies that unprelinking +the executable or shared library followed by immediate prelinking (with the +same base address) creates bitwise identical output with the executable +or shared library that's being verified. Furthermore, depending on +other \tts{prelink} options, it either writes the unprelinked image +to its standard output or computes MD5 or SHA1 digest from this unprelinked +image. Mere undo operation to a file and checksumming it is not good +enough, since an intruder could have modified e.g. conflict fixups or +memory which relocations point at, changing a behavior of the program +while file after unprelinking would be unmodified. + +During verification, both \tts{prelink} executable and the dynamic linker +are used, so a proper system integrity verification first checks whether +\tts{prelink} executable (which is statically linked for this reason) hasn't +been modified, then uses \tts{prelink --verify} to verify the dynamic linker +(when verificating \tts{ld.so} the dynamic linker is not executed) +followed by verification of other executables and libraries. + +Verification requires all dependencies of checked object to be unmodified +since last prelinking. If some dependency has been changed or is missing, +\tts{prelink} will report it and return with non-zero exit status. +This is because prelinking depends on their content and so if they are +modified, the executable or shared library might be different to one after +unprelinking followed by prelinking again. In the future, perhaps it +would be possible to even verify executables or shared libraries without +unmodified dependencies, under the assumption that in such case the prelink +information will not be used. It would just need to verify that nothing +else but the information only used when dependencies are up to date +has changed between the executable or library on the filesystem and file +after unprelink followed by prelink cycle. The prelink operation +would need to be modified in this case, so that no information is +collected from the dynamic linker, the list of dependencies is assumed +to be the one stored in the executable and expect it to have identical +number of conflict fixups. + +\section{Measurements} + +There are two areas where \tts{prelink} can speed things up noticeably. +The primary is certainly startup time of big GUI applications where the +dynamic linker spends from 100ms up to a few seconds before giving control +to the application. Another area is when lots of small programs are started +up, but their execution time is rather short, so the startup time which +\tts{prelink} optimizes is a noticeable fraction of the total time. +This is typical for shell scripting. + +First numbers are from \tts{lmbench} benchmark, version 3.0-a3. +Most of the benchmarks in \tts{lmbench} suite measure kernel speed, +so it doesn't matter much whether \tts{prelink} is used or not. +Only in \tts{lat\_proc} benchmark \tts{prelink} shows up visibly. +This benchmark measures 3 different things: +\begin{itemize} +\item {\sl fork proc}, which is \tts{fork()} followed by immediate +\tts{exit(1)} in the child and \tts{wait(0)} in the parent. The results +are (as expected) about the same between unprelinked and prelinked systems. +\item {\sl exec proc}, i.e. \tts{fork()} followed by immediate +\tts{close(1)} and \tts{execve()} of a simple hello world program (this +program is compiled and linked during the benchmark into a temporary +directory and is never prelinked). The numbers are 160$\mu$s to 200$\mu$s +better on prelinked systems, because there is no relocation processing needed +initially in the dynamic linker and because all relative relocations +in \tts{libc.so.6} can be skipped. +\item {\sl sh proc}, i.e. \tts{fork()} followed by immediate \tts{close(1)} +and \tts{execlp("/bin/sh", "sh", "-c", "/tmp/hello", 0)}. Although +the hello world program is not prelinked in this case either, the shell is, +so out of the 900$\mu$s to 1000$\mu$s speedup less than 200$\mu$s can be +accounted on the speed up of the hello world program as in {\sl exec proc} +benchmark and the rest to the speedup of shell startup. +\end{itemize} + +First 4 rows are from running the benchmark on a fully unprelinked system, +the last 4 rows on the same system, but fully prelinked. + +\noindent{{\small\begin{verbatim} + L M B E N C H 3 . 0 S U M M A R Y + ------------------------------------ + (Alpha software, do not distribute) + +Processor, Processes - times in microseconds - smaller is better +------------------------------------------------------------------------- +Host OS Mhz null null open slct sig sig fork exec sh + call I/O stat clos TCP inst hndl proc proc proc +---- ------------ ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- +pork Linux 2.4.22 651 0.53 0.97 6.20 8.10 41.2 1.44 4.30 276. 1497 5403 +pork Linux 2.4.22 651 0.53 0.95 6.14 7.91 37.8 1.43 4.34 274. 1486 5391 +pork Linux 2.4.22 651 0.56 0.94 6.18 8.09 43.4 1.41 4.30 251. 1507 5423 +pork Linux 2.4.22 651 0.53 0.94 6.12 8.09 41.0 1.43 4.40 256. 1497 5385 +pork Linux 2.4.22 651 0.56 0.94 5.79 7.58 39.1 1.41 4.30 271. 1319 4460 +pork Linux 2.4.22 651 0.56 0.92 5.76 7.40 38.9 1.41 4.30 253. 1304 4417 +pork Linux 2.4.22 651 0.56 0.95 6.20 7.83 37.7 1.41 4.37 248. 1323 4481 +pork Linux 2.4.22 651 0.56 1.01 6.04 7.77 37.9 1.43 4.32 256. 1324 4457 +\end{verbatim}} +\prelinklistingcaption{\tts{lmbench} results without and with prelinking}} + +Below is a sample timing of a 239K long configure shell script from GCC +on both unprelinked and prelinked system. Preparation step was following: + +\noindent{{\small\begin{verbatim} +cd; cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/gcc login +# Empty password +cvs -d :pserver:anoncvs@subversions.gnu.org:/cvsroot/gcc -z3 co -D20031103 gcc +mkdir ~/gcc/obj +cd ~/gcc/obj; ../configure i386-redhat-linux; make configure-gcc +\end{verbatim}} +\prelinklistingcaption{Preparation script for shell script tests}} + +On an unprelinked system, the results were: + +\noindent{{\small\begin{verbatim} +cd ~/gcc/obj/gcc +for i in 1 2; do ./config.status --recheck > /dev/null 2>&1; done +for i in 1 2 3 4; do time ./config.status --recheck > /dev/null 2>&1; done + +real 0m4.436s +user 0m1.730s +sys 0m1.260s + +real 0m4.409s +user 0m1.660s +sys 0m1.340s + +real 0m4.431s +user 0m1.810s +sys 0m1.300s + +real 0m4.432s +user 0m1.670s +sys 0m1.210s +\end{verbatim}} +\prelinklistingcaption{Shell script test results on unprelinked system}} + +and on a fully prelinked system: + +\noindent{{\small\begin{verbatim} +cd ~/gcc/obj/gcc +for i in 1 2; do ./config.status --recheck > /dev/null 2>&1; done +for i in 1 2 3 4; do time ./config.status --recheck > /dev/null 2>&1; done + +real 0m4.126s +user 0m1.590s +sys 0m1.240s + +real 0m4.151s +user 0m1.620s +sys 0m1.230s + +real 0m4.161s +user 0m1.600s +sys 0m1.190s + +real 0m4.122s +user 0m1.570s +sys 0m1.230s +\end{verbatim}} +\prelinklistingcaption{Shell script test results on prelinked system}} + +Now timing of a few big GUI programs. All timings were done without X +server running and with \tts{DISPLAY} environment variable not set +(so that when control is transfered to the application, it very soon +finds out there is no X server it can talk to and bail out). The +measurements are done by the dynamic linker in ticks on a 651MHz +dual Pentium III machine, i.e. ticks have to be divided by 651000000 +to get times in seconds. Each application has been run 4 times +and the results with smallest total time spent in the dynamic +linker was chosen. Epiphany WWW browser and Evolution mail client +were chosen as examples of \tts{Gtk+} applications (typically they use +really many shared libraries, but many of them are quite small, +there aren't really many relocations nor conflict fixups and most +of the libraries are written in C) and Konqueror WWW browser and +KWord word processor were chosen as examples of \tts{KDE} applications +(typically they use slightly fewer shared libraries, though +still a lot, most of the shared libraries are written in C++, +have many relocations and cause many conflict fixups, especially +without C++ conflict fixup optimizations in \tts{prelink}). +On non-prelinked system, the timings are done with lazy binding, +i.e. without \tts{LD\_BIND\_NOW=1} set in the environment. +This is because that's how people generally run programs, on the other +side it is not exact apples to apples comparison, since on prelinked +system there is no lazy binding with the exception of shared libraries +loaded through \tts{dlopen}. So when control is passed to the application, +prelinked programs should be slightly faster for a while since non-prelinked +programs will have to do symbol lookups and processing relocations +(and on various architectures flushing instruction caches) whenever +they call some function they haven't called before in particular shared +library or in the executable. + +\noindent{{\small\begin{verbatim} +$ ldd `which epiphany-bin` | wc -l + 64 +$ # Unprelinked system +$ LD_DEBUG=statistics epiphany-bin 2>&1 | sed 's/^ *//' +18960: +18960: runtime linker statistics: +18960: total startup time in dynamic loader: 67336593 clock cycles +18960: time needed for relocation: 58119983 clock cycles (86.3%) +18960: number of relocations: 6999 +18960: number of relocations from cache: 4770 +18960: number of relative relocations: 31494 +18960: time needed to load objects: 8696104 clock cycles (12.9%) + +(epiphany-bin:18960): Gtk-WARNING **: cannot open display: +18960: +18960: runtime linker statistics: +18960: final number of relocations: 7692 +18960: final number of relocations from cache: 4770 +$ # Prelinked system +$ LD_DEBUG=statistics epiphany-bin 2>&1 | sed 's/^ *//' +25697: +25697: runtime linker statistics: +25697: total startup time in dynamic loader: 7313721 clock cycles +25697: time needed for relocation: 565680 clock cycles (7.7%) +25697: number of relocations: 0 +25697: number of relocations from cache: 1205 +25697: number of relative relocations: 0 +25697: time needed to load objects: 6179467 clock cycles (84.4%) + +(epiphany-bin:25697): Gtk-WARNING **: cannot open display: +25697: +25697: runtime linker statistics: +25697: final number of relocations: 31 +25697: final number of relocations from cache: 1205 + +$ ldd `which evolution` | wc -l + 68 +$ # Unprelinked system +$ LD_DEBUG=statistics evolution 2>&1 | sed 's/^ *//' +19042: +19042: runtime linker statistics: +19042: total startup time in dynamic loader: 54382122 clock cycles +19042: time needed for relocation: 43403190 clock cycles (79.8%) +19042: number of relocations: 3452 +19042: number of relocations from cache: 2885 +19042: number of relative relocations: 34957 +19042: time needed to load objects: 10450142 clock cycles (19.2%) + +(evolution:19042): Gtk-WARNING **: cannot open display: +19042: +19042: runtime linker statistics: +19042: final number of relocations: 4075 +19042: final number of relocations from cache: 2885 +$ # Prelinked system +$ LD_DEBUG=statistics evolution 2>&1 | sed 's/^ *//' +25723: +25723: runtime linker statistics: +25723: total startup time in dynamic loader: 9176140 clock cycles +25723: time needed for relocation: 203783 clock cycles (2.2%) +25723: number of relocations: 0 +25723: number of relocations from cache: 525 +25723: number of relative relocations: 0 +25723: time needed to load objects: 8405157 clock cycles (91.5%) + +(evolution:25723): Gtk-WARNING **: cannot open display: +25723: +25723: runtime linker statistics: +25723: final number of relocations: 31 +25723: final number of relocations from cache: 525 + +$ ldd `which konqueror` | wc -l + 37 +$ # Unprelinked system +$ LD_DEBUG=statistics konqueror 2>&1 | sed 's/^ *//' +18979: +18979: runtime linker statistics: +18979: total startup time in dynamic loader: 131985703 clock cycles +18979: time needed for relocation: 127341077 clock cycles (96.4%) +18979: number of relocations: 25473 +18979: number of relocations from cache: 53594 +18979: number of relative relocations: 31171 +18979: time needed to load objects: 4318803 clock cycles (3.2%) +konqueror: cannot connect to X server +18979: +18979: runtime linker statistics: +18979: final number of relocations: 25759 +18979: final number of relocations from cache: 53594 +$ # Prelinked system +$ LD_DEBUG=statistics konqueror 2>&1 | sed 's/^ *//' +25733: +25733: runtime linker statistics: +25733: total startup time in dynamic loader: 5533696 clock cycles +25733: time needed for relocation: 1941489 clock cycles (35.0%) +25733: number of relocations: 0 +25733: number of relocations from cache: 2066 +25733: number of relative relocations: 0 +25733: time needed to load objects: 3217736 clock cycles (58.1%) +konqueror: cannot connect to X server +25733: +25733: runtime linker statistics: +25733: final number of relocations: 0 +25733: final number of relocations from cache: 2066 + +$ ldd `which kword` | wc -l + 40 +$ # Unprelinked system +$ LD_DEBUG=statistics kword 2>&1 | sed 's/^ *//' +19065: +19065: runtime linker statistics: +19065: total startup time in dynamic loader: 153684591 clock cycles +19065: time needed for relocation: 148255294 clock cycles (96.4%) +19065: number of relocations: 26231 +19065: number of relocations from cache: 55833 +19065: number of relative relocations: 30660 +19065: time needed to load objects: 5068746 clock cycles (3.2%) +kword: cannot connect to X server +19065: +19065: runtime linker statistics: +19065: final number of relocations: 26528 +19065: final number of relocations from cache: 55833 +$ # Prelinked system +$ LD_DEBUG=statistics kword 2>&1 | sed 's/^ *//' +25749: +25749: runtime linker statistics: +25749: total startup time in dynamic loader: 6516635 clock cycles +25749: time needed for relocation: 2106856 clock cycles (32.3%) +25749: number of relocations: 0 +25749: number of relocations from cache: 2130 +25749: number of relative relocations: 0 +25749: time needed to load objects: 4008585 clock cycles (61.5%) +kword: cannot connect to X server +25749: +25749: runtime linker statistics: +25749: final number of relocations: 0 +25749: final number of relocations from cache: 2130 +\end{verbatim}} +\prelinklistingcaption{Dynamic linker statistics for unprelinked and prelinked GUI programs}} + +In the case of above mentioned \tts{Gtk+} applications, the original startup +time spent in the dynamic linker decreased into 11\% to 17\% of the original +times, with \tts{KDE} applications it decreased even into around 4.2\% of original +times. + +The startup time reported by the dynamic linker is only part of the total +startup time of a GUI program. Unfortunately it cannot be measured very +accurately without patching each application separately, so that it would +print current process CPU time at the point when all windows are painted and +the process starts waiting for user input. The following table contains +values reported by \tts{time(1)} command on each of the 4 GUI programs +running under X, both on unprelinked and fully prelinked system. +As soon as each program painted its windows, it was killed by +application's quit hot key +\footnote{\tts{Ctrl+W} for Epiphany, \tts{Ctrl+Q} for Evolution and +Konqueror and \tts{Enter} in Kword's document type choice dialog.}. +Especially the \tts{real} time values depend also on the speed of +human reactions, so each measurement was repeated 10 times. All timings +were done with hot caches, after running the applications two times +before measurement. + +\noindent{\small\begin{center} +\begin{longtable}{l|llllllllll|ll} +{\bf Type} & \multicolumn{10}{l|}{\bf Values (in seconds)} & {\bf Average} & {\bf Std.Dev.} \\ +\hline +\endhead +& \multicolumn{10}{l|}{unprelinked epiphany} && \\ +\hline +{real} & {3.053} & {2.84} & {2.996} & {2.901} & {3.019} & {2.929} & {2.883} & {2.975} & {2.922} & {3.026} & {2.954} & {0.0698} \\ +{user} & {2.33} & {2.31} & {2.28} & {2.32} & {2.44} & {2.37} & {2.29} & {2.35} & {2.34} & {2.41} & {2.344} & {0.0508} \\ +{sys} & {0.2} & {0.23} & {0.23} & {0.19} & {0.19} & {0.12} & {0.25} & {0.16} & {0.14} & {0.14} & {0.185} & {0.0440} \\ +\hline +& \multicolumn{10}{l|}{prelinked epiphany} && \\ +\hline +{real} & {2.773} & {2.743} & {2.833} & {2.753} & {2.753} & {2.644} & {2.717} & {2.897} & {2.68} & {2.761} & {2.755} & {0.0716} \\ +{user} & {2.18} & {2.17} & {2.17} & {2.12} & {2.23} & {2.26} & {2.13} & {2.17} & {2.15} & {2.15} & {2.173} & {0.0430} \\ +{sys} & {0.13} & {0.15} & {0.18} & {0.15} & {0.11} & {0.04} & {0.18} & {0.14} & {0.1} & {0.15} & {0.133} & {0.0416} \\ +\hline +& \multicolumn{10}{l|}{unprelinked evolution} && \\ +\hline +{real} & {2.106} & {1.886} & {1.828} & {2.12} & {1.867} & {1.871} & {2.242} & {1.871} & {1.862} & {2.241} & {1.989} & {0.1679} \\ +{user} & {1.12} & {1.09} & {1.15} & {1.19} & {1.17} & {1.23} & {1.15} & {1.11} & {1.17} & {1.14} & {1.152} & {0.0408} \\ +{sys} & {0.1} & {0.11} & {0.13} & {0.07} & {0.1} & {0.05} & {0.11} & {0.11} & {0.09} & {0.08} & {0.095} & {0.0232} \\ +\hline +& \multicolumn{10}{l|}{prelinked evolution} && \\ +\hline +{real} & {1.684} & {1.621} & {1.686} & {1.72} & {1.694} & {1.691} & {1.631} & {1.697} & {1.668} & {1.535} & {1.663} & {0.0541} \\ +{user} & {0.92} & {0.87} & {0.92} & {0.95} & {0.79} & {0.86} & {0.94} & {0.87} & {0.89} & {0.86} & {0.887} & {0.0476} \\ +{sys} & {0.06} & {0.1} & {0.06} & {0.05} & {0.11} & {0.08} & {0.07} & {0.1} & {0.12} & {0.07} & {0.082} & {0.0239} \\ +\hline +& \multicolumn{10}{l|}{unprelinked kword} && \\ +\hline +{real} & {2.111} & {1.414} & {1.36} & {1.356} & {1.259} & {1.383} & {1.28} & {1.321} & {1.252} & {1.407} & {1.414} & {0.2517} \\ +{user} & {1.04} & {0.9} & {0.93} & {0.88} & {0.89} & {0.89} & {0.87} & {0.89} & {0.9} & {0.8} & {0.899} & {0.0597} \\ +{sys} & {0.07} & {0.04} & {0.06} & {0.05} & {0.06} & {0.1} & {0.09} & {0.08} & {0.08} & {0.12} & {0.075} & {0.0242} \\ +\hline +& \multicolumn{10}{l|}{prelinked kword} && \\ +\hline +{real} & {1.59} & {1.052} & {0.972} & {1.064} & {1.106} & {1.087} & {1.066} & {1.087} & {1.065} & {1.005} & {1.109} & {0.1735} \\ +{user} & {0.61} & {0.53} & {0.58} & {0.6} & {0.6} & {0.58} & {0.59} & {0.61} & {0.57} & {0.6} & {0.587} & {0.0241} \\ +{sys} & {0.08} & {0.08} & {0.06} & {0.06} & {0.03} & {0.07} & {0.06} & {0.03} & {0.06} & {0.04} & {0.057} & {0.0183} \\ +\hline +& \multicolumn{10}{l|}{unprelinked konqueror} && \\ +\hline +{real} & {1.306} & {1.386} & {1.27} & {1.243} & {1.227} & {1.286} & {1.262} & {1.322} & {1.345} & {1.332} & {1.298} & {0.0495} \\ +{user} & {0.88} & {0.86} & {0.88} & {0.9} & {0.87} & {0.83} & {0.83} & {0.86} & {0.86} & {0.89} & {0.866} & {0.0232} \\ +{sys} & {0.07} & {0.11} & {0.12} & {0.1} & {0.12} & {0.08} & {0.13} & {0.12} & {0.09} & {0.08} & {0.102} & {0.0210} \\ +\hline +& \multicolumn{10}{l|}{prelinked konqueror} && \\ +\hline +{real} & {1.056} & {0.962} & {0.961} & {0.906} & {0.927} & {0.923} & {0.933} & {0.958} & {0.955} & {1.142} & {0.972} & {0.0722} \\ +{user} & {0.56} & {0.6} & {0.56} & {0.52} & {0.57} & {0.58} & {0.5} & {0.57} & {0.61} & {0.55} & {0.562} & {0.0334} \\ +{sys} & {0.1} & {0.13} & {0.08} & {0.15} & {0.07} & {0.09} & {0.09} & {0.09} & {0.1} & {0.08} & {0.098} & {0.0244} \\ +\hline +\multicolumn{13}{l}{} \\ +\caption{GUI program start up times without and with prelinking} \\ +\end{longtable} +\end{center}} + +\tts{OpenOffice.org} is probably the largest program these days in Linux, +mostly written in C++. In \tts{OpenOffice.org} 1.1, the main executable, +\tts{soffice.bin}, links directly against 34 shared libraries, but typically +during startup it loads using \tts{dlopen} many others. As has been +mentioned earlier, \tts{prelink} cannot speed up loading shared libraries +using \tts{dlopen}, since it cannot predict in which order and what +shared libraries will be loaded (and thus cannot compute conflict fixups). +The \tts{soffice.bin} is typically started through a wrapper script +and depending on what arguments are passed to it, different +\tts{OpenOffice.org} application is started. With no options, it starts +just empty window with menu from which the applications can be started, +with say \tts{private:factory/swriter} argument it starts +a word processor, with \tts{private:factory/scalc} it starts a spreadsheet +etc. When \tts{soffice.bin} is already running, if you start another +copy of it, it just instructs the already running copy to pop up a new +window and exits. + +In an experiment, \tts{soffice.bin} has been invoked 7 times against running +X server, with no arguments, \tts{private:factory/swriter}, +\tts{private:factory/scalc}, \tts{private:factory/sdraw}, +\tts{private:factory/simpress}, \tts{private:factory/smath} arguments +(in all these cases nothing was pressed at all) and last with +the \tts{private:factory/swriter} argument where the menu item \tts{New Presentation} +was selected and the word processor window closed. +In all these cases, \tts{/proc/`pidof soffice.bin`/maps} file was +captured and the application then killed. This file contains among +other things list of all shared libraries mmapped by the process at +the point where it started waiting for user input after loading up. +These lists were then summarized, to get number of the runs in +which particular shared library was loaded up out of the total 7 +runs. There were 38 shared libraries shipped as part of \tts{OpenOffice.org} +package which have been loaded in all 7 times, another 3 shared +libraries included in \tts{OpenOffice.org} (and also one shared +library shipped in another package, \tts{libdb\_cxx-4.1.so}) +which were loaded 6 times. +\footnote{In all runs but when ran without +arguments. But when the application is started without any +arguments, it cannot do any useful work, so one loads one of the +applications afterward anyway.} There was one shared library +loaded in 5 runs, but was locale specific and thus not worth +considering. Inspecting \tts{OpenOffice.org} source, these shared +libraries are never unloaded with \tts{dlclose}, so \tts{soffice.bin} +can be made much more \tts{prelink} friendly and thus save substantial +amount of startup time by linking against all those 76 shared libraries +instead of just 34 shared libraries it is linked against. +In the timings below, \tts{soffice1.bin} is the original \tts{soffice.bin} +as created by the \tts{OpenOffice.org} makefiles and \tts{soffice3.bin} is +the same executable linked dynamically against additional 42 shared libraries. +The ordering of those 42 shared libraries matters for the number of conflict +fixups, unfortunately with large C++ shared libraries there is no obvious rule +for ordering them as sometimes it is more useful when a shared library precedes +its dependency and sometimes vice versa, so a few different orderings were +tried in several steps and always the one with smallest number of conflict +fixups was chosen. Still, the number of conflict fixups is quite high +and big part of the fixups are storing addresses of \tts{PLT} slots in +the executable into various places in shared libraries +\footnote{This might get better when the linker is modified to handle +calls without ever taking address of the function in executables specially, +but only testing it will actually show it up.} +\tts{soffice2.bin} is another experiment, where the executable itself is empty +source file, all objects which were originally in \tts{soffice.bin} +executable with the exception of start files were recompiled as position independent +code and linked into a new shared library. This reduced number of conflicts +a lot and speeded up start up times against \tts{soffice3.bin} when caches +are hot. It is a little bit slower than \tts{soffice3.bin} when running +with cold caches (e.g. for the first time after bootup), as there is one +more shared library to load etc. + +In the timings below, numbers for \tts{soffice1.bin} and \tts{soffice2.bin} +resp. \tts{soffice3.bin} cannot be easily compared, as \tts{soffice1.bin} +loads less than half of the needed shared libraries which the remaining +two executables load and the time to load those shared libraries doesn't +show up there. Still, when it is prelinked it takes just slightly more +than two times longer to load \tts{soffice2.bin} than \tts{soffice1.bin} +and the times are still less than 7\% of how long it takes to load +just the initial 34 shared libraries when not prelinking. + +\noindent{{\small\begin{verbatim} +$ S='s/^ *//' +$ ldd /usr/lib/openoffice/program/soffice1.bin | wc -l + 34 +$ # Unprelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice1.bin 2>&1 | sed "$S" +19095: +19095: runtime linker statistics: +19095: total startup time in dynamic loader: 159833582 clock cycles +19095: time needed for relocation: 155464174 clock cycles (97.2%) +19095: number of relocations: 31136 +19095: number of relocations from cache: 31702 +19095: number of relative relocations: 18284 +19095: time needed to load objects: 3919645 clock cycles (2.4%) +/usr/lib/openoffice/program/soffice1.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +19095: +19095: runtime linker statistics: +19095: final number of relocations: 31715 +19095: final number of relocations from cache: 31702 +$ # Prelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice1.bin 2>&1 | sed "$S" +25759: +25759: runtime linker statistics: +25759: total startup time in dynamic loader: 4252397 clock cycles +25759: time needed for relocation: 1189840 clock cycles (27.9%) +25759: number of relocations: 0 +25759: number of relocations from cache: 2142 +25759: number of relative relocations: 0 +25759: time needed to load objects: 2604486 clock cycles (61.2%) +/usr/lib/openoffice/program/soffice1.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +25759: +25759: runtime linker statistics: +25759: final number of relocations: 24 +25759: final number of relocations from cache: 2142 +$ ldd /usr/lib/openoffice/program/soffice2.bin | wc -l + 77 +$ # Unprelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice2.bin 2>&1 | sed "$S" +19115: +19115: runtime linker statistics: +19115: total startup time in dynamic loader: 947793670 clock cycles +19115: time needed for relocation: 936895741 clock cycles (98.8%) +19115: number of relocations: 69164 +19115: number of relocations from cache: 94502 +19115: number of relative relocations: 59374 +19115: time needed to load objects: 10046486 clock cycles (1.0%) +/usr/lib/openoffice/program/soffice2.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +19115: +19115: runtime linker statistics: +19115: final number of relocations: 69966 +19115: final number of relocations from cache: 94502 +$ # Prelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice2.bin 2>&1 | sed "$S" +25777: +25777: runtime linker statistics: +25777: total startup time in dynamic loader: 10952099 clock cycles +25777: time needed for relocation: 3254518 clock cycles (29.7%) +25777: number of relocations: 0 +25777: number of relocations from cache: 5309 +25777: number of relative relocations: 0 +25777: time needed to load objects: 6805013 clock cycles (62.1%) +/usr/lib/openoffice/program/soffice2.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +25777: +25777: runtime linker statistics: +25777: final number of relocations: 24 +25777: final number of relocations from cache: 5309 +$ ldd /usr/lib/openoffice/program/soffice3.bin | wc -l + 76 +$ # Unprelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice3.bin 2>&1 | sed "$S" +19131: +19131: runtime linker statistics: +19131: total startup time in dynamic loader: 852275754 clock cycles +19131: time needed for relocation: 840996859 clock cycles (98.6%) +19131: number of relocations: 68362 +19131: number of relocations from cache: 89213 +19131: number of relative relocations: 55831 +19131: time needed to load objects: 10170207 clock cycles (1.1%) +/usr/lib/openoffice/program/soffice3.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +19131: +19131: runtime linker statistics: +19131: final number of relocations: 69177 +19131: final number of relocations from cache: 89213 +$ # Prelinked system +$ LD_DEBUG=statistics /usr/lib/openoffice/program/soffice3.bin 2>&1 | sed "$S" +25847: +25847: runtime linker statistics: +25847: total startup time in dynamic loader: 12277407 clock cycles +25847: time needed for relocation: 4232915 clock cycles (34.4%) +25847: number of relocations: 0 +25847: number of relocations from cache: 8961 +25847: number of relative relocations: 0 +25847: time needed to load objects: 6925023 clock cycles (56.4%) +/usr/lib/openoffice/program/soffice3.bin X11 error: Can't open display: +Set DISPLAY environment variable, use -display option +or check permissions of your X-Server +(See "man X" resp. "man xhost" for details) +25847: +25847: runtime linker statistics: +25847: final number of relocations: 24 +25847: final number of relocations from cache: 8961 +\end{verbatim}} +\prelinklistingcaption{Dynamic linker statistics for unprelinked and prelinked OpenOffice.org}} + +Below are measurement using \tts{time(1)} for each of the \tts{soffice.bin} +variants, prelinked and unprelinked. \tts{OpenOffice.org} was killed +immediately after painting \tts{Writer}'s window using \tts{Ctrl+Q}. + +\noindent{\small\begin{center} +\begin{longtable}{l|llllllllll|ll} +{\bf Type} & \multicolumn{10}{l|}{\bf Values (in seconds)} & {\bf Average} & {\bf Std.Dev.} \\ +\hline +\endhead +& \multicolumn{10}{l|}{unprelinked soffice1.bin private:factory/swriter} && \\ +\hline +{real} & {5.569} & {5.149} & {5.547} & {5.559} & {5.549} & {5.139} & {5.55} & {5.559} & {5.598} & {5.559} & {5.478} & {0.1765} \\ +{user} & {4.65} & {4.57} & {4.62} & {4.64} & {4.57} & {4.55} & {4.65} & {4.49} & {4.52} & {4.46} & {4.572} & {0.0680} \\ +{sys} & {0.29} & {0.24} & {0.19} & {0.21} & {0.21} & {0.21} & {0.25} & {0.25} & {0.27} & {0.26} & {0.238} & {0.0319} \\ +\hline +& \multicolumn{10}{l|}{prelinked soffice1.bin private:factory/swriter} && \\ +\hline +{real} & {4.946} & {4.899} & {5.291} & {4.879} & {4.879} & {4.898} & {5.299} & {4.901} & {4.887} & {4.901} & {4.978} & {0.1681} \\ +{user} & {4.23} & {4.27} & {4.18} & {4.24} & {4.17} & {4.22} & {4.15} & {4.25} & {4.26} & {4.31} & {4.228} & {0.0494} \\ +{sys} & {0.22} & {0.22} & {0.24} & {0.26} & {0.3} & {0.26} & {0.29} & {0.17} & {0.21} & {0.23} & {0.24} & {0.0389} \\ +\hline +& \multicolumn{10}{l|}{unprelinked soffice2.bin private:factory/swriter} && \\ +\hline +{real} & {5.575} & {5.166} & {5.592} & {5.149} & {5.571} & {5.559} & {5.159} & {5.157} & {5.569} & {5.149} & {5.365} & {0.2201} \\ +{user} & {4.59} & {4.5} & {4.57} & {4.37} & {4.47} & {4.57} & {4.56} & {4.41} & {4.63} & {4.5} & {4.517} & {0.0826} \\ +{sys} & {0.24} & {0.24} & {0.21} & {0.34} & {0.27} & {0.19} & {0.19} & {0.27} & {0.19} & {0.29} & {0.243} & {0.0501} \\ +\hline +& \multicolumn{10}{l|}{prelinked soffice2.bin private:factory/swriter} && \\ +\hline +{real} & {3.69} & {3.66} & {3.658} & {3.661} & {3.639} & {3.638} & {3.649} & {3.659} & {3.65} & {3.659} & {3.656} & {0.0146} \\ +{user} & {2.93} & {2.88} & {2.88} & {2.9} & {2.84} & {2.63} & {2.89} & {2.85} & {2.77} & {2.83} & {2.84} & {0.0860} \\ +{sys} & {0.22} & {0.18} & {0.23} & {0.2} & {0.18} & {0.29} & {0.22} & {0.23} & {0.24} & {0.22} & {0.221} & {0.0318} \\ +\hline +& \multicolumn{10}{l|}{unprelinked soffice3.bin private:factory/swriter} && \\ +\hline +{real} & {5.031} & {5.02} & {5.009} & {5.028} & {5.019} & {5.019} & {5.019} & {5.052} & {5.426} & {5.029} & {5.065} & {0.1273} \\ +{user} & {4.31} & {4.35} & {4.34} & {4.3} & {4.38} & {4.29} & {4.45} & {4.37} & {4.38} & {4.44} & {4.361} & {0.0547} \\ +{sys} & {0.27} & {0.25} & {0.26} & {0.27} & {0.27} & {0.31} & {0.18} & {0.17} & {0.16} & {0.15} & {0.229} & {0.0576} \\ +\hline +& \multicolumn{10}{l|}{prelinked soffice3.bin private:factory/swriter} && \\ +\hline +{real} & {3.705} & {3.669} & {3.659} & {3.669} & {3.66} & {3.659} & {3.659} & {3.661} & {3.668} & {3.649} & {3.666} & {0.0151} \\ +{user} & {2.86} & {2.88} & {2.85} & {2.84} & {2.83} & {2.86} & {2.84} & {2.91} & {2.86} & {2.8} & {2.853} & {0.0295} \\ +{sys} & {0.26} & {0.19} & {0.27} & {0.25} & {0.24} & {0.23} & {0.28} & {0.21} & {0.21} & {0.27} & {0.241} & {0.0303} \\ +\hline +\multicolumn{13}{l}{} \\ +\caption{OpenOffice.org start up times without and with prelinking} \\ +\end{longtable} +\end{center}} + +\section{Similar tools on other ELF using Operating Systems} + +Something similar to \tts{prelink} is available on other \tts{ELF} +platforms. On Irix there is \tts{QUICKSTART} and on Solaris \tts{crle}. + +SGI \tts{QUICKSTART} is much closer to \tts{prelink} from these two. +The \tts{rqs} program relocates libraries to (if possible) unique +virtual address space slot. The base address is either specified +on the command line with the \tts{-l} option, or \tts{rqs} uses +a \tts{so\_locations} registry with \tts{-c} or \tts{-u} options +and finds a not yet occupied slot. This is similar to how \tts{prelink} +lays out libraries without the \tts{-m} option. + +\tts{QUICKSTART} uses the same data structure for library lists +(\tts{ElfNN\_Lib}) as \tts{prelink}, but uses more fields in it +(\tts{prelink} doesn't use \tts{l\_version} and \tts{l\_flags} fields at +the moment) and uses different dynamic tags and section type for +it. Another difference is that \tts{QUICKSTART} makes all liblist +section \tts{SHF\_ALLOC}, whether in shared libraries or executables. +\tts{prelink} only needs liblist section in the executable be allocated, +liblist sections in shared libraries are not allocated and used +at \tts{prelink} time only. + +The biggest difference between \tts{QUICKSTART} and \tts{prelink} +is in how conflicts are encoded. SGI stores them in a very compact +format, as array of \tts{.dynsym} section indexes for symbols which +are conflicting. There is no information publicly available +what exactly SGI dynamic linker does when it is resolving the conflicts, +so this is just a guess. Given that the conflicts can be stored +in a shared library or executable different to the shared library with the +relocations against the conflicting symbol and different to the shared +library which the symbol was originally resolved to, there doesn't seem +to be an obvious way how to handle the conflicts very cheaply. +The dynamic linker probably collects list of all conflicting symbol +names, for each such symbol computes \tts{ELF} hash and walks hash buckets +for this hash of all shared libraries, looking for the symbol. +Every time it finds the symbol, all relocations against it need to be +redone. Unlike this, \tts{prelink} stores conflicts as an array of +\tts{ElfNN\_Rela} structures, with one entry for each shared relocation +against conflicting symbol in some shared library. This guarantees +that there are no symbol lookups during program startup (provided +that shared libraries have not been changed after prelinking), while +with \tts{QUICKSTART} will do some symbol lookups if there are any +conflicts. \tts{QUICKSTART} puts conflict sections into the executable +and every shared library where \tts{rqs} determines conflicts while +\tts{prelink} stores them in the executable only (but the array is typically +much bigger). Disk space requirements for prelinked executables are certainly +bigger than for requickstarted executables, but which one has bigger runtime +memory requirements is unclear. If prelinking can be used, all \tts{.rela*} +and \tts{.rel*} sections in the executable and all shared libraries are skipped, +so they will not need to be paged in during whole program's life (with the +exception of first and last pages in the relocation sections which can be +paged in because of other sections on the same page), but whole +\tts{.gnu.conflict} section needs to be paged in (read-only) and processed. +With \tts{QUICKSTART}, probably all (much smaller) conflict sections need +to be paged in and also likely for each conflict whole relocation sections +of each library which needs the conflict to be applied against. + +In \tts{QUICKSTART} documentation, SGI says that conflicts are very costly +and that developers should avoid them. Unfortunately, this is sometimes quite +hard, especially with C++ shared libraries. It is unclear whether \tts{rqs} +does any optimizations to trim down the number of conflicts. + +Sun took completely different approach. The dynamic linker provides a +\tts{dldump (const char *ipath, const char *opath, int flags);} function. +{\sl ipath} is supposed to be a path to an \tts{ELF} object loaded already in +the current process. This function creates a new \tts{ELF} object at +{\sl opath}, which is like the {\sl ipath} object, but relocated to the +base address which it has actually been mapped at in the current process +and with some relocations (specified in {\sl flags} bitmask) applied as +they have been resolved in the current process. Relocations, which have +been applied, are overwritten in the relocation sections with +\tts{R\_*\_NONE} relocations. The \tts{crle} executable, in addition to other +functions not related to startup times, with some specific options uses the +\tts{dldump} function to dump all shared libraries a particular executable +uses (and the executable itself) into a new directory, with selected +relocation classes being already applied. The main disadvantage of this +approach is that such alternate shared libraries are at least for +most relocation classes not shareable across different programs at all +(and for those where they could be shareable a little bit there will +be many relocations left for the dynamic linker, so the speed gains will +be small). Another disadvantage is that all relocation sections need to +be paged into the memory, just to find out that most of the relocations +are \tts{R\_*\_NONE}. + +\section{ELF extensions for prelink} + +\tts{Prelink} needs a few \tts{ELF} extensions for its data structures +in \tts{ELF} objects. For list of dependencies at the time of prelinking, +a new section type \tts{SHT\_GNU\_LIBLIST} is defined: + +\noindent{{\small\begin{verbatim} +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Unused, should be zero */ + Elf32_Word l_flags; /* Unused, should be zero */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Unused, should be zero */ + Elf64_Word l_flags; /* Unused, should be zero */ +} Elf64_Lib; +\end{verbatim}} +\prelinklistingcaption{New structures and section type constants used by \tts{prelink}}} + +Introduces a few new special sections: + +\noindent{\begin{center} +\begin{longtable}{l|lc} +{\bf Name} & {\bf Type} & {\bf Attributes} \\ +\hline +& {\sl In shared libraries} & \\ +{.gnu.liblist} & {SHT\_GNU\_LIBLIST} & {0} \\ +{.gnu.libstr} & {SHT\_STRTAB} & {0} \\ +{.gnu.prelink\_undo} & {SHT\_PROGBITS} & {0} \\ +\hline +& {\sl In executables} & \\ +{.gnu.liblist} & {SHT\_GNU\_LIBLIST} & {SHF\_ALLOC} \\ +{.gnu.conflict} & {SHT\_RELA} & {SHF\_ALLOC} \\ +{.gnu.prelink\_undo} & {SHT\_PROGBITS} & {0} \\ +\multicolumn{3}{l}{} \\ +\caption{Special sections introduced by \tts{prelink}} \\ +\end{longtable} +\end{center}} + +\begin{description} +\item[\tts{.gnu.liblist}] This section contains one \tts{ElfNN\_Lib} structure +for each shared library which the object has been prelinked against, +in the order in which they appear in symbol search scope. +Section's \tts{sh\_link} value should contain section index of \tts{.gnu.libstr} +for shared libraries and section index of \tts{.dynsym} for executables. +\tts{l\_name} field contains the dependent library's name as index +into the section pointed by\tts{sh\_link} field. \tts{l\_time\_stamp} +resp. \tts{l\_checksum} should contain copies of \tts{DT\_GNU\_PRELINKED} +resp. \tts{DT\_CHECKSUM} values of the dependent library. + +\item[\tts{.gnu.conflict}] This section contains one \tts{ElfNN\_Rela} +structure for each needed \tts{prelink} conflict fixup. \tts{r\_offset} +field contains the absolute address at which the fixup needs to be applied, +\tts{r\_addend} the value that needs to be stored at that location. +\tts{ELFNN\_R\_SYM} of \tts{r\_info} field should be zero, +\tts{ELFNN\_R\_TYPE} of \tts{r\_info} field should be architecture +specific relocation type which should be handled the same as +for \tts{.rela.*} sections on the architecture. For \tts{EM\_ALPHA} machine, +all types with \tts{R\_ALPHA\_JMP\_SLOT} in lowest 8 bits of \tts{ELF64\_R\_TYPE} +should be handled as \tts{R\_ALPHA\_JMP\_SLOT} relocation, the upper +24 bits contains index in original \tts{.rela.plt} section of the +\tts{R\_ALPHA\_JMP\_SLOT} relocation the fixup was created for. + +\item[\tts{.gnu.libstr}] This section contains strings for \tts{.gnu.liblist} +section in shared libraries where \tts{.gnu.liblist} section is not +allocated. + +\item[\tts{.gnu.prelink\_undo}] This section contains \tts{prelink} private +data used for \tts{prelink --undo} operation. This data includes the +original \tts{ElfNN\_Ehdr} of the object before prelinking and all its +original \tts{ElfNN\_Phdr} and \tts{ElfNN\_Shdr} headers. +\end{description} + +\tts{Prelink} also defines 6 new dynamic tags: + +\noindent{{\small\begin{verbatim} +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 /* Library checksum */ + +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +\end{verbatim}} +\prelinklistingcaption{\tts{Prelink} dynamic tags}} + +\tts{DT\_GNU\_PRELINKED} and \tts{DT\_CHECKSUM} dynamic tags must +be present in prelinked shared libraries. The corresponding +\tts{d\_un.d\_val} fields should contain time when the library +has been prelinked (in seconds since January, 1st, 1970, 00:00 UTC) +resp. \tts{CRC32} checksum of all sections with one of +\tts{SHF\_ALLOC}, \tts{SHF\_WRITE} or \tts{SHF\_EXECINSTR} bit set +whose type is not \tts{SHT\_NOBITS}, in the order they appear in the +shared library's section header table, with \tts{DT\_GNU\_PRELINKED} +and \tts{DT\_CHECKSUM} \tts{d\_un.v\_val} values set to 0 for +the time of checksum computation. + +The \tts{DT\_GNU\_LIBLIST} and \tts{DT\_GNU\_LIBLISTSZ} dynamic tags +must be present in all prelinked executables. The \tts{d\_un.d\_ptr} value of +the \tts{DT\_GNU\_LIBLIST} dynamic tag contains the virtual address +of the \tts{.gnu.liblist} section in the executable and \tts{d\_un.d\_val} +of \tts{DT\_GNU\_LIBLISTSZ} tag contains its size in bytes. + +\tts{DT\_GNU\_CONFLICT} and \tts{DT\_GNU\_CONFLICTSZ} dynamic tags +may be present in prelinked executables. \tts{d\_un.d\_ptr} of +\tts{DT\_GNU\_CONFLICT} dynamic tag contains the virtual address +of \tts{.gnu.conflict} section in the executable (if present) +and \tts{d\_un.d\_val} of \tts{DT\_GNU\_CONFLICTSZ} tag contains +its size in bytes. + +\begin{appendix} + +\section{Glossary} +\printglossary + +\section{References} + +\begin{description} +\item[\textrm{[1]}] +\href{http://www.caldera.com/developers/devspecs/gabi41.pdf}% +{\sl System V Application Binary Interface, Edition 4.1}. + +\item[\textrm{[2]}] +\href{http://www.caldera.com/developers/devspecs/abi386-4.pdf}% +{\sl System V Application Binary Interface, Intel 386 Architecture Processor +Supplement}. + +\item[\textrm{[3]}] +\href{http://www.x86-64.org/cgi-bin/cvsweb.cgi/x86-64-ABI/}% +{\sl System V Application Binary Interface, AMD64 Architecture Processor +Supplement}. + +\item[\textrm{[4]}] +\href{http://refspecs.freestandards.org/elf/IA64-SysV-psABI.pdf}% +{{\sl System V Application Binary Interface, Intel Itanium Architecture Processor +Supplement}, Intel Corporation, 2001}. + +\item[\textrm{[5]}] +\href{http://refspecs.freestandards.org/elf/elfspec_ppc.pdf}% +{Steve Zucker, Kari Karhi, {\sl System V Application Binary Interface, +PowerPC Architecture Processor Supplement}, SunSoft, IBM, 1995}. + +\item[\textrm{[6]}] +\href{ftp://ftp.linuxppc64.org/pub/people/amodra/PPC-elf64abi.txt.gz}% +{\sl System V Application Binary Interface, PowerPC64 Architecture Processor +Supplement}. + +\item[\textrm{[7]}] +\href{http://www.arm.com/support/566FHT/$File/ARMELF.pdf}% +{\sl System V Application Binary Interface, ARM Architecture Processor +Supplement}. + +\item[\textrm{[8]}] +\href{http://www.sparc.com/standards/SCD.2.4.1.ps.Z}% +{{\sl SPARC Compliance Definition, Version 2.4.1}, +SPARC International, Inc., 1999}. + +\item[\textrm{[9]}] +\href{http://people.redhat.com/drepper/dsohowto.pdf}% +{Ulrich Drepper, {\sl How To Write Shared Libraries}, Red Hat, Inc., 2003}. + +\item[\textrm{[10]}] +\href{http://docs.sun.com/db/doc/816-1386}% +{{\sl Linker And Library Guide}, Sun Microsystems, 2002}. + +\item[\textrm{[11]}] +\href{http://www.gzlinux.org/docs/category/dev/c/linkerandloader.pdf}% +{John R. Levine, {\sl Linkers and Loaders}, 1999}. + +\item[\textrm{[12]}] +\href{http://people.redhat.com/drepper/tls.pdf}% +{Ulrich Drepper, {\sl ELF Handling For Thread-Local Storage}, Red Hat, Inc., +2003}. + +\item[\textrm{[13]}] +\href{ftp://ftp.linuxppc64.org/pub/people/amodra/ppc32tls.txt.gz}% +{Alan Modra, {\sl PowerPC Specific Thread Local Storage ABI}, 2003}. + +\item[\textrm{[14]}] +\href{ftp://ftp.linuxppc64.org/pub/people/amodra/ppc64tls.txt.gz}% +{Alan Modra, {\sl PowerPC64 Specific Thread Local Storage ABI}, 2003}. + +\item[\textrm{[15]}] +\href{http://www.eagercon.com/dwarf/dwarf-2.0.0.pdf}% +{\sl DWARF Debugging Information Format Version 2}. + +\item[\textrm{[16]}] +\href{http://reality.sgiweb.org/davea/dwarf3-draft8-011125.pdf}% +{{\sl DWARF Debugging Information Format Version 3}, Draft, 2001}. + +\item[\textrm{[17]}] +\href{http://sources.redhat.com/cgi-bin/cvsweb.cgi/src/gdb/doc/stabs.texinfo?cvsroot=src}% +{\sl The "stabs" debugging information format}. +\end{description} + + +\section{Revision History} + +\begin{description} +\item[2003-11-03] First draft. + + +\end{description} + +\end{appendix} + +\end{document} diff --git a/trunk/doc/prelinklisting.sty b/trunk/doc/prelinklisting.sty new file mode 100644 index 0000000..f0aff06 --- /dev/null +++ b/trunk/doc/prelinklisting.sty @@ -0,0 +1,41 @@ +\NeedsTeXFormat{LaTeX2e}[2003/12/06] +\ProvidesPackage{prelinklisting}[] +\newcounter{prelinklisting} +\renewcommand\theprelinklisting{\@arabic\c@prelinklisting} +\newcommand\prelinklistingname{Listing} +\newcommand\listprelinklistingname{List of Listings} +\def\fps@prelinklisting{tbp} +\def\ftype@prelinklisting{5} +\def\ext@prelinklisting{lol} +\def\fnum@prelinklisting{\prelinklistingname~\theprelinklisting} +\newcommand\listofprelinklistings{% +\begingroup +\csname lol@parskip\endcsname +\@ifundefined{chapter}{\section}{\chapter}*{\listprelinklistingname + \@mkboth{\MakeUppercase\listprelinklistingname}% + {\MakeUppercase\listprelinklistingname}}% + \@starttoc{\ext@prelinklisting}% +\endgroup + } +\newcommand*\l@prelinklisting{\@dottedtocline{1}{1.5em}{2.3em}} +\def\JJ@caption{% + \bgroup + \@ifnextchar[{\egroup\JJ@c@ption\@firstofone}\JJ@capti@n} +\def\JJ@capti@n{% + \@ifstar + {\egroup\JJ@c@ption\@gobble[]}% + {\egroup\@xdblarg{\JJ@c@ption\@firstofone}}} +\def\JJ@c@ption#1[#2]#3{% + \JJ@makecaption#1\fnum@prelinklisting{#3}% + \def\@tempa{#2}% + \ifx\@tempa\@empty\else + {\let\\\space + \hyperdef{prelinklisting}{\theprelinklisting}{} + \let\theHprelinklisting\theprelinklisting + \hyper@makecurrent{prelinklisting} + \addcontentsline{lol}{prelinklisting}{\protect\numberline{\theprelinklisting}{#2}}% + \addtocounter{prelinklisting}{1}}% + \fi} +\def\JJ@makecaption#1#2#3{{#1{#2: }#3\endgraf\vskip\baselineskip}} +\let\prelinklistingcaption\JJ@caption +\endinput diff --git a/trunk/gelf/Makefile.am b/trunk/gelf/Makefile.am new file mode 100644 index 0000000..f6320fa --- /dev/null +++ b/trunk/gelf/Makefile.am @@ -0,0 +1,13 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall +INCLUDES = @GELFINCLUDE@ + +noinst_LTLIBRARIES = libgelf.la + +libgelf_la_SOURCES = gelf.c + +noinst_HEADERS = gelf.h diff --git a/trunk/gelf/Makefile.in b/trunk/gelf/Makefile.in new file mode 100644 index 0000000..05f9925 --- /dev/null +++ b/trunk/gelf/Makefile.in @@ -0,0 +1,345 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall +INCLUDES = @GELFINCLUDE@ + +noinst_LTLIBRARIES = libgelf.la + +libgelf_la_SOURCES = gelf.c + +noinst_HEADERS = gelf.h +subdir = gelf +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + +libgelf_la_LDFLAGS = +libgelf_la_LIBADD = +am_libgelf_la_OBJECTS = gelf.lo +libgelf_la_OBJECTS = $(am_libgelf_la_OBJECTS) +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/gelf.Plo +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CFLAGS = @CFLAGS@ +DIST_SOURCES = $(libgelf_la_SOURCES) +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +SOURCES = $(libgelf_la_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu gelf/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test -z "$dir" && dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libgelf.la: $(libgelf_la_OBJECTS) $(libgelf_la_DEPENDENCIES) + $(LINK) $(libgelf_la_LDFLAGS) $(libgelf_la_OBJECTS) $(libgelf_la_LIBADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gelf.Plo@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` + +.c.lo: +@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +CCDEPMODE = @CCDEPMODE@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(LTLIBRARIES) $(HEADERS) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-libtool clean-noinstLTLIBRARIES distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-data install-data-am \ + install-exec install-exec-am install-info install-info-am \ + install-man install-strip installcheck installcheck-am \ + installdirs maintainer-clean maintainer-clean-generic \ + mostlyclean mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool tags uninstall uninstall-am \ + uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/gelf/gelf.c b/trunk/gelf/gelf.c new file mode 100644 index 0000000..915cf5b --- /dev/null +++ b/trunk/gelf/gelf.c @@ -0,0 +1,573 @@ +/* Generic ELF wrapper for libelf which does not support gelf_ API. + Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <elf.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> +#include <sys/types.h> +#include "gelf.h" + +inline int +gelf_getclass (Elf *elf) +{ + size_t size; + char *e_ident = elf_getident (elf, &size); + + if (e_ident == NULL) + return ELFCLASSNONE; + switch (e_ident [EI_CLASS]) + { + case ELFCLASS32: + case ELFCLASS64: + return e_ident [EI_CLASS]; + default: + return ELFCLASSNONE; + } +} + +size_t +gelf_fsize (Elf *elf, Elf_Type type, size_t count, unsigned int ver) +{ + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + return elf32_fsize (type, count, ver); + case ELFCLASS64: + return elf64_fsize (type, count, ver); + default: + return 0; + } +} + +GElf_Ehdr * +gelf_getehdr (Elf *elf, GElf_Ehdr *dst) +{ + Elf32_Ehdr *ehdr32; + Elf64_Ehdr *ehdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + ehdr32 = elf32_getehdr (elf); + if (ehdr32 != NULL) + { + memcpy (dst->e_ident, ehdr32->e_ident, EI_NIDENT); + dst->e_type = ehdr32->e_type; + dst->e_machine = ehdr32->e_machine; + dst->e_version = ehdr32->e_version; + dst->e_entry = ehdr32->e_entry; + dst->e_phoff = ehdr32->e_phoff; + dst->e_shoff = ehdr32->e_shoff; + dst->e_flags = ehdr32->e_flags; + dst->e_ehsize = ehdr32->e_ehsize; + dst->e_phentsize = ehdr32->e_phentsize; + dst->e_phnum = ehdr32->e_phnum; + dst->e_shentsize = ehdr32->e_shentsize; + dst->e_shnum = ehdr32->e_shnum; + dst->e_shstrndx = ehdr32->e_shstrndx; + return dst; + } + break; + case ELFCLASS64: + ehdr64 = elf64_getehdr (elf); + if (ehdr64 != NULL) + { + memcpy (dst, ehdr64, sizeof (Elf64_Ehdr)); + return dst; + } + } + return NULL; +} + +int +gelf_update_ehdr (Elf *elf, GElf_Ehdr *src) +{ + Elf32_Ehdr *ehdr32; + Elf64_Ehdr *ehdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + ehdr32 = elf32_getehdr (elf); + if (ehdr32 == NULL) + return 0; + memcpy (ehdr32->e_ident, src->e_ident, EI_NIDENT); + ehdr32->e_type = src->e_type; + ehdr32->e_machine = src->e_machine; + ehdr32->e_version = src->e_version; + ehdr32->e_entry = src->e_entry; + ehdr32->e_phoff = src->e_phoff; + ehdr32->e_shoff = src->e_shoff; + ehdr32->e_flags = src->e_flags; + ehdr32->e_ehsize = src->e_ehsize; + ehdr32->e_phentsize = src->e_phentsize; + ehdr32->e_phnum = src->e_phnum; + ehdr32->e_shentsize = src->e_shentsize; + ehdr32->e_shnum = src->e_shnum; + ehdr32->e_shstrndx = src->e_shstrndx; + return 1; + case ELFCLASS64: + ehdr64 = elf64_getehdr (elf); + if (ehdr64 != NULL) + { + memcpy (ehdr64, src, sizeof (Elf64_Ehdr)); + return 1; + } + default: + break; + } + return 0; +} + +unsigned long +gelf_newehdr (Elf *elf, int class) +{ + switch (class) + { + case ELFCLASS32: + return (unsigned long) elf32_newehdr (elf); + case ELFCLASS64: + return (unsigned long) elf64_newehdr (elf); + default: + return 0; + } +} + +GElf_Phdr * +gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst) +{ + Elf32_Ehdr *ehdr32; + Elf64_Ehdr *ehdr64; + Elf32_Phdr *phdr32; + Elf64_Phdr *phdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + phdr32 = elf32_getphdr (elf); + if (phdr32 == NULL) + return NULL; + ehdr32 = elf32_getehdr (elf); + if (ehdr32 == NULL) + return NULL; + if (ndx >= ehdr32->e_phnum) + return NULL; + phdr32 += ndx; + dst->p_type = phdr32->p_type; + dst->p_offset = phdr32->p_offset; + dst->p_vaddr = phdr32->p_vaddr; + dst->p_paddr = phdr32->p_paddr; + dst->p_filesz = phdr32->p_filesz; + dst->p_memsz = phdr32->p_memsz; + dst->p_flags = phdr32->p_flags; + dst->p_align = phdr32->p_align; + return dst; + case ELFCLASS64: + phdr64 = elf64_getphdr (elf); + if (phdr64 == NULL) + return NULL; + ehdr64 = elf64_getehdr (elf); + if (ehdr64 == NULL) + return NULL; + if (ndx >= ehdr64->e_phnum) + return NULL; + memcpy (dst, phdr64 + ndx, sizeof (Elf64_Phdr)); + return dst; + default: + return NULL; + } +} + +int +gelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src) +{ + Elf32_Ehdr *ehdr32; + Elf64_Ehdr *ehdr64; + Elf32_Phdr *phdr32; + Elf64_Phdr *phdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + phdr32 = elf32_getphdr (elf); + if (phdr32 == NULL) + return 0; + ehdr32 = elf32_getehdr (elf); + if (ehdr32 == NULL) + return 0; + if (ndx >= ehdr32->e_phnum) + return 0; + phdr32 += ndx; + phdr32->p_type = src->p_type; + phdr32->p_offset = src->p_offset; + phdr32->p_vaddr = src->p_vaddr; + phdr32->p_paddr = src->p_paddr; + phdr32->p_filesz = src->p_filesz; + phdr32->p_memsz = src->p_memsz; + phdr32->p_flags = src->p_flags; + phdr32->p_align = src->p_align; + return 1; + case ELFCLASS64: + phdr64 = elf64_getphdr (elf); + if (phdr64 == NULL) + return 0; + ehdr64 = elf64_getehdr (elf); + if (ehdr64 == NULL) + return 0; + if (ndx >= ehdr64->e_phnum) + return 0; + memcpy (phdr64 + ndx, src, sizeof (Elf64_Phdr)); + return 1; + default: + return 0; + } +} + +unsigned long +gelf_newphdr (Elf *elf, size_t phnum) +{ + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + return (unsigned long) elf32_newphdr (elf, phnum); + case ELFCLASS64: + return (unsigned long) elf64_newphdr (elf, phnum); + default: + return 0; + } +} + +GElf_Shdr * +gelfx_getshdr (Elf *elf, Elf_Scn *scn, GElf_Shdr *dst) +{ + Elf32_Shdr *shdr32; + Elf64_Shdr *shdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + shdr32 = elf32_getshdr (scn); + if (shdr32 == NULL) + return NULL; + dst->sh_name = shdr32->sh_name; + dst->sh_type = shdr32->sh_type; + dst->sh_flags = shdr32->sh_flags; + dst->sh_addr = shdr32->sh_addr; + dst->sh_offset = shdr32->sh_offset; + dst->sh_size = shdr32->sh_size; + dst->sh_link = shdr32->sh_link; + dst->sh_info = shdr32->sh_info; + dst->sh_addralign = shdr32->sh_addralign; + dst->sh_entsize = shdr32->sh_entsize; + return dst; + case ELFCLASS64: + shdr64 = elf64_getshdr (scn); + if (shdr64 == NULL) + return NULL; + memcpy (dst, shdr64, sizeof (Elf64_Shdr)); + return dst; + default: + return NULL; + } +} + +int +gelfx_update_shdr (Elf *elf, Elf_Scn *scn, GElf_Shdr *src) +{ + Elf32_Shdr *shdr32; + Elf64_Shdr *shdr64; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + shdr32 = elf32_getshdr (scn); + if (shdr32 == NULL) + return 0; + shdr32->sh_name = src->sh_name; + shdr32->sh_type = src->sh_type; + shdr32->sh_flags = src->sh_flags; + shdr32->sh_addr = src->sh_addr; + shdr32->sh_offset = src->sh_offset; + shdr32->sh_size = src->sh_size; + shdr32->sh_link = src->sh_link; + shdr32->sh_info = src->sh_info; + shdr32->sh_addralign = src->sh_addralign; + shdr32->sh_entsize = src->sh_entsize; + return 1; + case ELFCLASS64: + shdr64 = elf64_getshdr (scn); + if (shdr64 == NULL) + return 0; + memcpy (shdr64, src, sizeof (Elf64_Shdr)); + return 1; + default: + return 0; + } +} + +Elf_Data * +gelf_xlatetom (Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode) +{ + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + return elf32_xlatetom (dst, src, encode); + case ELFCLASS64: + return elf64_xlatetom (dst, src, encode); + default: + return NULL; + } +} + +Elf_Data * +gelf_xlatetof (Elf *elf, Elf_Data *dst, const Elf_Data *src, unsigned encode) +{ + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + return elf32_xlatetof (dst, src, encode); + case ELFCLASS64: + return elf64_xlatetof (dst, src, encode); + default: + return NULL; + } +} + +GElf_Sym *gelfx_getsym (Elf *elf, Elf_Data *data, int ndx, GElf_Sym *dst) +{ + Elf32_Sym *sym32; + + if (data->d_type != ELF_T_SYM) + return NULL; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Sym) > data->d_size) + return NULL; + sym32 = &((Elf32_Sym *) data->d_buf)[ndx]; + dst->st_name = sym32->st_name; + dst->st_info = sym32->st_info; + dst->st_other = sym32->st_other; + dst->st_shndx = sym32->st_shndx; + dst->st_value = sym32->st_value; + dst->st_size = sym32->st_size; + return dst; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Sym) > data->d_size) + return NULL; + *dst = ((GElf_Sym *) data->d_buf)[ndx]; + return dst; + default: + return NULL; + } +} + +int gelfx_update_sym (Elf *elf, Elf_Data *data, int ndx, GElf_Sym *src) +{ + Elf32_Sym *sym32; + + if (data->d_type != ELF_T_SYM) + return 0; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Sym) > data->d_size) + return 0; + sym32 = &((Elf32_Sym *) data->d_buf)[ndx]; + sym32->st_name = src->st_name; + sym32->st_info = src->st_info; + sym32->st_other = src->st_other; + sym32->st_shndx = src->st_shndx; + sym32->st_value = src->st_value; + sym32->st_size = src->st_size; + return 1; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Sym) > data->d_size) + return 0; + ((GElf_Sym *) data->d_buf)[ndx] = *src; + return 1; + default: + return 0; + } +} + +GElf_Dyn *gelfx_getdyn (Elf *elf, Elf_Data *data, int ndx, GElf_Dyn *dst) +{ + Elf32_Dyn *dyn32; + + if (data->d_type != ELF_T_DYN) + return NULL; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Dyn) > data->d_size) + return NULL; + dyn32 = &((Elf32_Dyn *) data->d_buf)[ndx]; + dst->d_tag = dyn32->d_tag; + dst->d_un.d_val = dyn32->d_un.d_val; + return dst; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Dyn) > data->d_size) + return NULL; + *dst = ((GElf_Dyn *) data->d_buf)[ndx]; + return dst; + default: + return NULL; + } +} + +int gelfx_update_dyn (Elf *elf, Elf_Data *data, int ndx, GElf_Dyn *src) +{ + Elf32_Dyn *dyn32; + + if (data->d_type != ELF_T_DYN) + return 0; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Dyn) > data->d_size) + return 0; + dyn32 = &((Elf32_Dyn *) data->d_buf)[ndx]; + dyn32->d_tag = src->d_tag; + dyn32->d_un.d_val = src->d_un.d_val; + return 1; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Dyn) > data->d_size) + return 0; + ((GElf_Dyn *) data->d_buf)[ndx] = *src; + return 1; + default: + return 0; + } +} + +GElf_Rel *gelfx_getrel (Elf *elf, Elf_Data *data, int ndx, GElf_Rel *dst) +{ + Elf32_Rel *rel32; + + if (data->d_type != ELF_T_REL) + return NULL; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Rel) > data->d_size) + return NULL; + rel32 = &((Elf32_Rel *) data->d_buf)[ndx]; + dst->r_offset = rel32->r_offset; + dst->r_info = GELF_R_INFO (ELF32_R_SYM (rel32->r_info), + ELF32_R_TYPE (rel32->r_info)); + return dst; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Rel) > data->d_size) + return NULL; + *dst = ((GElf_Rel *) data->d_buf)[ndx]; + return dst; + default: + return NULL; + } +} + +int gelfx_update_rel (Elf *elf, Elf_Data *data, int ndx, GElf_Rel *src) +{ + Elf32_Rel *rel32; + + if (data->d_type != ELF_T_REL) + return 0; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Rel) > data->d_size) + return 0; + rel32 = &((Elf32_Rel *) data->d_buf)[ndx]; + rel32->r_offset = src->r_offset; + rel32->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info), + GELF_R_TYPE (src->r_info)); + return 1; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Rel) > data->d_size) + return 0; + ((GElf_Rel *) data->d_buf)[ndx] = *src; + return 1; + default: + return 0; + } +} + +GElf_Rela *gelfx_getrela (Elf *elf, Elf_Data *data, int ndx, GElf_Rela *dst) +{ + Elf32_Rela *rela32; + + if (data->d_type != ELF_T_RELA) + return NULL; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Rela) > data->d_size) + return NULL; + rela32 = &((Elf32_Rela *) data->d_buf)[ndx]; + dst->r_offset = rela32->r_offset; + dst->r_info = GELF_R_INFO (ELF32_R_SYM (rela32->r_info), + ELF32_R_TYPE (rela32->r_info)); + dst->r_addend = rela32->r_addend; + return dst; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Rela) > data->d_size) + return NULL; + *dst = ((GElf_Rela *) data->d_buf)[ndx]; + return dst; + default: + return NULL; + } +} + +int gelfx_update_rela (Elf *elf, Elf_Data *data, int ndx, GElf_Rela *src) +{ + Elf32_Rela *rela32; + + if (data->d_type != ELF_T_RELA) + return 0; + + switch (gelf_getclass (elf)) + { + case ELFCLASS32: + if ((ndx + 1) * sizeof (Elf32_Rela) > data->d_size) + return 0; + rela32 = &((Elf32_Rela *) data->d_buf)[ndx]; + rela32->r_offset = src->r_offset; + rela32->r_info = ELF32_R_INFO (GELF_R_SYM (src->r_info), + GELF_R_TYPE (src->r_info)); + rela32->r_addend = src->r_addend; + return 1; + case ELFCLASS64: + if ((ndx + 1) * sizeof (Elf64_Rela) > data->d_size) + return 0; + ((GElf_Rela *) data->d_buf)[ndx] = *src; + return 1; + default: + return 0; + } +} diff --git a/trunk/gelf/gelf.h b/trunk/gelf/gelf.h new file mode 100644 index 0000000..6b76a15 --- /dev/null +++ b/trunk/gelf/gelf.h @@ -0,0 +1,72 @@ +/* Generic ELF wrapper for libelf which does not support gelf_ API. + Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GELF_H +#define GELF_H + +typedef Elf64_Half GElf_Half; +typedef Elf64_Word GElf_Word; +typedef Elf64_Sword GElf_Sword; +typedef Elf64_Xword GElf_Xword; +typedef Elf64_Sxword GElf_Sxword; +typedef Elf64_Addr GElf_Addr; +typedef Elf64_Off GElf_Off; +typedef Elf64_Ehdr GElf_Ehdr; +typedef Elf64_Shdr GElf_Shdr; +typedef Elf64_Section GElf_Section; +typedef Elf64_Sym GElf_Sym; +typedef Elf64_Rel GElf_Rel; +typedef Elf64_Rela GElf_Rela; +typedef Elf64_Phdr GElf_Phdr; +typedef Elf64_Dyn GElf_Dyn; +#define GELF_ST_BIND ELF64_ST_BIND +#define GELF_ST_TYPE ELF64_ST_TYPE +#define GELF_ST_INFO ELF64_ST_INFO +#define GELF_ST_VISIBILITY ELF64_ST_VISIBILITY +#define GELF_R_SYM ELF64_R_SYM +#define GELF_R_TYPE ELF64_R_TYPE +#define GELF_R_INFO ELF64_R_INFO + +extern int gelf_getclass (Elf *); +extern size_t gelf_fsize (Elf *, Elf_Type, size_t, unsigned); +extern GElf_Ehdr *gelf_getehdr (Elf *, GElf_Ehdr *); +extern int gelf_update_ehdr (Elf *, GElf_Ehdr *); +extern unsigned long gelf_newehdr (Elf *, int); +extern GElf_Phdr *gelf_getphdr (Elf *, int, GElf_Phdr *); +extern int gelf_update_phdr (Elf *, int, GElf_Phdr *); +extern unsigned long gelf_newphdr (Elf *, size_t); +extern Elf_Data *gelf_xlatetom (Elf *, Elf_Data *, const Elf_Data *, unsigned); +extern Elf_Data *gelf_xlatetof (Elf *, Elf_Data *, const Elf_Data *, unsigned); +/* The gelf_ equivalents of these functions only provide Elf_Scn resp. + Elf_Data pointers, without changing the underlying libelf implementation + it is either impossible to get Elf * pointer from that or it requires + internal knowledge about the libelf implementation. */ +extern GElf_Shdr *gelfx_getshdr (Elf *, Elf_Scn *, GElf_Shdr *); +extern int gelfx_update_shdr (Elf *, Elf_Scn *, GElf_Shdr *); +extern GElf_Sym *gelfx_getsym (Elf *, Elf_Data *, int, GElf_Sym *); +extern int gelfx_update_sym (Elf *, Elf_Data *, int, GElf_Sym *); +extern GElf_Dyn *gelfx_getdyn (Elf *, Elf_Data *, int, GElf_Dyn *); +extern int gelfx_update_dyn (Elf *, Elf_Data *, int, GElf_Dyn *); +extern GElf_Rel *gelfx_getrel (Elf *, Elf_Data *, int, GElf_Rel *); +extern GElf_Rela *gelfx_getrela (Elf *, Elf_Data *, int, GElf_Rela *); +extern int gelfx_update_rel (Elf *, Elf_Data *, int, GElf_Rel *); +extern int gelfx_update_rela (Elf *, Elf_Data *, int, GElf_Rela *); + +#define HAVE_GELFX_GETSHDR 1 + +#endif /* GELF_H */ diff --git a/trunk/gelfx/Makefile.am b/trunk/gelfx/Makefile.am new file mode 100644 index 0000000..ae51b93 --- /dev/null +++ b/trunk/gelfx/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +noinst_HEADERS = gelfx.h diff --git a/trunk/gelfx/Makefile.in b/trunk/gelfx/Makefile.in new file mode 100644 index 0000000..692bbea --- /dev/null +++ b/trunk/gelfx/Makefile.in @@ -0,0 +1,268 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +noinst_HEADERS = gelfx.h +subdir = gelfx +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu gelfx/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool tags uninstall \ + uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/gelfx/gelfx.h b/trunk/gelfx/gelfx.h new file mode 100644 index 0000000..c011a57 --- /dev/null +++ b/trunk/gelfx/gelfx.h @@ -0,0 +1,40 @@ +/* Generic ELF wrapper for libelf which does not support gelf_ API. + Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GELFX_H +#define GELFX_H + +#include <libelf.h> +#include <gelf.h> + +#ifndef HAVE_GELFX_GETSHDR + +#define gelfx_getshdr(elf,scn,shdr) gelf_getshdr(scn,shdr) +#define gelfx_update_shdr(elf,scn,shdr) gelf_update_shdr(scn,shdr) +#define gelfx_getsym(elf,data,ndx,x) gelf_getsym(data,ndx,x) +#define gelfx_update_sym(elf,data,ndx,x) gelf_update_sym(data,ndx,x) +#define gelfx_getdyn(elf,data,ndx,x) gelf_getdyn(data,ndx,x) +#define gelfx_update_dyn(elf,data,ndx,x) gelf_update_dyn(data,ndx,x) +#define gelfx_getrel(elf,data,ndx,x) gelf_getrel(data,ndx,x) +#define gelfx_update_rel(elf,data,ndx,x) gelf_update_rel(data,ndx,x) +#define gelfx_getrela(elf,data,ndx,x) gelf_getrela(data,ndx,x) +#define gelfx_update_rela(elf,data,ndx,x) gelf_update_rela(data,ndx,x) + +#endif + +#endif /* GELFX_H */ diff --git a/trunk/gelfx32/Makefile.am b/trunk/gelfx32/Makefile.am new file mode 100644 index 0000000..ae51b93 --- /dev/null +++ b/trunk/gelfx32/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +noinst_HEADERS = gelfx.h diff --git a/trunk/gelfx32/Makefile.in b/trunk/gelfx32/Makefile.in new file mode 100644 index 0000000..4f6898a --- /dev/null +++ b/trunk/gelfx32/Makefile.in @@ -0,0 +1,268 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +noinst_HEADERS = gelfx.h +subdir = gelfx32 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +HEADERS = $(noinst_HEADERS) + +DIST_COMMON = $(noinst_HEADERS) Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu gelfx32/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(HEADERS) + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +.PHONY: GTAGS all all-am check check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distclean-tags distdir dvi dvi-am info info-am install \ + install-am install-data install-data-am install-exec \ + install-exec-am install-info install-info-am install-man \ + install-strip installcheck installcheck-am installdirs \ + maintainer-clean maintainer-clean-generic mostlyclean \ + mostlyclean-generic mostlyclean-libtool tags uninstall \ + uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/gelfx32/gelfx.h b/trunk/gelfx32/gelfx.h new file mode 100644 index 0000000..7668a84 --- /dev/null +++ b/trunk/gelfx32/gelfx.h @@ -0,0 +1,227 @@ +/* gelf API which supports ELFCLASS32 only. + Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GELFX_H +#define GELFX_H + +#include <error.h> +#include <libelf.h> +#include <stdlib.h> +#include <string.h> + +typedef Elf32_Half GElf_Half; +typedef Elf32_Word GElf_Word; +typedef Elf32_Sword GElf_Sword; +typedef Elf32_Xword GElf_Xword; +typedef Elf32_Sxword GElf_Sxword; +typedef Elf32_Addr GElf_Addr; +typedef Elf32_Off GElf_Off; +typedef Elf32_Ehdr GElf_Ehdr; +typedef Elf32_Shdr GElf_Shdr; +typedef Elf32_Section GElf_Section; +typedef Elf32_Sym GElf_Sym; +typedef Elf32_Rel GElf_Rel; +typedef Elf32_Rela GElf_Rela; +typedef Elf32_Phdr GElf_Phdr; +typedef Elf32_Dyn GElf_Dyn; +#define GELF_ST_BIND ELF32_ST_BIND +#define GELF_ST_TYPE ELF32_ST_TYPE +#define GELF_ST_INFO ELF32_ST_INFO +#define GELF_R_SYM ELF32_R_SYM +#define GELF_R_TYPE ELF32_R_TYPE +#define GELF_R_INFO ELF32_R_INFO + +extern inline int +gelf_getclass (Elf *elf) +{ + size_t size; + char *e_ident = elf_getident (elf, &size); + if (e_ident [EI_CLASS] == ELFCLASS64) + error (EXIT_FAILURE, 0, "64-bit ELF not supported"); + return e_ident [EI_CLASS] == ELFCLASS32 ? ELFCLASS32 : ELFCLASSNONE; +} + +#define gelf_fsize(e,t,c,v) elf32_fsize(t,c,v) + +extern inline GElf_Ehdr *gelf_getehdr (Elf *elf, GElf_Ehdr *dst) +{ + Elf32_Ehdr *ehdr = elf32_getehdr (elf); + if (ehdr == NULL) + return NULL; + return memcpy (dst, ehdr, sizeof (Elf32_Ehdr)); +} + +extern inline int +gelf_update_ehdr (Elf *elf, GElf_Ehdr *src) +{ + Elf32_Ehdr *ehdr = elf32_getehdr (elf); + if (ehdr == NULL) + return 0; + memcpy (ehdr, src, sizeof (Elf32_Ehdr)); + return 1; +} + +extern inline unsigned long +gelf_newehdr (Elf *elf, int class) +{ + if (class != ELFCLASS32) + return 0; + return (unsigned long) elf32_newehdr (elf); +} + +extern inline GElf_Phdr * +gelf_getphdr (Elf *elf, int ndx, GElf_Phdr *dst) +{ + Elf32_Ehdr *ehdr = elf32_getehdr (elf); + Elf32_Phdr *phdr = elf32_getphdr (elf); + if (ehdr == NULL || phdr == NULL || ndx >= ehdr->e_phnum) + return NULL; + return memcpy (dst, phdr + ndx, sizeof (Elf32_Phdr)); +} + +extern inline int +gelf_update_phdr (Elf *elf, int ndx, GElf_Phdr *src) +{ + Elf32_Ehdr *ehdr = elf32_getehdr (elf); + Elf32_Phdr *phdr = elf32_getphdr (elf); + if (ehdr == NULL || phdr == NULL || ndx >= ehdr->e_phnum) + return 0; + memcpy (phdr + ndx, src, sizeof (Elf32_Phdr)); + return 1; +} + +extern inline unsigned long +gelf_newphdr (Elf *elf, size_t phnum) +{ + return (unsigned long) elf32_newphdr (elf, phnum); +} + +#define gelf_xlatetom(e,d,s,n) elf32_xlatetom(e,d,s,n) +#define gelf_xlatetof(e,d,s,n) elf32_xlatetof(e,d,s,n) + +extern inline GElf_Shdr * +gelf_getshdr (Elf_Scn *scn, GElf_Shdr *dst) +{ + Elf32_Shdr *shdr = elf32_getshdr (scn); + if (shdr == NULL) + return NULL; + return memcpy (dst, shdr, sizeof (Elf32_Shdr)); +} + +extern inline int +gelf_update_shdr (Elf_Scn *scn, GElf_Shdr *src) +{ + Elf32_Shdr *shdr = elf32_getshdr (scn); + if (shdr == NULL) + return 0; + memcpy (shdr, src, sizeof (Elf32_Shdr)); + return 1; +} + +extern inline GElf_Sym * +gelf_getsym (Elf_Data *data, int ndx, GElf_Sym *dst) +{ + if (data->d_type != ELF_T_SYM + || (ndx + 1) * sizeof (Elf32_Sym) > data->d_size) + return NULL; + *dst = ((GElf_Sym *) data->d_buf)[ndx]; + return dst; +} + +extern inline int +gelf_update_sym (Elf_Data *data, int ndx, GElf_Sym *src) +{ + if (data->d_type != ELF_T_SYM + || (ndx + 1) * sizeof (Elf32_Sym) > data->d_size) + return 0; + ((GElf_Sym *) data->d_buf)[ndx] = *src; + return 1; +} + +extern inline GElf_Dyn * +gelf_getdyn (Elf_Data *data, int ndx, GElf_Dyn *dst) +{ + if (data->d_type != ELF_T_DYN + || (ndx + 1) * sizeof (Elf32_Dyn) > data->d_size) + return NULL; + *dst = ((GElf_Dyn *) data->d_buf)[ndx]; + return dst; +} + +extern inline int +gelf_update_dyn (Elf_Data *data, int ndx, GElf_Dyn *src) +{ + if (data->d_type != ELF_T_DYN + || (ndx + 1) * sizeof (Elf32_Dyn) > data->d_size) + return 0; + ((GElf_Dyn *) data->d_buf)[ndx] = *src; + return 1; +} + +extern inline GElf_Rel * +gelf_getrel (Elf_Data *data, int ndx, GElf_Rel *dst) +{ + if (data->d_type != ELF_T_REL + || (ndx + 1) * sizeof (Elf32_Rel) > data->d_size) + return NULL; + *dst = ((GElf_Rel *) data->d_buf)[ndx]; + return dst; +} + +extern inline int +gelf_update_rel (Elf_Data *data, int ndx, GElf_Rel *src) +{ + if (data->d_type != ELF_T_REL + || (ndx + 1) * sizeof (Elf32_Rel) > data->d_size) + return 0; + ((GElf_Rel *) data->d_buf)[ndx] = *src; + return 1; +} + +extern inline GElf_Rela * +gelf_getrela (Elf_Data *data, int ndx, GElf_Rela *dst) +{ + if (data->d_type != ELF_T_RELA + || (ndx + 1) * sizeof (Elf32_Rela) > data->d_size) + return NULL; + *dst = ((GElf_Rela *) data->d_buf)[ndx]; + return dst; +} + +extern inline int +gelf_update_rela (Elf_Data *data, int ndx, GElf_Rela *src) +{ + if (data->d_type != ELF_T_RELA + || (ndx + 1) * sizeof (Elf32_Rela) > data->d_size) + return 0; + ((GElf_Rela *) data->d_buf)[ndx] = *src; + return 1; +} + +#define gelfx_getshdr(elf,scn,shdr) gelf_getshdr(scn,shdr) +#define gelfx_update_shdr(elf,scn,shdr) gelf_update_shdr(scn,shdr) +#define gelfx_getsym(elf,data,ndx,x) gelf_getsym(data,ndx,x) +#define gelfx_update_sym(elf,data,ndx,x) gelf_update_sym(data,ndx,x) +#define gelfx_getdyn(elf,data,ndx,x) gelf_getdyn(data,ndx,x) +#define gelfx_update_dyn(elf,data,ndx,x) gelf_update_dyn(data,ndx,x) +#define gelfx_getrel(elf,data,ndx,x) gelf_getrel(data,ndx,x) +#define gelfx_update_rel(elf,data,ndx,x) gelf_update_rel(data,ndx,x) +#define gelfx_getrela(elf,data,ndx,x) gelf_getrela(data,ndx,x) +#define gelfx_update_rela(elf,data,ndx,x) gelf_update_rela(data,ndx,x) + +#endif /* GELFX_H */ diff --git a/trunk/install-sh b/trunk/install-sh new file mode 100755 index 0000000..398a88e --- /dev/null +++ b/trunk/install-sh @@ -0,0 +1,251 @@ +#!/bin/sh +# +# install - install a program, script, or datafile +# This comes from X11R5 (mit/util/scripts/install.sh). +# +# Copyright 1991 by the Massachusetts Institute of Technology +# +# Permission to use, copy, modify, distribute, and sell this software and its +# documentation for any purpose is hereby granted without fee, provided that +# the above copyright notice appear in all copies and that both that +# copyright notice and this permission notice appear in supporting +# documentation, and that the name of M.I.T. not be used in advertising or +# publicity pertaining to distribution of the software without specific, +# written prior permission. M.I.T. makes no representations about the +# suitability of this software for any purpose. It is provided "as is" +# without express or implied warranty. +# +# Calling this script install-sh is preferred over install.sh, to prevent +# `make' implicit rules from creating a file called install from it +# when there is no Makefile. +# +# This script is compatible with the BSD install script, but was written +# from scratch. It can only install one file at a time, a restriction +# shared with many OS's install programs. + + +# set DOITPROG to echo to test this script + +# Don't use :- since 4.3BSD and earlier shells don't like it. +doit="${DOITPROG-}" + + +# put in absolute paths if you don't have them in your path; or use env. vars. + +mvprog="${MVPROG-mv}" +cpprog="${CPPROG-cp}" +chmodprog="${CHMODPROG-chmod}" +chownprog="${CHOWNPROG-chown}" +chgrpprog="${CHGRPPROG-chgrp}" +stripprog="${STRIPPROG-strip}" +rmprog="${RMPROG-rm}" +mkdirprog="${MKDIRPROG-mkdir}" + +transformbasename="" +transform_arg="" +instcmd="$mvprog" +chmodcmd="$chmodprog 0755" +chowncmd="" +chgrpcmd="" +stripcmd="" +rmcmd="$rmprog -f" +mvcmd="$mvprog" +src="" +dst="" +dir_arg="" + +while [ x"$1" != x ]; do + case $1 in + -c) instcmd="$cpprog" + shift + continue;; + + -d) dir_arg=true + shift + continue;; + + -m) chmodcmd="$chmodprog $2" + shift + shift + continue;; + + -o) chowncmd="$chownprog $2" + shift + shift + continue;; + + -g) chgrpcmd="$chgrpprog $2" + shift + shift + continue;; + + -s) stripcmd="$stripprog" + shift + continue;; + + -t=*) transformarg=`echo $1 | sed 's/-t=//'` + shift + continue;; + + -b=*) transformbasename=`echo $1 | sed 's/-b=//'` + shift + continue;; + + *) if [ x"$src" = x ] + then + src=$1 + else + # this colon is to work around a 386BSD /bin/sh bug + : + dst=$1 + fi + shift + continue;; + esac +done + +if [ x"$src" = x ] +then + echo "install: no input file specified" + exit 1 +else + : +fi + +if [ x"$dir_arg" != x ]; then + dst=$src + src="" + + if [ -d $dst ]; then + instcmd=: + chmodcmd="" + else + instcmd=$mkdirprog + fi +else + +# Waiting for this to be detected by the "$instcmd $src $dsttmp" command +# might cause directories to be created, which would be especially bad +# if $src (and thus $dsttmp) contains '*'. + + if [ -f $src -o -d $src ] + then + : + else + echo "install: $src does not exist" + exit 1 + fi + + if [ x"$dst" = x ] + then + echo "install: no destination specified" + exit 1 + else + : + fi + +# If destination is a directory, append the input filename; if your system +# does not like double slashes in filenames, you may need to add some logic + + if [ -d $dst ] + then + dst="$dst"/`basename $src` + else + : + fi +fi + +## this sed command emulates the dirname command +dstdir=`echo $dst | sed -e 's,[^/]*$,,;s,/$,,;s,^$,.,'` + +# Make sure that the destination directory exists. +# this part is taken from Noah Friedman's mkinstalldirs script + +# Skip lots of stat calls in the usual case. +if [ ! -d "$dstdir" ]; then +defaultIFS=' + ' +IFS="${IFS-${defaultIFS}}" + +oIFS="${IFS}" +# Some sh's can't handle IFS=/ for some reason. +IFS='%' +set - `echo ${dstdir} | sed -e 's@/@%@g' -e 's@^%@/@'` +IFS="${oIFS}" + +pathcomp='' + +while [ $# -ne 0 ] ; do + pathcomp="${pathcomp}${1}" + shift + + if [ ! -d "${pathcomp}" ] ; + then + $mkdirprog "${pathcomp}" + else + : + fi + + pathcomp="${pathcomp}/" +done +fi + +if [ x"$dir_arg" != x ] +then + $doit $instcmd $dst && + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dst; else : ; fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dst; else : ; fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dst; else : ; fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dst; else : ; fi +else + +# If we're going to rename the final executable, determine the name now. + + if [ x"$transformarg" = x ] + then + dstfile=`basename $dst` + else + dstfile=`basename $dst $transformbasename | + sed $transformarg`$transformbasename + fi + +# don't allow the sed command to completely eliminate the filename + + if [ x"$dstfile" = x ] + then + dstfile=`basename $dst` + else + : + fi + +# Make a temp file name in the proper directory. + + dsttmp=$dstdir/#inst.$$# + +# Move or copy the file name to the temp name + + $doit $instcmd $src $dsttmp && + + trap "rm -f ${dsttmp}" 0 && + +# and set any options; do chmod last to preserve setuid bits + +# If any of these fail, we abort the whole thing. If we want to +# ignore errors from any of these, just make sure not to ignore +# errors from the above "$doit $instcmd $src $dsttmp" command. + + if [ x"$chowncmd" != x ]; then $doit $chowncmd $dsttmp; else :;fi && + if [ x"$chgrpcmd" != x ]; then $doit $chgrpcmd $dsttmp; else :;fi && + if [ x"$stripcmd" != x ]; then $doit $stripcmd $dsttmp; else :;fi && + if [ x"$chmodcmd" != x ]; then $doit $chmodcmd $dsttmp; else :;fi && + +# Now rename the file to the real destination. + + $doit $rmcmd -f $dstdir/$dstfile && + $doit $mvcmd $dsttmp $dstdir/$dstfile + +fi && + + +exit 0 diff --git a/trunk/ltconfig b/trunk/ltconfig new file mode 100755 index 0000000..c14d83c --- /dev/null +++ b/trunk/ltconfig @@ -0,0 +1,3114 @@ +#! /bin/sh + +# ltconfig - Create a system-specific libtool. +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# This file is free software; you can 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# A lot of this script is taken from autoconf-2.10. + +# Check that we are running under the correct shell. +SHELL=${CONFIG_SHELL-/bin/sh} +echo=echo +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell. + exec "$SHELL" "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit 0 +fi + +# Find the correct PATH separator. Usually this is `:', but +# DJGPP uses `;' like DOS. +if test "X${PATH_SEPARATOR+set}" != Xset; then + UNAME=${UNAME-`uname 2>/dev/null`} + case X$UNAME in + *-DOS) PATH_SEPARATOR=';' ;; + *) PATH_SEPARATOR=':' ;; + esac +fi + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +if test "X${echo_test_string+set}" != Xset; then + # find a string as large as possible, as long as the shell can cope with it + for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do + # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... + if (echo_test_string="`eval $cmd`") 2>/dev/null && + echo_test_string="`eval $cmd`" && + (test "X$echo_test_string" = "X$echo_test_string") 2>/dev/null; then + break + fi + done +fi + +if test "X`($echo '\t') 2>/dev/null`" != 'X\t' || + test "X`($echo "$echo_test_string") 2>/dev/null`" != X"$echo_test_string"; then + # The Solaris, AIX, and Digital Unix default echo programs unquote + # backslashes. This makes it impossible to quote backslashes using + # echo "$something" | sed 's/\\/\\\\/g' + # + # So, first we look for a working echo in the user's PATH. + + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH /usr/ucb; do + if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && + test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($dir/echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$dir/echo" + break + fi + done + IFS="$save_ifs" + + if test "X$echo" = Xecho; then + # We didn't find a better echo, so look for alternatives. + if test "X`(print -r '\t') 2>/dev/null`" = 'X\t' && + test "X`(print -r "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # This shell has a builtin print -r that does the trick. + echo='print -r' + elif (test -f /bin/ksh || test -f /bin/ksh$ac_exeext) && + test "X$CONFIG_SHELL" != X/bin/ksh; then + # If we have ksh, try running ltconfig again with it. + ORIGINAL_CONFIG_SHELL="${CONFIG_SHELL-/bin/sh}" + export ORIGINAL_CONFIG_SHELL + CONFIG_SHELL=/bin/ksh + export CONFIG_SHELL + exec "$CONFIG_SHELL" "$0" --no-reexec ${1+"$@"} + else + # Try using printf. + echo='printf "%s\n"' + if test "X`($echo '\t') 2>/dev/null`" = 'X\t' && + test "X`($echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + # Cool, printf works + : + elif test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$ORIGINAL_CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + CONFIG_SHELL="$ORIGINAL_CONFIG_SHELL" + export CONFIG_SHELL + SHELL="$CONFIG_SHELL" + export SHELL + echo="$CONFIG_SHELL $0 --fallback-echo" + elif test "X`("$CONFIG_SHELL" "$0" --fallback-echo '\t') 2>/dev/null`" = 'X\t' && + test "X`("$CONFIG_SHELL" "$0" --fallback-echo "$echo_test_string") 2>/dev/null`" = X"$echo_test_string"; then + echo="$CONFIG_SHELL $0 --fallback-echo" + else + # maybe with a smaller string... + prev=: + + for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do + if (test "X$echo_test_string" = "X`eval $cmd`") 2>/dev/null; then + break + fi + prev="$cmd" + done + + if test "$prev" != 'sed 50q "$0"'; then + echo_test_string=`eval $prev` + export echo_test_string + exec "${ORIGINAL_CONFIG_SHELL}" "$0" ${1+"$@"} + else + # Oops. We lost completely, so just stick with echo. + echo=echo + fi + fi + fi + fi +fi + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e s/^X//' +sed_quote_subst='s/\([\\"\\`$\\\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([\\"\\`\\\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# The name of this program. +progname=`$echo "X$0" | $Xsed -e 's%^.*/%%'` + +# Constants: +PROGRAM=ltconfig +PACKAGE=libtool +VERSION=1.3.5 +TIMESTAMP=" (1.385.2.206 2000/05/27 11:12:27)" +ac_compile='${CC-cc} -c $CFLAGS $CPPFLAGS conftest.$ac_ext 1>&5' +ac_link='${CC-cc} -o conftest $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS 1>&5' +rm="rm -f" + +help="Try \`$progname --help' for more information." + +# Global variables: +default_ofile=libtool +can_build_shared=yes +enable_shared=yes +# All known linkers require a `.a' archive for static linking (except M$VC, +# which needs '.lib'). +enable_static=yes +enable_fast_install=yes +enable_dlopen=unknown +enable_win32_dll=no +ltmain= +silent= +srcdir= +ac_config_guess= +ac_config_sub= +host= +nonopt= +ofile="$default_ofile" +verify_host=yes +with_gcc=no +with_gnu_ld=no +need_locks=yes +ac_ext=c +objext=o +libext=a +exeext= +cache_file= + +old_AR="$AR" +old_CC="$CC" +old_CFLAGS="$CFLAGS" +old_CPPFLAGS="$CPPFLAGS" +old_LDFLAGS="$LDFLAGS" +old_LD="$LD" +old_LN_S="$LN_S" +old_LIBS="$LIBS" +old_NM="$NM" +old_RANLIB="$RANLIB" +old_DLLTOOL="$DLLTOOL" +old_OBJDUMP="$OBJDUMP" +old_AS="$AS" + +# Parse the command line options. +args= +prev= +for option +do + case "$option" in + -*=*) optarg=`echo "$option" | sed 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + eval "$prev=\$option" + prev= + continue + fi + + case "$option" in + --help) cat <<EOM +Usage: $progname [OPTION]... [HOST [LTMAIN]] + +Generate a system-specific libtool script. + + --debug enable verbose shell tracing + --disable-shared do not build shared libraries + --disable-static do not build static libraries + --disable-fast-install do not optimize for fast installation + --enable-dlopen enable dlopen support + --enable-win32-dll enable building dlls on win32 hosts + --help display this help and exit + --no-verify do not verify that HOST is a valid host type +-o, --output=FILE specify the output file [default=$default_ofile] + --quiet same as \`--silent' + --silent do not print informational messages + --srcdir=DIR find \`config.guess' in DIR + --version output version information and exit + --with-gcc assume that the GNU C compiler will be used + --with-gnu-ld assume that the C compiler uses the GNU linker + --disable-lock disable file locking + --cache-file=FILE configure cache file + +LTMAIN is the \`ltmain.sh' shell script fragment or \`ltmain.c' program +that provides basic libtool functionality. + +HOST is the canonical host system name [default=guessed]. +EOM + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --disable-shared) enable_shared=no ;; + + --disable-static) enable_static=no ;; + + --disable-fast-install) enable_fast_install=no ;; + + --enable-dlopen) enable_dlopen=yes ;; + + --enable-win32-dll) enable_win32_dll=yes ;; + + --quiet | --silent) silent=yes ;; + + --srcdir) prev=srcdir ;; + --srcdir=*) srcdir="$optarg" ;; + + --no-verify) verify_host=no ;; + + --output | -o) prev=ofile ;; + --output=*) ofile="$optarg" ;; + + --version) echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP"; exit 0 ;; + + --with-gcc) with_gcc=yes ;; + --with-gnu-ld) with_gnu_ld=yes ;; + + --disable-lock) need_locks=no ;; + + --cache-file=*) cache_file="$optarg" ;; + + -*) + echo "$progname: unrecognized option \`$option'" 1>&2 + echo "$help" 1>&2 + exit 1 + ;; + + *) + if test -z "$ltmain"; then + ltmain="$option" + elif test -z "$host"; then +# This generates an unnecessary warning for sparc-sun-solaris4.1.3_U1 +# if test -n "`echo $option| sed 's/[-a-z0-9.]//g'`"; then +# echo "$progname: warning \`$option' is not a valid host type" 1>&2 +# fi + host="$option" + else + echo "$progname: too many arguments" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac +done + +if test -z "$ltmain"; then + echo "$progname: you must specify a LTMAIN file" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +if test ! -f "$ltmain"; then + echo "$progname: \`$ltmain' does not exist" 1>&2 + echo "$help" 1>&2 + exit 1 +fi + +# Quote any args containing shell metacharacters. +ltconfig_args= +for arg +do + case "$arg" in + *" "*|*" "*|*[\[\]\~\#\$\^\&\*\(\)\{\}\\\|\;\<\>\?]*) + ltconfig_args="$ltconfig_args '$arg'" ;; + *) ltconfig_args="$ltconfig_args $arg" ;; + esac +done + +# A relevant subset of AC_INIT. + +# File descriptor usage: +# 0 standard input +# 1 file creation +# 2 errors and warnings +# 3 some systems may open it to /dev/tty +# 4 used on the Kubota Titan +# 5 compiler messages saved in config.log +# 6 checking for... messages and results +if test "$silent" = yes; then + exec 6>/dev/null +else + exec 6>&1 +fi +exec 5>>./config.log + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +if test "X${LC_ALL+set}" = Xset; then LC_ALL=C; export LC_ALL; fi +if test "X${LANG+set}" = Xset; then LANG=C; export LANG; fi + +if test -n "$cache_file" && test -r "$cache_file"; then + echo "loading cache $cache_file within ltconfig" + . $cache_file +fi + +if (echo "testing\c"; echo 1,2,3) | grep c >/dev/null; then + # Stardent Vistra SVR4 grep lacks -e, says ghazi@caip.rutgers.edu. + if (echo -n testing; echo 1,2,3) | sed s/-n/xn/ | grep xn >/dev/null; then + ac_n= ac_c=' +' ac_t=' ' + else + ac_n=-n ac_c= ac_t= + fi +else + ac_n= ac_c='\c' ac_t= +fi + +if test -z "$srcdir"; then + # Assume the source directory is the same one as the path to LTMAIN. + srcdir=`$echo "X$ltmain" | $Xsed -e 's%/[^/]*$%%'` + test "$srcdir" = "$ltmain" && srcdir=. +fi + +trap "$rm conftest*; exit 1" 1 2 15 +if test "$verify_host" = yes; then + # Check for config.guess and config.sub. + ac_aux_dir= + for ac_dir in $srcdir $srcdir/.. $srcdir/../..; do + if test -f $ac_dir/config.guess; then + ac_aux_dir=$ac_dir + break + fi + done + if test -z "$ac_aux_dir"; then + echo "$progname: cannot find config.guess in $srcdir $srcdir/.. $srcdir/../.." 1>&2 + echo "$help" 1>&2 + exit 1 + fi + ac_config_guess=$ac_aux_dir/config.guess + ac_config_sub=$ac_aux_dir/config.sub + + # Make sure we can run config.sub. + if $SHELL $ac_config_sub sun4 >/dev/null 2>&1; then : + else + echo "$progname: cannot run $ac_config_sub" 1>&2 + echo "$help" 1>&2 + exit 1 + fi + + echo $ac_n "checking host system type""... $ac_c" 1>&6 + + host_alias=$host + case "$host_alias" in + "") + if host_alias=`$SHELL $ac_config_guess`; then : + else + echo "$progname: cannot guess host type; you must specify one" 1>&2 + echo "$help" 1>&2 + exit 1 + fi ;; + esac + host=`$SHELL $ac_config_sub $host_alias` + echo "$ac_t$host" 1>&6 + + # Make sure the host verified. + test -z "$host" && exit 1 + +elif test -z "$host"; then + echo "$progname: you must specify a host type if you use \`--no-verify'" 1>&2 + echo "$help" 1>&2 + exit 1 +else + host_alias=$host +fi + +# Transform linux* to *-*-linux-gnu*, to support old configure scripts. +case "$host_os" in +linux-gnu*) ;; +linux*) host=`echo $host | sed 's/^\(.*-.*-linux\)\(.*\)$/\1-gnu\2/'` +esac + +host_cpu=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'` +host_vendor=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\2/'` +host_os=`echo $host | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\3/'` + +case "$host_os" in +aix3*) + # AIX sometimes has problems with the GCC collect2 program. For some + # reason, if we set the COLLECT_NAMES environment variable, the problems + # vanish in a puff of smoke. + if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES + fi + ;; +esac + +# Determine commands to create old-style static archives. +old_archive_cmds='$AR cru $oldlib$oldobjs' +old_postinstall_cmds='chmod 644 $oldlib' +old_postuninstall_cmds= + +# Set a sane default for `AR'. +test -z "$AR" && AR=ar + +# Set a sane default for `OBJDUMP'. +test -z "$OBJDUMP" && OBJDUMP=objdump + +# If RANLIB is not set, then run the test. +if test "${RANLIB+set}" != "set"; then + result=no + + echo $ac_n "checking for ranlib... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/ranlib || test -f $dir/ranlib$ac_exeext; then + RANLIB="ranlib" + result="ranlib" + break + fi + done + IFS="$save_ifs" + + echo "$ac_t$result" 1>&6 +fi + +if test -n "$RANLIB"; then + old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" + old_postinstall_cmds="\$RANLIB \$oldlib~$old_postinstall_cmds" +fi + +# Set sane defaults for `DLLTOOL', `OBJDUMP', and `AS', used on cygwin. +test -z "$DLLTOOL" && DLLTOOL=dlltool +test -z "$OBJDUMP" && OBJDUMP=objdump +test -z "$AS" && AS=as + +# Check to see if we are using GCC. +if test "$with_gcc" != yes || test -z "$CC"; then + # If CC is not set, then try to find GCC or a usable CC. + if test -z "$CC"; then + echo $ac_n "checking for gcc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/gcc || test -f $dir/gcc$ac_exeext; then + CC="gcc" + break + fi + done + IFS="$save_ifs" + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + fi + + # Not "gcc", so try "cc", rejecting "/usr/ucb/cc". + if test -z "$CC"; then + echo $ac_n "checking for cc... $ac_c" 1>&6 + IFS="${IFS= }"; save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + cc_rejected=no + for dir in $PATH; do + test -z "$dir" && dir=. + if test -f $dir/cc || test -f $dir/cc$ac_exeext; then + if test "$dir/cc" = "/usr/ucb/cc"; then + cc_rejected=yes + continue + fi + CC="cc" + break + fi + done + IFS="$save_ifs" + if test $cc_rejected = yes; then + # We found a bogon in the path, so make sure we never use it. + set dummy $CC + shift + if test $# -gt 0; then + # We chose a different compiler from the bogus one. + # However, it has the same name, so the bogon will be chosen + # first if we set CC to just the name; use the full file name. + shift + set dummy "$dir/cc" "$@" + shift + CC="$@" + fi + fi + + if test -n "$CC"; then + echo "$ac_t$CC" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$CC"; then + echo "$progname: error: no acceptable cc found in \$PATH" 1>&2 + exit 1 + fi + fi + + # Now see if the compiler is really GCC. + with_gcc=no + echo $ac_n "checking whether we are using GNU C... $ac_c" 1>&6 + echo "$progname:581: checking whether we are using GNU C" >&5 + + $rm conftest.c + cat > conftest.c <<EOF +#ifdef __GNUC__ + yes; +#endif +EOF + if { ac_try='${CC-cc} -E conftest.c'; { (eval echo $progname:589: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }; } | egrep yes >/dev/null 2>&1; then + with_gcc=yes + fi + $rm conftest.c + echo "$ac_t$with_gcc" 1>&6 +fi + +# Allow CC to be a program name with arguments. +set dummy $CC +compiler="$2" + +echo $ac_n "checking for object suffix... $ac_c" 1>&6 +$rm conftest* +echo 'int i = 1;' > conftest.c +echo "$progname:603: checking for object suffix" >& 5 +if { (eval echo $progname:604: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c) ;; + *) objext=`echo $ac_file | sed -e s/conftest.//` ;; + esac + done +else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 +fi +$rm conftest* +echo "$ac_t$objext" 1>&6 + +echo $ac_n "checking for executable suffix... $ac_c" 1>&6 +if eval "test \"`echo '$''{'ac_cv_exeext'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_cv_exeext="no" + $rm conftest* + echo 'main () { return 0; }' > conftest.c + echo "$progname:629: checking for executable suffix" >& 5 + if { (eval echo $progname:630: \"$ac_link\") 1>&5; (eval $ac_link) 2>conftest.err; }; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + for ac_file in conftest.*; do + case $ac_file in + *.c | *.err | *.$objext ) ;; + *) ac_cv_exeext=.`echo $ac_file | sed -e s/conftest.//` ;; + esac + done + else + cat conftest.err 1>&5 + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* +fi +if test "X$ac_cv_exeext" = Xno; then + exeext="" +else + exeext="$ac_cv_exeext" +fi +echo "$ac_t$ac_cv_exeext" 1>&6 + +echo $ac_n "checking for $compiler option to produce PIC... $ac_c" 1>&6 +pic_flag= +special_shlib_compile_flags= +wl= +link_static_flag= +no_builtin_flag= + +if test "$with_gcc" = yes; then + wl='-Wl,' + link_static_flag='-static' + + case "$host_os" in + beos* | irix5* | irix6* | osf3* | osf4* | osf5*) + # PIC is the default for these OSes. + ;; + aix*) + # Below there is a dirty hack to force normal static linking with -ldl + # The problem is because libdl dynamically linked with both libc and + # libC (AIX C++ library), which obviously doesn't included in libraries + # list by gcc. This cause undefined symbols with -static flags. + # This hack allows C programs to be linked with "-static -ldl", but + # we not sure about C++ programs. + link_static_flag="$link_static_flag ${wl}-lC" + ;; + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + amigaos*) + # FIXME: we need at least 68020 code to build shared libraries, but + # adding the `-m68020' flag to GCC prevents building anything better, + # like `-m68040'. + pic_flag='-m68020 -resident32 -malways-restore-a4' + ;; + sysv4*MP*) + if test -d /usr/nec; then + pic_flag=-Kconform_pic + fi + ;; + *) + pic_flag='-fPIC' + ;; + esac +else + # PORTME Check for PIC flags for the system compiler. + case "$host_os" in + aix3* | aix4*) + # All AIX code is PIC. + link_static_flag='-bnso -bI:/lib/syscalls.exp' + ;; + + hpux9* | hpux10* | hpux11*) + # Is there a better link_static_flag that works with the bundled CC? + wl='-Wl,' + link_static_flag="${wl}-a ${wl}archive" + pic_flag='+Z' + ;; + + irix5* | irix6*) + wl='-Wl,' + link_static_flag='-non_shared' + # PIC (with -KPIC) is the default. + ;; + + cygwin* | mingw* | os2*) + # We can build DLLs from non-PIC. + ;; + + osf3* | osf4* | osf5*) + # All OSF/1 code is PIC. + wl='-Wl,' + link_static_flag='-non_shared' + ;; + + sco3.2v5*) + pic_flag='-Kpic' + link_static_flag='-dn' + special_shlib_compile_flags='-belf' + ;; + + solaris*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + sunos4*) + pic_flag='-PIC' + link_static_flag='-Bstatic' + wl='-Qoption ld ' + ;; + + sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + pic_flag='-KPIC' + link_static_flag='-Bstatic' + wl='-Wl,' + ;; + + uts4*) + pic_flag='-pic' + link_static_flag='-Bstatic' + ;; + sysv4*MP*) + if test -d /usr/nec ;then + pic_flag='-Kconform_pic' + link_static_flag='-Bstatic' + fi + ;; + *) + can_build_shared=no + ;; + esac +fi + +if test -n "$pic_flag"; then + echo "$ac_t$pic_flag" 1>&6 + + # Check to make sure the pic_flag actually works. + echo $ac_n "checking if $compiler PIC flag $pic_flag works... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS $pic_flag -DPIC" + echo "$progname:776: checking if $compiler PIC flag $pic_flag works" >&5 + if { (eval echo $progname:777: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.$objext; then + # Append any warnings to the config.log. + cat conftest.err 1>&5 + + case "$host_os" in + hpux9* | hpux10* | hpux11*) + # On HP-UX, both CC and GCC only warn that PIC is supported... then they + # create non-PIC objects. So, if there were any warnings, we assume that + # PIC is not supported. + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + can_build_shared=no + pic_flag= + else + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + fi + ;; + *) + echo "$ac_t"yes 1>&6 + pic_flag=" $pic_flag" + ;; + esac + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + can_build_shared=no + pic_flag= + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + echo "$ac_t"none 1>&6 +fi + +# Check to see if options -o and -c are simultaneously supported by compiler +echo $ac_n "checking if $compiler supports -c -o file.o... $ac_c" 1>&6 +$rm -r conftest 2>/dev/null +mkdir conftest +cd conftest +$rm conftest* +echo "int some_variable = 0;" > conftest.c +mkdir out +# According to Tom Tromey, Ian Lance Taylor reported there are C compilers +# that will create temporary files in the current directory regardless of +# the output directory. Thus, making CWD read-only will cause this test +# to fail, enabling locking or at least warning the user not to do parallel +# builds. +chmod -w . +save_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS -o out/conftest2.o" +echo "$progname:829: checking if $compiler supports -c -o file.o" >&5 +if { (eval echo $progname:830: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>out/conftest.err; } && test -s out/conftest2.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s out/conftest.err; then + echo "$ac_t"no 1>&6 + compiler_c_o=no + else + echo "$ac_t"yes 1>&6 + compiler_c_o=yes + fi +else + # Append any errors to the config.log. + cat out/conftest.err 1>&5 + compiler_c_o=no + echo "$ac_t"no 1>&6 +fi +CFLAGS="$save_CFLAGS" +chmod u+w . +$rm conftest* out/* +rmdir out +cd .. +rmdir conftest +$rm -r conftest 2>/dev/null + +if test x"$compiler_c_o" = x"yes"; then + # Check to see if we can write to a .lo + echo $ac_n "checking if $compiler supports -c -o file.lo... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -c -o conftest.lo" + echo "$progname:862: checking if $compiler supports -c -o file.lo" >&5 +if { (eval echo $progname:863: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.lo; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_o_lo=no + else + echo "$ac_t"yes 1>&6 + compiler_o_lo=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_o_lo=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* +else + compiler_o_lo=no +fi + +# Check to see if we can do hard links to lock some files if needed +hard_links="nottested" +if test "$compiler_c_o" = no && test "$need_locks" != no; then + # do not overwrite the value of need_locks provided by the user + echo $ac_n "checking if we can lock with hard links... $ac_c" 1>&6 + hard_links=yes + $rm conftest* + ln conftest.a conftest.b 2>/dev/null && hard_links=no + touch conftest.a + ln conftest.a conftest.b 2>&5 || hard_links=no + ln conftest.a conftest.b 2>/dev/null && hard_links=no + echo "$ac_t$hard_links" 1>&6 + $rm conftest* + if test "$hard_links" = no; then + echo "*** WARNING: \`$CC' does not support \`-c -o', so \`make -j' may be unsafe" >&2 + need_locks=warn + fi +else + need_locks=no +fi + +if test "$with_gcc" = yes; then + # Check to see if options -fno-rtti -fno-exceptions are supported by compiler + echo $ac_n "checking if $compiler supports -fno-rtti -fno-exceptions ... $ac_c" 1>&6 + $rm conftest* + echo "int some_variable = 0;" > conftest.c + save_CFLAGS="$CFLAGS" + CFLAGS="$CFLAGS -fno-rtti -fno-exceptions -c conftest.c" + echo "$progname:914: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 + if { (eval echo $progname:915: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>conftest.err; } && test -s conftest.o; then + + # The compiler can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + echo "$ac_t"no 1>&6 + compiler_rtti_exceptions=no + else + echo "$ac_t"yes 1>&6 + compiler_rtti_exceptions=yes + fi + else + # Append any errors to the config.log. + cat conftest.err 1>&5 + compiler_rtti_exceptions=no + echo "$ac_t"no 1>&6 + fi + CFLAGS="$save_CFLAGS" + $rm conftest* + + if test "$compiler_rtti_exceptions" = "yes"; then + no_builtin_flag=' -fno-builtin -fno-rtti -fno-exceptions' + else + no_builtin_flag=' -fno-builtin' + fi + +fi + +# Check for any special shared library compilation flags. +if test -n "$special_shlib_compile_flags"; then + echo "$progname: warning: \`$CC' requires \`$special_shlib_compile_flags' to build shared libraries" 1>&2 + if echo "$old_CC $old_CFLAGS " | egrep -e "[ ]$special_shlib_compile_flags[ ]" >/dev/null; then : + else + echo "$progname: add \`$special_shlib_compile_flags' to the CC or CFLAGS env variable and reconfigure" 1>&2 + can_build_shared=no + fi +fi + +echo $ac_n "checking if $compiler static flag $link_static_flag works... $ac_c" 1>&6 +$rm conftest* +echo 'main(){return(0);}' > conftest.c +save_LDFLAGS="$LDFLAGS" +LDFLAGS="$LDFLAGS $link_static_flag" +echo "$progname:958: checking if $compiler static flag $link_static_flag works" >&5 +if { (eval echo $progname:959: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + echo "$ac_t$link_static_flag" 1>&6 +else + echo "$ac_t"none 1>&6 + link_static_flag= +fi +LDFLAGS="$save_LDFLAGS" +$rm conftest* + +if test -z "$LN_S"; then + # Check to see if we can use ln -s, or we need hard links. + echo $ac_n "checking whether ln -s works... $ac_c" 1>&6 + $rm conftest.dat + if ln -s X conftest.dat 2>/dev/null; then + $rm conftest.dat + LN_S="ln -s" + else + LN_S=ln + fi + if test "$LN_S" = "ln -s"; then + echo "$ac_t"yes 1>&6 + else + echo "$ac_t"no 1>&6 + fi +fi + +# Make sure LD is an absolute path. +if test -z "$LD"; then + ac_prog=ld + if test "$with_gcc" = yes; then + # Check if gcc -print-prog-name=ld gives a path. + echo $ac_n "checking for ld used by GCC... $ac_c" 1>&6 + echo "$progname:991: checking for ld used by GCC" >&5 + ac_prog=`($CC -print-prog-name=ld) 2>&5` + case "$ac_prog" in + # Accept absolute paths. + [\\/]* | [A-Za-z]:[\\/]*) + re_direlt='/[^/][^/]*/\.\./' + # Canonicalize the path of ld + ac_prog=`echo $ac_prog| sed 's%\\\\%/%g'` + while echo $ac_prog | grep "$re_direlt" > /dev/null 2>&1; do + ac_prog=`echo $ac_prog| sed "s%$re_direlt%/%"` + done + test -z "$LD" && LD="$ac_prog" + ;; + "") + # If it fails, then pretend we are not using GCC. + ac_prog=ld + ;; + *) + # If it is relative, then search for the first ld in PATH. + with_gnu_ld=unknown + ;; + esac + elif test "$with_gnu_ld" = yes; then + echo $ac_n "checking for GNU ld... $ac_c" 1>&6 + echo "$progname:1015: checking for GNU ld" >&5 + else + echo $ac_n "checking for non-GNU ld""... $ac_c" 1>&6 + echo "$progname:1018: checking for non-GNU ld" >&5 + fi + + if test -z "$LD"; then + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH; do + test -z "$ac_dir" && ac_dir=. + if test -f "$ac_dir/$ac_prog" || test -f "$ac_dir/$ac_prog$ac_exeext"; then + LD="$ac_dir/$ac_prog" + # Check to see if the program is GNU ld. I'd rather use --version, + # but apparently some GNU ld's only accept -v. + # Break only if it was the GNU/non-GNU ld that we prefer. + if "$LD" -v 2>&1 < /dev/null | egrep '(GNU|with BFD)' > /dev/null; then + test "$with_gnu_ld" != no && break + else + test "$with_gnu_ld" != yes && break + fi + fi + done + IFS="$ac_save_ifs" + fi + + if test -n "$LD"; then + echo "$ac_t$LD" 1>&6 + else + echo "$ac_t"no 1>&6 + fi + + if test -z "$LD"; then + echo "$progname: error: no acceptable ld found in \$PATH" 1>&2 + exit 1 + fi +fi + +# Check to see if it really is or is not GNU ld. +echo $ac_n "checking if the linker ($LD) is GNU ld... $ac_c" 1>&6 +# I'd rather use --version here, but apparently some GNU ld's only accept -v. +if $LD -v 2>&1 </dev/null | egrep '(GNU|with BFD)' 1>&5; then + with_gnu_ld=yes +else + with_gnu_ld=no +fi +echo "$ac_t$with_gnu_ld" 1>&6 + +# See if the linker supports building shared libraries. +echo $ac_n "checking whether the linker ($LD) supports shared libraries... $ac_c" 1>&6 + +allow_undefined_flag= +no_undefined_flag= +need_lib_prefix=unknown +need_version=unknown +# when you set need_version to no, make sure it does not cause -set_version +# flags to be left without arguments +archive_cmds= +archive_expsym_cmds= +old_archive_from_new_cmds= +export_dynamic_flag_spec= +whole_archive_flag_spec= +thread_safe_flag_spec= +hardcode_libdir_flag_spec= +hardcode_libdir_separator= +hardcode_direct=no +hardcode_minus_L=no +hardcode_shlibpath_var=unsupported +runpath_var= +always_export_symbols=no +export_symbols_cmds='$NM $libobjs $convenience | $global_symbol_pipe | sed '\''s/.* //'\'' | sort | uniq > $export_symbols' +# include_expsyms should be a list of space-separated symbols to be *always* +# included in the symbol list +include_expsyms= +# exclude_expsyms can be an egrep regular expression of symbols to exclude +# it will be wrapped by ` (' and `)$', so one must not match beginning or +# end of line. Example: `a|bc|.*d.*' will exclude the symbols `a' and `bc', +# as well as any symbol that contains `d'. +exclude_expsyms="_GLOBAL_OFFSET_TABLE_" +# Although _GLOBAL_OFFSET_TABLE_ is a valid symbol C name, most a.out +# platforms (ab)use it in PIC code, but their linkers get confused if +# the symbol is explicitly referenced. Since portable code cannot +# rely on this symbol name, it's probably fine to never include it in +# preloaded symbol tables. + +case "$host_os" in +cygwin* | mingw*) + # FIXME: the MSVC++ port hasn't been tested in a loooong time + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + if test "$with_gcc" != yes; then + with_gnu_ld=no + fi + ;; + +esac + +ld_shlibs=yes +if test "$with_gnu_ld" = yes; then + # If archive_cmds runs LD, not CC, wlarc should be empty + wlarc='${wl}' + + # See if GNU ld supports shared libraries. + case "$host_os" in + aix3* | aix4*) + # On AIX, the GNU linker is very broken + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** to be unable to reliably create shared libraries on AIX. +*** Therefore, libtool is disabling shared libraries support. If you +*** really care for shared libraries, you may want to modify your PATH +*** so that a non-GNU linker is found, and then restart. + +EOF + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + + # Samuel A. Falvo II <kc5tja@dolphin.openprojects.net> reports + # that the semantics of dynamic libraries on AmigaOS, at least up + # to version 4, is to share data among multiple programs linked + # with the same dynamic library. Since this doesn't match the + # behavior of shared libraries on other platforms, we can use + # them. + ld_shlibs=no + ;; + + beos*) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + allow_undefined_flag=unsupported + # Joseph Beckenbach <jrb3@best.com> says some releases of gcc + # support --undefined. This deserves some investigation. FIXME + archive_cmds='$CC -nostart $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + else + ld_shlibs=no + fi + ;; + + cygwin* | mingw*) + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec='-L$libdir' + allow_undefined_flag=unsupported + always_export_symbols=yes + + # Extract the symbol export list from an `--export-all' def file, + # then regenerate the def file from the symbol export list, so that + # the compiled dll only exports the symbol export list. + # Be careful not to strip the DATA tag left by newer dlltools. + export_symbols_cmds='test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $DLLTOOL --export-all --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --output-def $objdir/$soname-def $objdir/$soname-ltdll.$objext $libobjs $convenience~ + sed -e "1,/EXPORTS/d" -e "s/ @ [0-9]*//" -e "s/ *;.*$//" < $objdir/$soname-def > $export_symbols' + + # If DATA tags from a recent dlltool are present, honour them! + archive_expsym_cmds='echo EXPORTS > $objdir/$soname-def~ + _lt_hint=1; + cat $export_symbols | while read symbol; do + set dummy \$symbol; + case \$# in + 2) echo " \$2 @ \$_lt_hint ; " >> $objdir/$soname-def;; + *) echo " \$2 @ \$_lt_hint \$3 ; " >> $objdir/$soname-def;; + esac; + _lt_hint=`expr 1 + \$_lt_hint`; + done~ + test -f $objdir/$soname-ltdll.c || sed -e "/^# \/\* ltdll\.c starts here \*\//,/^# \/\* ltdll.c ends here \*\// { s/^# //; p; }" -e d < $0 > $objdir/$soname-ltdll.c~ + test -f $objdir/$soname-ltdll.$objext || (cd $objdir && $CC -c $soname-ltdll.c)~ + $CC -Wl,--base-file,$objdir/$soname-base -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC -Wl,--base-file,$objdir/$soname-base $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts~ + $DLLTOOL --as=$AS --dllname $soname --exclude-symbols DllMain@12,_cygwin_dll_entry@12,_cygwin_noncygwin_dll_entry@12 --def $objdir/$soname-def --base-file $objdir/$soname-base --output-exp $objdir/$soname-exp~ + $CC $objdir/$soname-exp -Wl,--dll -nostartfiles -Wl,-e,__cygwin_dll_entry@12 -o $lib $objdir/$soname-ltdll.$objext $libobjs $deplibs $linkopts' + + old_archive_from_new_cmds='$DLLTOOL --as=$AS --dllname $soname --def $objdir/$soname-def --output-lib $objdir/$libname.a' + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + archive_cmds='$LD -Bshareable $libobjs $deplibs $linkopts -o $lib' + # can we support soname and/or expsyms with a.out? -oliva + fi + ;; + + solaris* | sysv5*) + if $LD -v 2>&1 | egrep 'BFD 2\.8' > /dev/null; then + ld_shlibs=no + cat <<EOF 1>&2 + +*** Warning: The releases 2.8.* of the GNU linker cannot reliably +*** create shared libraries on Solaris systems. Therefore, libtool +*** is disabling shared libraries support. We urge you to upgrade GNU +*** binutils to release 2.9.1 or newer. Another option is to modify +*** your PATH or compiler configuration so that the native linker is +*** used, and then restart. + +EOF + elif $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bshareable -o $lib $libobjs $deplibs $linkopts' + wlarc= + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + *) + if $LD --help 2>&1 | egrep ': supported targets:.* elf' > /dev/null; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname $wl$soname ${wl}-retain-symbols-file $wl$export_symbols -o $lib' + else + ld_shlibs=no + fi + ;; + esac + + if test "$ld_shlibs" = yes; then + runpath_var=LD_RUN_PATH + hardcode_libdir_flag_spec='${wl}--rpath ${wl}$libdir' + export_dynamic_flag_spec='${wl}--export-dynamic' + case $host_os in + cygwin* | mingw*) + # dlltool doesn't understand --whole-archive et. al. + whole_archive_flag_spec= + ;; + *) + # ancient GNU ld didn't support --whole-archive et. al. + if $LD --help 2>&1 | egrep 'no-whole-archive' > /dev/null; then + whole_archive_flag_spec="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' + else + whole_archive_flag_spec= + fi + ;; + esac + fi +else + # PORTME fill in a description of your system's linker (not GNU ld) + case "$host_os" in + aix3*) + allow_undefined_flag=unsupported + always_export_symbols=yes + archive_expsym_cmds='$LD -o $objdir/$soname $libobjs $deplibs $linkopts -bE:$export_symbols -T512 -H512 -bM:SRE~$AR cru $lib $objdir/$soname' + # Note: this linker hardcodes the directories in LIBPATH if there + # are no directories specified by -L. + hardcode_minus_L=yes + if test "$with_gcc" = yes && test -z "$link_static_flag"; then + # Neither direct hardcoding nor static linking is supported with a + # broken collect2. + hardcode_direct=unsupported + fi + ;; + + aix4*) + hardcode_libdir_flag_spec='${wl}-b ${wl}nolibpath ${wl}-b ${wl}libpath:$libdir:/usr/lib:/lib' + hardcode_libdir_separator=':' + if test "$with_gcc" = yes; then + collect2name=`${CC} -print-prog-name=collect2` + if test -f "$collect2name" && \ + strings "$collect2name" | grep resolve_lib_name >/dev/null + then + # We have reworked collect2 + hardcode_direct=yes + else + # We have old collect2 + hardcode_direct=unsupported + # It fails to find uninstalled libraries when the uninstalled + # path is not listed in the libpath. Setting hardcode_minus_L + # to unsupported forces relinking + hardcode_minus_L=yes + hardcode_libdir_flag_spec='-L$libdir' + hardcode_libdir_separator= + fi + shared_flag='-shared' + else + shared_flag='${wl}-bM:SRE' + hardcode_direct=yes + fi + allow_undefined_flag=' ${wl}-berok' + archive_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bexpall ${wl}-bnoentry${allow_undefined_flag}' + archive_expsym_cmds="\$CC $shared_flag"' -o $objdir/$soname $libobjs $deplibs $linkopts ${wl}-bE:$export_symbols ${wl}-bnoentry${allow_undefined_flag}' + case "$host_os" in aix4.[01]|aix4.[01].*) + # According to Greg Wooledge, -bexpall is only supported from AIX 4.2 on + always_export_symbols=yes ;; + esac + ;; + + amigaos*) + archive_cmds='$rm $objdir/a2ixlibrary.data~$echo "#define NAME $libname" > $objdir/a2ixlibrary.data~$echo "#define LIBRARY_ID 1" >> $objdir/a2ixlibrary.data~$echo "#define VERSION $major" >> $objdir/a2ixlibrary.data~$echo "#define REVISION $revision" >> $objdir/a2ixlibrary.data~$AR cru $lib $libobjs~$RANLIB $lib~(cd $objdir && a2ixlibrary -32)' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + # see comment about different semantics on the GNU ld section + ld_shlibs=no + ;; + + cygwin* | mingw*) + # When not using gcc, we currently assume that we are using + # Microsoft Visual C++. + # hardcode_libdir_flag_spec is actually meaningless, as there is + # no search path for DLLs. + hardcode_libdir_flag_spec=' ' + allow_undefined_flag=unsupported + # Tell ltmain to make .lib files, not .a files. + libext=lib + # FIXME: Setting linknames here is a bad hack. + archive_cmds='$CC -o $lib $libobjs $linkopts `echo "$deplibs" | sed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + # The linker will automatically build a .lib file if we build a DLL. + old_archive_from_new_cmds='true' + # FIXME: Should let the user specify the lib program. + old_archive_cmds='lib /OUT:$oldlib$oldobjs' + fix_srcfile_path='`cygpath -w $srcfile`' + ;; + + freebsd1*) + ld_shlibs=no + ;; + + # FreeBSD 2.2.[012] allows us to include c++rt0.o to get C++ constructor + # support. Future versions do this automatically, but an explicit c++rt0.o + # does not break anything, and helps significantly (at the cost of a little + # extra space). + freebsd2.2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts /usr/lib/c++rt0.o' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + # Unfortunately, older versions of FreeBSD 2 do not have this feature. + freebsd2*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + # FreeBSD 3 and greater uses gcc -shared to do shared libraries. + freebsd*) + archive_cmds='$CC -shared -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + hpux9* | hpux10* | hpux11*) + case "$host_os" in + hpux9*) archive_cmds='$rm $objdir/$soname~$LD -b +b $install_libdir -o $objdir/$soname $libobjs $deplibs $linkopts~test $objdir/$soname = $lib || mv $objdir/$soname $lib' ;; + *) archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linkopts' ;; + esac + hardcode_libdir_flag_spec='${wl}+b ${wl}$libdir' + hardcode_libdir_separator=: + hardcode_direct=yes + hardcode_minus_L=yes # Not in the search PATH, but as the default + # location of the library. + export_dynamic_flag_spec='${wl}-E' + ;; + + irix5* | irix6*) + if test "$with_gcc" = yes; then + archive_cmds='$CC -shared $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + archive_cmds='$LD -shared $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + netbsd*) + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' # a.out + else + archive_cmds='$LD -shared -o $lib $libobjs $deplibs $linkopts' # ELF + fi + hardcode_libdir_flag_spec='${wl}-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + openbsd*) + archive_cmds='$LD -Bshareable -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + os2*) + hardcode_libdir_flag_spec='-L$libdir' + hardcode_minus_L=yes + allow_undefined_flag=unsupported + archive_cmds='$echo "LIBRARY $libname INITINSTANCE" > $objdir/$libname.def~$echo "DESCRIPTION \"$libname\"" >> $objdir/$libname.def~$echo DATA >> $objdir/$libname.def~$echo " SINGLE NONSHARED" >> $objdir/$libname.def~$echo EXPORTS >> $objdir/$libname.def~emxexp $libobjs >> $objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $linkopts $objdir/$libname.def' + old_archive_from_new_cmds='emximp -o $objdir/$libname.a $objdir/$libname.def' + ;; + + osf3*) + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + + osf4* | osf5*) # As osf3* with the addition of the -msym flag + if test "$with_gcc" = yes; then + allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $linkopts ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && echo ${wl}-set_version ${wl}$verstring` ${wl}-update_registry ${wl}${objdir}/so_locations -o $lib' + else + allow_undefined_flag=' -expect_unresolved \*' + archive_cmds='$LD -shared${allow_undefined_flag} $libobjs $deplibs $linkopts -msym -soname $soname `test -n "$verstring" && echo -set_version $verstring` -update_registry ${objdir}/so_locations -o $lib' + fi + hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' + hardcode_libdir_separator=: + ;; + rhapsody*) + archive_cmds='$CC -bundle -undefined suppress -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flags_spec='-L$libdir' + hardcode_direct=yes + hardcode_shlibpath_var=no + ;; + + sco3.2v5*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ;; + + solaris*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec='-R$libdir' + hardcode_shlibpath_var=no + case "$host_os" in + solaris2.[0-5] | solaris2.[0-5].*) ;; + *) # Supported since Solaris 2.6 (maybe 2.5.1?) + whole_archive_flag_spec='-z allextract$convenience -z defaultextract' ;; + esac + ;; + + sunos4*) + archive_cmds='$LD -assert pure-text -Bstatic -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_direct=yes + hardcode_minus_L=yes + hardcode_shlibpath_var=no + ;; + + sysv4) + if test "x$host_vendor" = xsequent; then + # Use $CC to link under sequent, because it throws in some extra .o + # files that make .init and .fini sections work. + archive_cmds='$CC -G ${wl}-h $soname -o $lib $libobjs $deplibs $linkopts' + else + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + fi + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + hardcode_direct=no #Motorola manual says yes, but my tests say they lie + ;; + + sysv4.3*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + export_dynamic_flag_spec='-Bexport' + ;; + + sysv5*) + no_undefined_flag=' -z text' + # $CC -shared without GNU ld will not create a library from C++ + # object files and a static libstdc++, better avoid it by now + archive_cmds='$LD -G${allow_undefined_flag} -h $soname -o $lib $libobjs $deplibs $linkopts' + archive_expsym_cmds='$echo "{ global:" > $lib.exp~cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $lib.exp~$echo "local: *; };" >> $lib.exp~ + $LD -G${allow_undefined_flag} -M $lib.exp -h $soname -o $lib $libobjs $deplibs $linkopts~$rm $lib.exp' + hardcode_libdir_flag_spec= + hardcode_shlibpath_var=no + runpath_var='LD_RUN_PATH' + ;; + + uts4*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + dgux*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_libdir_flag_spec='-L$libdir' + hardcode_shlibpath_var=no + ;; + + sysv4*MP*) + if test -d /usr/nec; then + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + hardcode_shlibpath_var=no + runpath_var=LD_RUN_PATH + hardcode_runpath_var=yes + ld_shlibs=yes + fi + ;; + + sysv4.2uw2*) + archive_cmds='$LD -G -o $lib $libobjs $deplibs $linkopts' + hardcode_direct=yes + hardcode_minus_L=no + hardcode_shlibpath_var=no + hardcode_runpath_var=yes + runpath_var=LD_RUN_PATH + ;; + + unixware7*) + archive_cmds='$LD -G -h $soname -o $lib $libobjs $deplibs $linkopts' + runpath_var='LD_RUN_PATH' + hardcode_shlibpath_var=no + ;; + + *) + ld_shlibs=no + ;; + esac +fi +echo "$ac_t$ld_shlibs" 1>&6 +test "$ld_shlibs" = no && can_build_shared=no + +if test -z "$NM"; then + echo $ac_n "checking for BSD-compatible nm... $ac_c" 1>&6 + case "$NM" in + [\\/]* | [A-Za-z]:[\\/]*) ;; # Let the user override the test with a path. + *) + IFS="${IFS= }"; ac_save_ifs="$IFS"; IFS="${IFS}${PATH_SEPARATOR}" + for ac_dir in $PATH /usr/ucb /usr/ccs/bin /bin; do + test -z "$ac_dir" && ac_dir=. + if test -f $ac_dir/nm || test -f $ac_dir/nm$ac_exeext; then + # Check to see if the nm accepts a BSD-compat flag. + # Adding the `sed 1q' prevents false positives on HP-UX, which says: + # nm: unknown option "B" ignored + if ($ac_dir/nm -B /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -B" + break + elif ($ac_dir/nm -p /dev/null 2>&1 | sed '1q'; exit 0) | egrep /dev/null >/dev/null; then + NM="$ac_dir/nm -p" + break + else + NM=${NM="$ac_dir/nm"} # keep the first match, but + continue # so that we can try to find one that supports BSD flags + fi + fi + done + IFS="$ac_save_ifs" + test -z "$NM" && NM=nm + ;; + esac + echo "$ac_t$NM" 1>&6 +fi + +# Check for command to grab the raw symbol name followed by C symbol from nm. +echo $ac_n "checking command to parse $NM output... $ac_c" 1>&6 + +# These are sane defaults that work on at least a few old systems. +# [They come from Ultrix. What could be older than Ultrix?!! ;)] + +# Character class describing NM global symbol codes. +symcode='[BCDEGRST]' + +# Regexp to match symbols that can be accessed directly from C. +sympat='\([_A-Za-z][_A-Za-z0-9]*\)' + +# Transform the above into a raw symbol and a C symbol. +symxfrm='\1 \2\3 \3' + +# Transform an extracted symbol line into a proper C declaration +global_symbol_to_cdecl="sed -n -e 's/^. .* \(.*\)$/extern char \1;/p'" + +# Define system-specific variables. +case "$host_os" in +aix*) + symcode='[BCDT]' + ;; +cygwin* | mingw*) + symcode='[ABCDGISTW]' + ;; +hpux*) # Its linker distinguishes data from code symbols + global_symbol_to_cdecl="sed -n -e 's/^T .* \(.*\)$/extern char \1();/p' -e 's/^. .* \(.*\)$/extern char \1;/p'" + ;; +irix*) + symcode='[BCDEGRST]' + ;; +solaris*) + symcode='[BDT]' + ;; +sysv4) + symcode='[DFNSTU]' + ;; +esac + +# If we're using GNU nm, then use its standard symbol codes. +if $NM -V 2>&1 | egrep '(GNU|with BFD)' > /dev/null; then + symcode='[ABCDGISTW]' +fi + +# Try without a prefix undercore, then with it. +for ac_symprfx in "" "_"; do + + # Write the raw and C identifiers. + global_symbol_pipe="sed -n -e 's/^.*[ ]\($symcode\)[ ][ ]*\($ac_symprfx\)$sympat$/$symxfrm/p'" + + # Check to see that the pipe works correctly. + pipe_works=no + $rm conftest* + cat > conftest.c <<EOF +#ifdef __cplusplus +extern "C" { +#endif +char nm_test_var; +void nm_test_func(){} +#ifdef __cplusplus +} +#endif +main(){nm_test_var='a';nm_test_func();return(0);} +EOF + + echo "$progname:1653: checking if global_symbol_pipe works" >&5 + if { (eval echo $progname:1654: \"$ac_compile\") 1>&5; (eval $ac_compile) 2>&5; } && test -s conftest.$objext; then + # Now try to grab the symbols. + nlist=conftest.nm + if { echo "$progname:1657: eval \"$NM conftest.$objext | $global_symbol_pipe > $nlist\"" >&5; eval "$NM conftest.$objext | $global_symbol_pipe > $nlist 2>&5"; } && test -s "$nlist"; then + + # Try sorting and uniquifying the output. + if sort "$nlist" | uniq > "$nlist"T; then + mv -f "$nlist"T "$nlist" + else + rm -f "$nlist"T + fi + + # Make sure that we snagged all the symbols we need. + if egrep ' nm_test_var$' "$nlist" >/dev/null; then + if egrep ' nm_test_func$' "$nlist" >/dev/null; then + cat <<EOF > conftest.c +#ifdef __cplusplus +extern "C" { +#endif + +EOF + # Now generate the symbol file. + eval "$global_symbol_to_cdecl"' < "$nlist" >> conftest.c' + + cat <<EOF >> conftest.c +#if defined (__STDC__) && __STDC__ +# define lt_ptr_t void * +#else +# define lt_ptr_t char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr_t address; +} +lt_preloaded_symbols[] = +{ +EOF + sed 's/^. \(.*\) \(.*\)$/ {"\2", (lt_ptr_t) \&\2},/' < "$nlist" >> conftest.c + cat <<\EOF >> conftest.c + {0, (lt_ptr_t) 0} +}; + +#ifdef __cplusplus +} +#endif +EOF + # Now try linking the two files. + mv conftest.$objext conftstm.$objext + save_LIBS="$LIBS" + save_CFLAGS="$CFLAGS" + LIBS="conftstm.$objext" + CFLAGS="$CFLAGS$no_builtin_flag" + if { (eval echo $progname:1709: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest; then + pipe_works=yes + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + LIBS="$save_LIBS" + else + echo "cannot find nm_test_func in $nlist" >&5 + fi + else + echo "cannot find nm_test_var in $nlist" >&5 + fi + else + echo "cannot run $global_symbol_pipe" >&5 + fi + else + echo "$progname: failed program was:" >&5 + cat conftest.c >&5 + fi + $rm conftest* conftst* + + # Do not use the global_symbol_pipe unless it works. + if test "$pipe_works" = yes; then + break + else + global_symbol_pipe= + fi +done +if test "$pipe_works" = yes; then + echo "${ac_t}ok" 1>&6 +else + echo "${ac_t}failed" 1>&6 +fi + +if test -z "$global_symbol_pipe"; then + global_symbol_to_cdecl= +fi + +# Check hardcoding attributes. +echo $ac_n "checking how to hardcode library paths into programs... $ac_c" 1>&6 +hardcode_action= +if test -n "$hardcode_libdir_flag_spec" || \ + test -n "$runpath_var"; then + + # We can hardcode non-existant directories. + if test "$hardcode_direct" != no && + # If the only mechanism to avoid hardcoding is shlibpath_var, we + # have to relink, otherwise we might link with an installed library + # when we should be linking with a yet-to-be-installed one + ## test "$hardcode_shlibpath_var" != no && + test "$hardcode_minus_L" != no; then + # Linking always hardcodes the temporary library directory. + hardcode_action=relink + else + # We can link without hardcoding, and we can hardcode nonexisting dirs. + hardcode_action=immediate + fi +else + # We cannot hardcode anything, or else we can only hardcode existing + # directories. + hardcode_action=unsupported +fi +echo "$ac_t$hardcode_action" 1>&6 + + +reload_flag= +reload_cmds='$LD$reload_flag -o $output$reload_objs' +echo $ac_n "checking for $LD option to reload object files... $ac_c" 1>&6 +# PORTME Some linkers may need a different reload flag. +reload_flag='-r' +echo "$ac_t$reload_flag" 1>&6 +test -n "$reload_flag" && reload_flag=" $reload_flag" + +# PORTME Fill in your ld.so characteristics +library_names_spec= +libname_spec='lib$name' +soname_spec= +postinstall_cmds= +postuninstall_cmds= +finish_cmds= +finish_eval= +shlibpath_var= +shlibpath_overrides_runpath=unknown +version_type=none +dynamic_linker="$host_os ld.so" +sys_lib_dlsearch_path_spec="/lib /usr/lib" +sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" +file_magic_cmd= +file_magic_test_file= +deplibs_check_method='unknown' +# Need to set the preceding variable on all platforms that support +# interlibrary dependencies. +# 'none' -- dependencies not supported. +# `unknown' -- same as none, but documents that we really don't know. +# 'pass_all' -- all dependencies passed with no checks. +# 'test_compile' -- check by making test program. +# 'file_magic [regex]' -- check by looking for files in library path +# which responds to the $file_magic_cmd with a given egrep regex. +# If you have `file' or equivalent on your system and you're not sure +# whether `pass_all' will *always* work, you probably want this one. +echo $ac_n "checking dynamic linker characteristics... $ac_c" 1>&6 +case "$host_os" in +aix3*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix $libname.a' + shlibpath_var=LIBPATH + + # AIX has no versioning support, so we append a major version to the name. + soname_spec='${libname}${release}.so$major' + ;; + +aix4*) + version_type=linux + # AIX has no versioning support, so currently we can not hardcode correct + # soname into executable. Probably we can add versioning support to + # collect2, so additional links can be useful in future. + # We preserve .a as extension for shared libraries though AIX4.2 + # and later linker supports .so + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.a' + shlibpath_var=LIBPATH + deplibs_check_method=pass_all + ;; + +amigaos*) + library_names_spec='$libname.ixlibrary $libname.a' + # Create ${libname}_ixlibrary.a entries in /sys/libs. + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$echo "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $rm /sys/libs/${libname}_ixlibrary.a; $show "(cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a)"; (cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a) || exit 1; done' + ;; + +beos*) + library_names_spec='${libname}.so' + dynamic_linker="$host_os ld.so" + shlibpath_var=LIBRARY_PATH + deplibs_check_method=pass_all + lt_cv_dlopen="load_add_on" + lt_cv_dlopen_libs= + lt_cv_dlopen_self=yes + ;; + +bsdi4*) + version_type=linux + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib)' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + sys_lib_search_path_spec="/shlib /usr/lib /usr/X11/lib /usr/contrib/lib /lib /usr/local/lib" + sys_lib_dlsearch_path_spec="/shlib /usr/lib /usr/local/lib" + export_dynamic_flag_spec=-rdynamic + # the default ld.so.conf also contains /usr/contrib/lib and + # /usr/X11R6/lib (/usr/X11 is a link to /usr/X11R6), but let us allow + # libtool to hard-code these into programs + ;; + +cygwin* | mingw*) + version_type=windows + need_version=no + need_lib_prefix=no + if test "$with_gcc" = yes; then + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.a' + else + library_names_spec='${libname}`echo ${release} | sed -e 's/[.]/-/g'`${versuffix}.dll $libname.lib' + fi + dynamic_linker='Win32 ld.exe' + deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + file_magic_cmd='${OBJDUMP} -f' + # FIXME: first we should search . and the directory the executable is in + shlibpath_var=PATH + lt_cv_dlopen="LoadLibrary" + lt_cv_dlopen_libs= + ;; + +freebsd1*) + dynamic_linker=no + ;; + +freebsd*) + objformat=`test -x /usr/bin/objformat && /usr/bin/objformat || echo aout` + version_type=freebsd-$objformat + case "$version_type" in + freebsd-elf*) + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB shared object' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + need_version=no + need_lib_prefix=no + ;; + freebsd-*) + deplibs_check_method=unknown + library_names_spec='${libname}${release}.so$versuffix $libname.so$versuffix' + need_version=yes + ;; + esac + shlibpath_var=LD_LIBRARY_PATH + case "$host_os" in + freebsd2* | freebsd3.[01]* | freebsdelf3.[01]*) + shlibpath_overrides_runpath=yes + ;; + *) # from 3.2 on + shlibpath_overrides_runpath=no + ;; + esac + ;; + +gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so${major} ${libname}.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +hpux9* | hpux10* | hpux11*) + # Give a soname corresponding to the major version so that dld.sl refuses to + # link against other versions. + dynamic_linker="$host_os dld.sl" + version_type=sunos + need_lib_prefix=no + need_version=no + shlibpath_var=SHLIB_PATH + shlibpath_overrides_runpath=no # +s is required to enable SHLIB_PATH + library_names_spec='${libname}${release}.sl$versuffix ${libname}${release}.sl$major $libname.sl' + soname_spec='${libname}${release}.sl$major' + # HP-UX runs *really* slowly unless shared libraries are mode 555. + postinstall_cmds='chmod 555 $lib' + case "$host_os" in + hpux10.20*) + # TODO: Does this work for hpux-11 too? + deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/usr/lib/libc.sl + ;; + esac + ;; + +irix5* | irix6*) + version_type=irix + need_lib_prefix=no + need_version=no + soname_spec='${libname}${release}.so.$major' + library_names_spec='${libname}${release}.so.$versuffix ${libname}${release}.so.$major ${libname}${release}.so $libname.so' + case "$host_os" in + irix5*) + libsuff= shlibsuff= + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method="file_magic ELF 32-bit MSB dynamic lib MIPS - version 1" + ;; + *) + case "$LD" in # libtool.m4 will add one of these switches to LD + *-32|*"-32 ") libsuff= shlibsuff= libmagic=32-bit;; + *-n32|*"-n32 ") libsuff=32 shlibsuff=N32 libmagic=N32;; + *-64|*"-64 ") libsuff=64 shlibsuff=64 libmagic=64-bit;; + *) libsuff= shlibsuff= libmagic=never-match;; + esac + ;; + esac + shlibpath_var=LD_LIBRARY${shlibsuff}_PATH + shlibpath_overrides_runpath=no + sys_lib_search_path_spec="/usr/lib${libsuff} /lib${libsuff} /usr/local/lib${libsuff}" + sys_lib_dlsearch_path_spec="/usr/lib${libsuff} /lib${libsuff}" + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /lib${libsuff}/libc.so*` + deplibs_check_method='pass_all' + ;; + +# No shared lib support for Linux oldld, aout, or coff. +linux-gnuoldld* | linux-gnuaout* | linux-gnucoff*) + dynamic_linker=no + ;; + +# This must be Linux ELF. +linux-gnu*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=no + deplibs_check_method=pass_all + + if test -f /lib/ld.so.1; then + dynamic_linker='GNU ld.so' + else + # Only the GNU ld.so supports shared libraries on MkLinux. + case "$host_cpu" in + powerpc*) dynamic_linker=no ;; + *) dynamic_linker='Linux ld.so' ;; + esac + fi + ;; + +netbsd*) + version_type=sunos + if echo __ELF__ | $CC -E - | grep __ELF__ >/dev/null; then + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + dynamic_linker='NetBSD (a.out) ld.so' + else + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major ${libname}${release}.so ${libname}.so' + soname_spec='${libname}${release}.so$major' + dynamic_linker='NetBSD ld.elf_so' + fi + shlibpath_var=LD_LIBRARY_PATH + ;; + +openbsd*) + version_type=sunos + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + need_version=no + fi + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/sbin" ldconfig -m $libdir' + shlibpath_var=LD_LIBRARY_PATH + ;; + +os2*) + libname_spec='$name' + need_lib_prefix=no + library_names_spec='$libname.dll $libname.a' + dynamic_linker='OS/2 ld.exe' + shlibpath_var=LIBPATH + ;; + +osf3* | osf4* | osf5*) + version_type=osf + need_version=no + soname_spec='${libname}${release}.so' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so $libname.so' + shlibpath_var=LD_LIBRARY_PATH + # this will be overridden with pass_all, but let us keep it just in case + deplibs_check_method='file_magic COFF format alpha shared library' + file_magic_cmd=/usr/bin/file + file_magic_test_file=/shlib/libc.so + deplibs_check_method='pass_all' + sys_lib_search_path_spec="/usr/shlib /usr/ccs/lib /usr/lib/cmplrs/cc /usr/lib /usr/local/lib /var/shlib" + sys_lib_dlsearch_path_spec="$sys_lib_search_path_spec" + ;; + +rhapsody*) + version_type=sunos + library_names_spec='${libname}.so' + soname_spec='${libname}.so' + shlibpath_var=DYLD_LIBRARY_PATH + deplibs_check_method=pass_all + ;; + +sco3.2v5*) + version_type=osf + soname_spec='${libname}${release}.so$major' + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + shlibpath_var=LD_LIBRARY_PATH + ;; + +solaris*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + # ldd complains unless libraries are executable + postinstall_cmds='chmod +x $lib' + deplibs_check_method="file_magic ELF [0-9][0-9]-bit [LM]SB dynamic lib" + file_magic_cmd=/usr/bin/file + file_magic_test_file=/lib/libc.so + ;; + +sunos4*) + version_type=sunos + library_names_spec='${libname}${release}.so$versuffix ${libname}.so$versuffix' + finish_cmds='PATH="\$PATH:/usr/etc" ldconfig $libdir' + shlibpath_var=LD_LIBRARY_PATH + shlibpath_overrides_runpath=yes + if test "$with_gnu_ld" = yes; then + need_lib_prefix=no + fi + need_version=yes + ;; + +sysv4 | sysv4.2uw2* | sysv4.3* | sysv5*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + case "$host_vendor" in + sequent) + file_magic_cmd='/bin/file' + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [LM]SB (shared object|dynamic lib )' + ;; + ncr) + deplibs_check_method='pass_all' + ;; + motorola) + need_lib_prefix=no + need_version=no + shlibpath_overrides_runpath=no + sys_lib_search_path_spec='/lib /usr/lib /usr/ccs/lib' + deplibs_check_method='file_magic ELF [0-9][0-9]*-bit [ML]SB (shared object|dynamic lib) M[0-9][0-9]* Version [0-9]' + file_magic_cmd=/usr/bin/file + file_magic_test_file=`echo /usr/lib/libc.so*` + ;; + esac + ;; + +uts4*) + version_type=linux + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +dgux*) + version_type=linux + need_lib_prefix=no + need_version=no + library_names_spec='${libname}${release}.so$versuffix ${libname}${release}.so$major $libname.so' + soname_spec='${libname}${release}.so$major' + shlibpath_var=LD_LIBRARY_PATH + ;; + +sysv4*MP*) + if test -d /usr/nec ;then + version_type=linux + library_names_spec='$libname.so.$versuffix $libname.so.$major $libname.so' + soname_spec='$libname.so.$major' + shlibpath_var=LD_LIBRARY_PATH + fi + ;; + +*) + dynamic_linker=no + ;; +esac +echo "$ac_t$dynamic_linker" 1>&6 +test "$dynamic_linker" = no && can_build_shared=no + +# Report the final consequences. +echo "checking if libtool supports shared libraries... $can_build_shared" 1>&6 + +# Only try to build win32 dlls if AC_LIBTOOL_WIN32_DLL was used in +# configure.in, otherwise build static only libraries. +case "$host_os" in +cygwin* | mingw* | os2*) + if test x$can_build_shared = xyes; then + test x$enable_win32_dll = xno && can_build_shared=no + echo "checking if package supports dlls... $can_build_shared" 1>&6 + fi +;; +esac + +if test -n "$file_magic_test_file" && test -n "$file_magic_cmd"; then + case "$deplibs_check_method" in + "file_magic "*) + file_magic_regex="`expr \"$deplibs_check_method\" : \"file_magic \(.*\)\"`" + if eval $file_magic_cmd \$file_magic_test_file 2> /dev/null | + egrep "$file_magic_regex" > /dev/null; then + : + else + cat <<EOF 1>&2 + +*** Warning: the command libtool uses to detect shared libraries, +*** $file_magic_cmd, produces output that libtool cannot recognize. +*** The result is that libtool may fail to recognize shared libraries +*** as such. This will affect the creation of libtool libraries that +*** depend on shared libraries, but programs linked with such libtool +*** libraries will work regardless of this problem. Nevertheless, you +*** may want to report the problem to your system manager and/or to +*** bug-libtool@gnu.org + +EOF + fi ;; + esac +fi + +echo $ac_n "checking whether to build shared libraries... $ac_c" 1>&6 +test "$can_build_shared" = "no" && enable_shared=no + +# On AIX, shared libraries and static libraries use the same namespace, and +# are all built from PIC. +case "$host_os" in +aix3*) + test "$enable_shared" = yes && enable_static=no + if test -n "$RANLIB"; then + archive_cmds="$archive_cmds~\$RANLIB \$lib" + postinstall_cmds='$RANLIB $lib' + fi + ;; + +aix4*) + test "$enable_shared" = yes && enable_static=no + ;; +esac + +echo "$ac_t$enable_shared" 1>&6 + +# Make sure either enable_shared or enable_static is yes. +test "$enable_shared" = yes || enable_static=yes + +echo "checking whether to build static libraries... $enable_static" 1>&6 + +if test "$hardcode_action" = relink; then + # Fast installation is not supported + enable_fast_install=no +elif test "$shlibpath_overrides_runpath" = yes || + test "$enable_shared" = no; then + # Fast installation is not necessary + enable_fast_install=needless +fi + +echo $ac_n "checking for objdir... $ac_c" 1>&6 +rm -f .libs 2>/dev/null +mkdir .libs 2>/dev/null +if test -d .libs; then + objdir=.libs +else + # MS-DOS does not allow filenames that begin with a dot. + objdir=_libs +fi +rmdir .libs 2>/dev/null +echo "$ac_t$objdir" 1>&6 + +if test "x$enable_dlopen" != xyes; then + enable_dlopen=unknown + enable_dlopen_self=unknown + enable_dlopen_self_static=unknown +else +if eval "test \"`echo '$''{'lt_cv_dlopen'+set}'`\" != set"; then + lt_cv_dlopen=no lt_cv_dlopen_libs= +echo $ac_n "checking for dlopen in -ldl""... $ac_c" 1>&6 +echo "$progname:2248: checking for dlopen in -ldl" >&5 +ac_lib_var=`echo dl'_'dlopen | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldl $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2256 "ltconfig" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen(); + +int main() { +dlopen() +; return 0; } +EOF +if { (eval echo $progname:2269: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" lt_cv_dlopen_libs="-ldl" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dlopen""... $ac_c" 1>&6 +echo "$progname:2288: checking for dlopen" >&5 +if eval "test \"`echo '$''{'ac_cv_func_dlopen'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2293 "ltconfig" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char dlopen(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dlopen(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_dlopen) || defined (__stub___dlopen) +choke me +#else +dlopen(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2318: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_dlopen=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_dlopen=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_func_'dlopen`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dlopen" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for dld_link in -ldld""... $ac_c" 1>&6 +echo "$progname:2335: checking for dld_link in -ldld" >&5 +ac_lib_var=`echo dld'_'dld_link | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2343 "ltconfig" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char dld_link(); + +int main() { +dld_link() +; return 0; } +EOF +if { (eval echo $progname:2356: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="dld_link" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load""... $ac_c" 1>&6 +echo "$progname:2375: checking for shl_load" >&5 +if eval "test \"`echo '$''{'ac_cv_func_shl_load'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2380 "ltconfig" +/* System header to define __stub macros and hopefully few prototypes, + which can conflict with char shl_load(); below. */ +#include <assert.h> +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load(); + +int main() { + +/* The GNU C library defines this for functions which it implements + to always fail with ENOSYS. Some functions are actually named + something starting with __ and the normal name is an alias. */ +#if defined (__stub_shl_load) || defined (__stub___shl_load) +choke me +#else +shl_load(); +#endif + +; return 0; } +EOF +if { (eval echo $progname:2405: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_func_shl_load=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_func_shl_load=no" +fi +rm -f conftest* +fi + +if eval "test \"`echo '$ac_cv_func_'shl_load`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" +else + echo "$ac_t""no" 1>&6 +echo $ac_n "checking for shl_load in -ldld""... $ac_c" 1>&6 +echo "$progname:2423: checking for shl_load in -ldld" >&5 +ac_lib_var=`echo dld'_'shl_load | sed 'y%./+-%__p_%'` +if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + ac_save_LIBS="$LIBS" +LIBS="-ldld $LIBS" +cat > conftest.$ac_ext <<EOF +#line 2431 "ltconfig" +#include "confdefs.h" +/* Override any gcc2 internal prototype to avoid an error. */ +/* We use char because int might match the return type of a gcc2 + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char shl_load(); + +int main() { +shl_load() +; return 0; } +EOF +if { (eval echo $progname:2445: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=yes" +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_lib_$ac_lib_var=no" +fi +rm -f conftest* +LIBS="$ac_save_LIBS" + +fi +if eval "test \"`echo '$ac_cv_lib_'$ac_lib_var`\" = yes"; then + echo "$ac_t""yes" 1>&6 + lt_cv_dlopen="shl_load" lt_cv_dlopen_libs="-ldld" +else + echo "$ac_t""no" 1>&6 +fi + + +fi + + +fi + + +fi + + +fi + +fi + + if test "x$lt_cv_dlopen" != xno; then + enable_dlopen=yes + fi + + case "$lt_cv_dlopen" in + dlopen) +for ac_hdr in dlfcn.h; do +ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'` +echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6 +echo "$progname:2488: checking for $ac_hdr" >&5 +if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + cat > conftest.$ac_ext <<EOF +#line 2493 "ltconfig" +#include <$ac_hdr> +int fnord = 0; +EOF +ac_try="$ac_compile >/dev/null 2>conftest.out" +{ (eval echo $progname:2498: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; } +ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"` +if test -z "$ac_err"; then + rm -rf conftest* + eval "ac_cv_header_$ac_safe=yes" +else + echo "$ac_err" >&5 + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -rf conftest* + eval "ac_cv_header_$ac_safe=no" +fi +rm -f conftest* +fi +if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then + echo "$ac_t""yes" 1>&6 +else + echo "$ac_t""no" 1>&6 +fi +done + + if test "x$ac_cv_header_dlfcn_h" = xyes; then + CPPFLAGS="$CPPFLAGS -DHAVE_DLFCN_H" + fi + eval LDFLAGS=\"\$LDFLAGS $export_dynamic_flag_spec\" + LIBS="$lt_cv_dlopen_libs $LIBS" + + echo $ac_n "checking whether a program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2526: checking whether a program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self=cross + else + cat > conftest.c <<EOF +#line 2534 "ltconfig" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2580: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self" 1>&6 + + if test "$lt_cv_dlopen_self" = yes; then + LDFLAGS="$LDFLAGS $link_static_flag" + echo $ac_n "checking whether a statically linked program can dlopen itself""... $ac_c" 1>&6 +echo "$progname:2599: checking whether a statically linked program can dlopen itself" >&5 +if test "${lt_cv_dlopen_self_static+set}" = set; then + echo $ac_n "(cached) $ac_c" 1>&6 +else + if test "$cross_compiling" = yes; then + lt_cv_dlopen_self_static=cross + else + cat > conftest.c <<EOF +#line 2607 "ltconfig" + +#if HAVE_DLFCN_H +#include <dlfcn.h> +#endif + +#include <stdio.h> + +#ifdef RTLD_GLOBAL +# define LTDL_GLOBAL RTLD_GLOBAL +#else +# ifdef DL_GLOBAL +# define LTDL_GLOBAL DL_GLOBAL +# else +# define LTDL_GLOBAL 0 +# endif +#endif + +/* We may have to define LTDL_LAZY_OR_NOW in the command line if we + find out it does not work in some platform. */ +#ifndef LTDL_LAZY_OR_NOW +# ifdef RTLD_LAZY +# define LTDL_LAZY_OR_NOW RTLD_LAZY +# else +# ifdef DL_LAZY +# define LTDL_LAZY_OR_NOW DL_LAZY +# else +# ifdef RTLD_NOW +# define LTDL_LAZY_OR_NOW RTLD_NOW +# else +# ifdef DL_NOW +# define LTDL_LAZY_OR_NOW DL_NOW +# else +# define LTDL_LAZY_OR_NOW 0 +# endif +# endif +# endif +# endif +#endif + +fnord() { int i=42;} +main() { void *self, *ptr1, *ptr2; self=dlopen(0,LTDL_GLOBAL|LTDL_LAZY_OR_NOW); + if(self) { ptr1=dlsym(self,"fnord"); ptr2=dlsym(self,"_fnord"); + if(ptr1 || ptr2) { dlclose(self); exit(0); } } exit(1); } + +EOF +if { (eval echo $progname:2653: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest && (./conftest; exit) 2>/dev/null +then + lt_cv_dlopen_self_static=yes +else + echo "$progname: failed program was:" >&5 + cat conftest.$ac_ext >&5 + rm -fr conftest* + lt_cv_dlopen_self_static=no +fi +rm -fr conftest* +fi + +fi + +echo "$ac_t""$lt_cv_dlopen_self_static" 1>&6 +fi + ;; + esac + + case "$lt_cv_dlopen_self" in + yes|no) enable_dlopen_self=$lt_cv_dlopen_self ;; + *) enable_dlopen_self=unknown ;; + esac + + case "$lt_cv_dlopen_self_static" in + yes|no) enable_dlopen_self_static=$lt_cv_dlopen_self_static ;; + *) enable_dlopen_self_static=unknown ;; + esac +fi + +# Copy echo and quote the copy, instead of the original, because it is +# used later. +ltecho="$echo" +if test "X$ltecho" = "X$CONFIG_SHELL $0 --fallback-echo"; then + ltecho="$CONFIG_SHELL \$0 --fallback-echo" +fi +LTSHELL="$SHELL" + +LTCONFIG_VERSION="$VERSION" + +# Only quote variables if we're using ltmain.sh. +case "$ltmain" in +*.sh) + # Now quote all the things that may contain metacharacters. + for var in ltecho old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS \ + AR CC LD LN_S NM LTSHELL LTCONFIG_VERSION \ + reload_flag reload_cmds wl \ + pic_flag link_static_flag no_builtin_flag export_dynamic_flag_spec \ + thread_safe_flag_spec whole_archive_flag_spec libname_spec \ + library_names_spec soname_spec \ + RANLIB old_archive_cmds old_archive_from_new_cmds old_postinstall_cmds \ + old_postuninstall_cmds archive_cmds archive_expsym_cmds postinstall_cmds postuninstall_cmds \ + file_magic_cmd export_symbols_cmds deplibs_check_method allow_undefined_flag no_undefined_flag \ + finish_cmds finish_eval global_symbol_pipe global_symbol_to_cdecl \ + hardcode_libdir_flag_spec hardcode_libdir_separator \ + sys_lib_search_path_spec sys_lib_dlsearch_path_spec \ + compiler_c_o compiler_o_lo need_locks exclude_expsyms include_expsyms; do + + case "$var" in + reload_cmds | old_archive_cmds | old_archive_from_new_cmds | \ + old_postinstall_cmds | old_postuninstall_cmds | \ + export_symbols_cmds | archive_cmds | archive_expsym_cmds | \ + postinstall_cmds | postuninstall_cmds | \ + finish_cmds | sys_lib_search_path_spec | sys_lib_dlsearch_path_spec) + # Double-quote double-evaled strings. + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$double_quote_subst\" -e \"\$sed_quote_subst\" -e \"\$delay_variable_subst\"\`\\\"" + ;; + *) + eval "$var=\\\"\`\$echo \"X\$$var\" | \$Xsed -e \"\$sed_quote_subst\"\`\\\"" + ;; + esac + done + + case "$ltecho" in + *'\$0 --fallback-echo"') + ltecho=`$echo "X$ltecho" | $Xsed -e 's/\\\\\\\$0 --fallback-echo"$/$0 --fallback-echo"/'` + ;; + esac + + trap "$rm \"$ofile\"; exit 1" 1 2 15 + echo "creating $ofile" + $rm "$ofile" + cat <<EOF > "$ofile" +#! $SHELL + +# `$echo "$ofile" | sed 's%^.*/%%'` - Provide generalized library-building support services. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +# NOTE: Changes made to this file will be lost: look at ltconfig or ltmain.sh. +# +# Copyright (C) 1996-1999 Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Sed that helps us avoid accidentally triggering echo(1) options like -n. +Xsed="sed -e s/^X//" + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test "X\${CDPATH+set}" = Xset; then CDPATH=:; export CDPATH; fi + +### BEGIN LIBTOOL CONFIG +EOF + cfgfile="$ofile" + ;; + +*) + # Double-quote the variables that need it (for aesthetics). + for var in old_CC old_CFLAGS old_CPPFLAGS \ + old_LD old_LDFLAGS old_LIBS \ + old_NM old_RANLIB old_LN_S old_DLLTOOL old_OBJDUMP old_AS; do + eval "$var=\\\"\$var\\\"" + done + + # Just create a config file. + cfgfile="$ofile.cfg" + trap "$rm \"$cfgfile\"; exit 1" 1 2 15 + echo "creating $cfgfile" + $rm "$cfgfile" + cat <<EOF > "$cfgfile" +# `$echo "$cfgfile" | sed 's%^.*/%%'` - Libtool configuration file. +# Generated automatically by $PROGRAM (GNU $PACKAGE $VERSION$TIMESTAMP) +EOF + ;; +esac + +cat <<EOF >> "$cfgfile" +# Libtool was configured as follows, on host `(hostname || uname -n) 2>/dev/null | sed 1q`: +# +# CC=$old_CC CFLAGS=$old_CFLAGS CPPFLAGS=$old_CPPFLAGS \\ +# LD=$old_LD LDFLAGS=$old_LDFLAGS LIBS=$old_LIBS \\ +# NM=$old_NM RANLIB=$old_RANLIB LN_S=$old_LN_S \\ +# DLLTOOL=$old_DLLTOOL OBJDUMP=$old_OBJDUMP AS=$old_AS \\ +# $0$ltconfig_args +# +# Compiler and other test output produced by $progname, useful for +# debugging $progname, is in ./config.log if it exists. + +# The version of $progname that generated this script. +LTCONFIG_VERSION=$LTCONFIG_VERSION + +# Shell to use when invoking shell scripts. +SHELL=$LTSHELL + +# Whether or not to build shared libraries. +build_libtool_libs=$enable_shared + +# Whether or not to build static libraries. +build_old_libs=$enable_static + +# Whether or not to optimize for fast installation. +fast_install=$enable_fast_install + +# The host system. +host_alias=$host_alias +host=$host + +# An echo program that does not interpret backslashes. +echo=$ltecho + +# The archiver. +AR=$AR + +# The default C compiler. +CC=$CC + +# The linker used to build libraries. +LD=$LD + +# Whether we need hard or soft links. +LN_S=$LN_S + +# A BSD-compatible nm program. +NM=$NM + +# Used on cygwin: DLL creation program. +DLLTOOL="$DLLTOOL" + +# Used on cygwin: object dumper. +OBJDUMP="$OBJDUMP" + +# Used on cygwin: assembler. +AS="$AS" + +# The name of the directory that contains temporary libtool files. +objdir=$objdir + +# How to create reloadable object files. +reload_flag=$reload_flag +reload_cmds=$reload_cmds + +# How to pass a linker flag through the compiler. +wl=$wl + +# Object file suffix (normally "o"). +objext="$objext" + +# Old archive suffix (normally "a"). +libext="$libext" + +# Executable file suffix (normally ""). +exeext="$exeext" + +# Additional compiler flags for building library objects. +pic_flag=$pic_flag + +# Does compiler simultaneously support -c and -o options? +compiler_c_o=$compiler_c_o + +# Can we write directly to a .lo ? +compiler_o_lo=$compiler_o_lo + +# Must we lock files when doing compilation ? +need_locks=$need_locks + +# Do we need the lib prefix for modules? +need_lib_prefix=$need_lib_prefix + +# Do we need a version for libraries? +need_version=$need_version + +# Whether dlopen is supported. +dlopen=$enable_dlopen + +# Whether dlopen of programs is supported. +dlopen_self=$enable_dlopen_self + +# Whether dlopen of statically linked programs is supported. +dlopen_self_static=$enable_dlopen_self_static + +# Compiler flag to prevent dynamic linking. +link_static_flag=$link_static_flag + +# Compiler flag to turn off builtin functions. +no_builtin_flag=$no_builtin_flag + +# Compiler flag to allow reflexive dlopens. +export_dynamic_flag_spec=$export_dynamic_flag_spec + +# Compiler flag to generate shared objects directly from archives. +whole_archive_flag_spec=$whole_archive_flag_spec + +# Compiler flag to generate thread-safe objects. +thread_safe_flag_spec=$thread_safe_flag_spec + +# Library versioning type. +version_type=$version_type + +# Format of library name prefix. +libname_spec=$libname_spec + +# List of archive names. First name is the real one, the rest are links. +# The last name is the one that the linker finds with -lNAME. +library_names_spec=$library_names_spec + +# The coded name of the library, if different from the real name. +soname_spec=$soname_spec + +# Commands used to build and install an old-style archive. +RANLIB=$RANLIB +old_archive_cmds=$old_archive_cmds +old_postinstall_cmds=$old_postinstall_cmds +old_postuninstall_cmds=$old_postuninstall_cmds + +# Create an old-style archive from a shared archive. +old_archive_from_new_cmds=$old_archive_from_new_cmds + +# Commands used to build and install a shared archive. +archive_cmds=$archive_cmds +archive_expsym_cmds=$archive_expsym_cmds +postinstall_cmds=$postinstall_cmds +postuninstall_cmds=$postuninstall_cmds + +# Method to check whether dependent libraries are shared objects. +deplibs_check_method=$deplibs_check_method + +# Command to use when deplibs_check_method == file_magic. +file_magic_cmd=$file_magic_cmd + +# Flag that allows shared libraries with undefined symbols to be built. +allow_undefined_flag=$allow_undefined_flag + +# Flag that forces no undefined symbols. +no_undefined_flag=$no_undefined_flag + +# Commands used to finish a libtool library installation in a directory. +finish_cmds=$finish_cmds + +# Same as above, but a single script fragment to be evaled but not shown. +finish_eval=$finish_eval + +# Take the output of nm and produce a listing of raw symbols and C names. +global_symbol_pipe=$global_symbol_pipe + +# Transform the output of nm in a proper C declaration +global_symbol_to_cdecl=$global_symbol_to_cdecl + +# This is the shared library runtime path variable. +runpath_var=$runpath_var + +# This is the shared library path variable. +shlibpath_var=$shlibpath_var + +# Is shlibpath searched before the hard-coded library search path? +shlibpath_overrides_runpath=$shlibpath_overrides_runpath + +# How to hardcode a shared library path into an executable. +hardcode_action=$hardcode_action + +# Flag to hardcode \$libdir into a binary during linking. +# This must work even if \$libdir does not exist. +hardcode_libdir_flag_spec=$hardcode_libdir_flag_spec + +# Whether we need a single -rpath flag with a separated argument. +hardcode_libdir_separator=$hardcode_libdir_separator + +# Set to yes if using DIR/libNAME.so during linking hardcodes DIR into the +# resulting binary. +hardcode_direct=$hardcode_direct + +# Set to yes if using the -LDIR flag during linking hardcodes DIR into the +# resulting binary. +hardcode_minus_L=$hardcode_minus_L + +# Set to yes if using SHLIBPATH_VAR=DIR during linking hardcodes DIR into +# the resulting binary. +hardcode_shlibpath_var=$hardcode_shlibpath_var + +# Compile-time system search path for libraries +sys_lib_search_path_spec=$sys_lib_search_path_spec + +# Run-time system search path for libraries +sys_lib_dlsearch_path_spec=$sys_lib_dlsearch_path_spec + +# Fix the shell variable \$srcfile for the compiler. +fix_srcfile_path="$fix_srcfile_path" + +# Set to yes if exported symbols are required. +always_export_symbols=$always_export_symbols + +# The commands to list exported symbols. +export_symbols_cmds=$export_symbols_cmds + +# Symbols that should not be listed in the preloaded symbols. +exclude_expsyms=$exclude_expsyms + +# Symbols that must always be exported. +include_expsyms=$include_expsyms + +EOF + +case "$ltmain" in +*.sh) + echo '### END LIBTOOL CONFIG' >> "$ofile" + echo >> "$ofile" + case "$host_os" in + aix3*) + cat <<\EOF >> "$ofile" + +# AIX sometimes has problems with the GCC collect2 program. For some +# reason, if we set the COLLECT_NAMES environment variable, the problems +# vanish in a puff of smoke. +if test "X${COLLECT_NAMES+set}" != Xset; then + COLLECT_NAMES= + export COLLECT_NAMES +fi +EOF + ;; + esac + + # Append the ltmain.sh script. + sed '$q' "$ltmain" >> "$ofile" || (rm -f "$ofile"; exit 1) + # We use sed instead of cat because bash on DJGPP gets confused if + # if finds mixed CR/LF and LF-only lines. Since sed operates in + # text mode, it properly converts lines to CR/LF. This bash problem + # is reportedly fixed, but why not run on old versions too? + + chmod +x "$ofile" + ;; + +*) + # Compile the libtool program. + echo "FIXME: would compile $ltmain" + ;; +esac + +test -n "$cache_file" || exit 0 + +# AC_CACHE_SAVE +trap '' 1 2 15 +cat > confcache <<\EOF +# This file is a shell script that caches the results of configure +# tests run on this system so they can be shared between configure +# scripts and configure runs. It is not useful on other systems. +# If it contains results you don't want to keep, you may remove or edit it. +# +# By default, configure uses ./config.cache as the cache file, +# creating it if it does not exist already. You can give configure +# the --cache-file=FILE option to use a different cache file; that is +# what configure does when it calls configure scripts in +# subdirectories, so they share the cache. +# Giving --cache-file=/dev/null disables caching, for debugging configure. +# config.status only pays attention to the cache file if you give it the +# --recheck option to rerun configure. +# +EOF +# The following way of writing the cache mishandles newlines in values, +# but we know of no workaround that is simple, portable, and efficient. +# So, don't put newlines in cache variables' values. +# Ultrix sh set writes to stderr and can't be redirected directly, +# and sets the high bit in the cache file unless we assign to the vars. +(set) 2>&1 | + case `(ac_space=' '; set | grep ac_space) 2>&1` in + *ac_space=\ *) + # `set' does not quote correctly, so add quotes (double-quote substitution + # turns \\\\ into \\, and sed turns \\ into \). + sed -n \ + -e "s/'/'\\\\''/g" \ + -e "s/^\\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\\)=\\(.*\\)/\\1=\${\\1='\\2'}/p" + ;; + *) + # `set' quotes correctly as required by POSIX, so do not add quotes. + sed -n -e 's/^\([a-zA-Z0-9_]*_cv_[a-zA-Z0-9_]*\)=\(.*\)/\1=${\1=\2}/p' + ;; + esac >> confcache +if cmp -s $cache_file confcache; then + : +else + if test -w $cache_file; then + echo "updating cache $cache_file" + cat confcache > $cache_file + else + echo "not updating unwritable cache $cache_file" + fi +fi +rm -f confcache + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/trunk/ltmain.sh b/trunk/ltmain.sh new file mode 100644 index 0000000..c8c38c2 --- /dev/null +++ b/trunk/ltmain.sh @@ -0,0 +1,5064 @@ +# ltmain.sh - Provide generalized library-building support services. +# NOTE: Changing this file will not affect anything until you rerun configure. +# +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001 +# Free Software Foundation, Inc. +# Originally by Gordon Matzigkeit <gord@gnu.ai.mit.edu>, 1996 +# +# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +# +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +# Check that we have a working $echo. +if test "X$1" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift +elif test "X$1" = X--fallback-echo; then + # Avoid inline document here, it may be left over + : +elif test "X`($echo '\t') 2>/dev/null`" = 'X\t'; then + # Yippee, $echo works! + : +else + # Restart under the correct shell, and then maybe $echo will work. + exec $SHELL "$0" --no-reexec ${1+"$@"} +fi + +if test "X$1" = X--fallback-echo; then + # used as fallback echo + shift + cat <<EOF +$* +EOF + exit 0 +fi + +# The name of this program. +progname=`$echo "$0" | sed 's%^.*/%%'` +modename="$progname" + +# Constants. +PROGRAM=ltmain.sh +PACKAGE=libtool +VERSION=1.4.2 +TIMESTAMP=" (1.922.2.54 2001/09/11 03:33:37)" + +default_mode= +help="Try \`$progname --help' for more information." +magic="%%%MAGIC variable%%%" +mkdir="mkdir" +mv="mv -f" +rm="rm -f" + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='s/\([\\`\\"$\\\\]\)/\\\1/g' +SP2NL='tr \040 \012' +NL2SP='tr \015\012 \040\040' + +# NLS nuisances. +# Only set LANG and LC_ALL to C if already set. +# These must not be set unconditionally because not all systems understand +# e.g. LANG=C (notably SCO). +# We save the old values to restore during execute mode. +if test "${LC_ALL+set}" = set; then + save_LC_ALL="$LC_ALL"; LC_ALL=C; export LC_ALL +fi +if test "${LANG+set}" = set; then + save_LANG="$LANG"; LANG=C; export LANG +fi + +# Make sure IFS has a sensible default +: ${IFS=" "} + +if test "$build_libtool_libs" != yes && test "$build_old_libs" != yes; then + echo "$modename: not configured to build any kind of library" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 +fi + +# Global variables. +mode=$default_mode +nonopt= +prev= +prevopt= +run= +show="$echo" +show_help= +execute_dlfiles= +lo2o="s/\\.lo\$/.${objext}/" +o2lo="s/\\.${objext}\$/.lo/" + +# Parse our command line options once, thoroughly. +while test $# -gt 0 +do + arg="$1" + shift + + case $arg in + -*=*) optarg=`$echo "X$arg" | $Xsed -e 's/[-_a-zA-Z0-9]*=//'` ;; + *) optarg= ;; + esac + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + execute_dlfiles) + execute_dlfiles="$execute_dlfiles $arg" + ;; + *) + eval "$prev=\$arg" + ;; + esac + + prev= + prevopt= + continue + fi + + # Have we seen a non-optional argument yet? + case $arg in + --help) + show_help=yes + ;; + + --version) + echo "$PROGRAM (GNU $PACKAGE) $VERSION$TIMESTAMP" + exit 0 + ;; + + --config) + sed -e '1,/^# ### BEGIN LIBTOOL CONFIG/d' -e '/^# ### END LIBTOOL CONFIG/,$d' $0 + exit 0 + ;; + + --debug) + echo "$progname: enabling shell trace mode" + set -x + ;; + + --dry-run | -n) + run=: + ;; + + --features) + echo "host: $host" + if test "$build_libtool_libs" = yes; then + echo "enable shared libraries" + else + echo "disable shared libraries" + fi + if test "$build_old_libs" = yes; then + echo "enable static libraries" + else + echo "disable static libraries" + fi + exit 0 + ;; + + --finish) mode="finish" ;; + + --mode) prevopt="--mode" prev=mode ;; + --mode=*) mode="$optarg" ;; + + --preserve-dup-deps) duplicate_deps="yes" ;; + + --quiet | --silent) + show=: + ;; + + -dlopen) + prevopt="-dlopen" + prev=execute_dlfiles + ;; + + -*) + $echo "$modename: unrecognized option \`$arg'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + + *) + nonopt="$arg" + break + ;; + esac +done + +if test -n "$prevopt"; then + $echo "$modename: option \`$prevopt' requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 +fi + +# If this variable is set in any of the actions, the command in it +# will be execed at the end. This prevents here-documents from being +# left over by shells. +exec_cmd= + +if test -z "$show_help"; then + + # Infer the operation mode. + if test -z "$mode"; then + case $nonopt in + *cc | *++ | gcc* | *-gcc*) + mode=link + for arg + do + case $arg in + -c) + mode=compile + break + ;; + esac + done + ;; + *db | *dbx | *strace | *truss) + mode=execute + ;; + *install*|cp|mv) + mode=install + ;; + *rm) + mode=uninstall + ;; + *) + # If we have no mode, but dlfiles were specified, then do execute mode. + test -n "$execute_dlfiles" && mode=execute + + # Just use the default operation mode. + if test -z "$mode"; then + if test -n "$nonopt"; then + $echo "$modename: warning: cannot infer operation mode from \`$nonopt'" 1>&2 + else + $echo "$modename: warning: cannot infer operation mode without MODE-ARGS" 1>&2 + fi + fi + ;; + esac + fi + + # Only execute mode is allowed to have -dlopen flags. + if test -n "$execute_dlfiles" && test "$mode" != execute; then + $echo "$modename: unrecognized option \`-dlopen'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Change the help message to a mode-specific one. + generic_help="$help" + help="Try \`$modename --help --mode=$mode' for more information." + + # These modes are in order of execution frequency so that they run quickly. + case $mode in + # libtool compile mode + compile) + modename="$modename: compile" + # Get the compilation command and the source file. + base_compile= + prev= + lastarg= + srcfile="$nonopt" + suppress_output= + + user_target=no + for arg + do + case $prev in + "") ;; + xcompiler) + # Aesthetically quote the previous argument. + prev= + lastarg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + + case $arg in + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + # Accept any command-line options. + case $arg in + -o) + if test "$user_target" != "no"; then + $echo "$modename: you cannot specify \`-o' more than once" 1>&2 + exit 1 + fi + user_target=next + ;; + + -static) + build_old_libs=yes + continue + ;; + + -prefer-pic) + pic_mode=yes + continue + ;; + + -prefer-non-pic) + pic_mode=no + continue + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "s/^-Wc,//"` + lastarg= + save_ifs="$IFS"; IFS=',' + for arg in $args; do + IFS="$save_ifs" + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + lastarg="$lastarg $arg" + done + IFS="$save_ifs" + lastarg=`$echo "X$lastarg" | $Xsed -e "s/^ //"` + + # Add the arguments to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + continue + ;; + esac + + case $user_target in + next) + # The next one is the -o target name + user_target=yes + continue + ;; + yes) + # We got the output file + user_target=set + libobj="$arg" + continue + ;; + esac + + # Accept the current argument as the source file. + lastarg="$srcfile" + srcfile="$arg" + + # Aesthetically quote the previous argument. + + # Backslashify any backslashes, double quotes, and dollar signs. + # These are the only characters that are still specially + # interpreted inside of double-quoted scrings. + lastarg=`$echo "X$lastarg" | $Xsed -e "$sed_quote_subst"` + + # Double-quote args containing other shell metacharacters. + # Many Bourne shells cannot handle close brackets correctly + # in scan sets, so we specify it separately. + case $lastarg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + lastarg="\"$lastarg\"" + ;; + esac + + # Add the previous argument to base_compile. + if test -z "$base_compile"; then + base_compile="$lastarg" + else + base_compile="$base_compile $lastarg" + fi + done + + case $user_target in + set) + ;; + no) + # Get the name of the library object. + libobj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%'` + ;; + *) + $echo "$modename: you must specify a target with \`-o'" 1>&2 + exit 1 + ;; + esac + + # Recognize several different file suffixes. + # If the user specifies -o file.o, it is replaced with file.lo + xform='[cCFSfmso]' + case $libobj in + *.ada) xform=ada ;; + *.adb) xform=adb ;; + *.ads) xform=ads ;; + *.asm) xform=asm ;; + *.c++) xform=c++ ;; + *.cc) xform=cc ;; + *.cpp) xform=cpp ;; + *.cxx) xform=cxx ;; + *.f90) xform=f90 ;; + *.for) xform=for ;; + esac + + libobj=`$echo "X$libobj" | $Xsed -e "s/\.$xform$/.lo/"` + + case $libobj in + *.lo) obj=`$echo "X$libobj" | $Xsed -e "$lo2o"` ;; + *) + $echo "$modename: cannot determine name of library object from \`$libobj'" 1>&2 + exit 1 + ;; + esac + + if test -z "$base_compile"; then + $echo "$modename: you must specify a compilation command" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Delete any leftover library objects. + if test "$build_old_libs" = yes; then + removelist="$obj $libobj" + else + removelist="$libobj" + fi + + $run $rm $removelist + trap "$run $rm $removelist; exit 1" 1 2 15 + + # On Cygwin there's no "real" PIC flag so we must build both object types + case $host_os in + cygwin* | mingw* | pw32* | os2*) + pic_mode=default + ;; + esac + if test "$pic_mode" = no && test "$deplibs_check_method" != pass_all; then + # non-PIC code in shared libraries is not supported + pic_mode=default + fi + + # Calculate the filename of the output object if compiler does + # not support -o with -c + if test "$compiler_c_o" = no; then + output_obj=`$echo "X$srcfile" | $Xsed -e 's%^.*/%%' -e 's%\.[^.]*$%%'`.${objext} + lockfile="$output_obj.lock" + removelist="$removelist $output_obj $lockfile" + trap "$run $rm $removelist; exit 1" 1 2 15 + else + need_locks=no + lockfile= + fi + + # Lock this critical section if it is needed + # We use this script file to make the link, it avoids creating a new file + if test "$need_locks" = yes; then + until $run ln "$0" "$lockfile" 2>/dev/null; do + $show "Waiting for $lockfile to be removed" + sleep 2 + done + elif test "$need_locks" = warn; then + if test -f "$lockfile"; then + echo "\ +*** ERROR, $lockfile exists and contains: +`cat $lockfile 2>/dev/null` + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + echo $srcfile > "$lockfile" + fi + + if test -n "$fix_srcfile_path"; then + eval srcfile=\"$fix_srcfile_path\" + fi + + # Only build a PIC object if we are building libtool libraries. + if test "$build_libtool_libs" = yes; then + # Without this assignment, base_compile gets emptied. + fbsd_hideous_sh_bug=$base_compile + + if test "$pic_mode" != no; then + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + else + # Don't build PIC code + command="$base_compile $srcfile" + fi + if test "$build_old_libs" = yes; then + lo_libobj="$libobj" + dir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$libobj"; then + dir="$objdir" + else + dir="$dir/$objdir" + fi + libobj="$dir/"`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + + if test -d "$dir"; then + $show "$rm $libobj" + $run $rm $libobj + else + $show "$mkdir $dir" + $run $mkdir $dir + status=$? + if test $status -ne 0 && test ! -d $dir; then + exit $status + fi + fi + fi + if test "$compiler_o_lo" = yes; then + output_obj="$libobj" + command="$command -o $output_obj" + elif test "$compiler_c_o" = yes; then + output_obj="$obj" + command="$command -o $output_obj" + fi + + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + test -n "$output_obj" && $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed, then go on to compile the next one + if test x"$output_obj" != x"$libobj"; then + $show "$mv $output_obj $libobj" + if $run $mv $output_obj $libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # If we have no pic_flag, then copy the object into place and finish. + if (test -z "$pic_flag" || test "$pic_mode" != default) && + test "$build_old_libs" = yes; then + # Rename the .lo from within objdir to obj + if test -f $obj; then + $show $rm $obj + $run $rm $obj + fi + + $show "$mv $libobj $obj" + if $run $mv $libobj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e "s%.*/%%"` + libobj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + # Now arrange that obj and lo_libobj become the same file + $show "(cd $xdir && $LN_S $baseobj $libobj)" + if $run eval '(cd $xdir && $LN_S $baseobj $libobj)'; then + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + exit 0 + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Allow error messages only from the first compilation. + suppress_output=' >/dev/null 2>&1' + fi + + # Only build a position-dependent object if we build old libraries. + if test "$build_old_libs" = yes; then + if test "$pic_mode" != yes; then + # Don't build PIC code + command="$base_compile $srcfile" + else + # All platforms use -DPIC, to notify preprocessed assembler code. + command="$base_compile $srcfile $pic_flag -DPIC" + fi + if test "$compiler_c_o" = yes; then + command="$command -o $obj" + output_obj="$obj" + fi + + # Suppress compiler output if we already did a PIC compilation. + command="$command$suppress_output" + $run $rm "$output_obj" + $show "$command" + if $run eval "$command"; then : + else + $run $rm $removelist + exit 1 + fi + + if test "$need_locks" = warn && + test x"`cat $lockfile 2>/dev/null`" != x"$srcfile"; then + echo "\ +*** ERROR, $lockfile contains: +`cat $lockfile 2>/dev/null` + +but it should contain: +$srcfile + +This indicates that another process is trying to use the same +temporary object file, and libtool could not work around it because +your compiler does not support \`-c' and \`-o' together. If you +repeat this compilation, it may succeed, by chance, but you had better +avoid parallel builds (make -j) in this platform, or get a better +compiler." + + $run $rm $removelist + exit 1 + fi + + # Just move the object if needed + if test x"$output_obj" != x"$obj"; then + $show "$mv $output_obj $obj" + if $run $mv $output_obj $obj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + + # Create an invalid libtool object if no PIC, so that we do not + # accidentally link it into a program. + if test "$build_libtool_libs" != yes; then + $show "echo timestamp > $libobj" + $run eval "echo timestamp > \$libobj" || exit $? + else + # Move the .lo from within objdir + $show "$mv $libobj $lo_libobj" + if $run $mv $libobj $lo_libobj; then : + else + error=$? + $run $rm $removelist + exit $error + fi + fi + fi + + # Unlock the critical section if it was locked + if test "$need_locks" != no; then + $run $rm "$lockfile" + fi + + exit 0 + ;; + + # libtool link mode + link | relink) + modename="$modename: link" + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # It is impossible to link a dll without this setting, and + # we shouldn't force the makefile maintainer to figure out + # which system we are compiling for in order to pass an extra + # flag for every libtool invokation. + # allow_undefined=no + + # FIXME: Unfortunately, there are problems with the above when trying + # to make a dll which has undefined symbols, in which case not + # even a static library is built. For now, we need to specify + # -no-undefined on the libtool link line when we can be certain + # that all symbols are satisfied, otherwise we get a static library. + allow_undefined=yes + ;; + *) + allow_undefined=yes + ;; + esac + libtool_args="$nonopt" + compile_command="$nonopt" + finalize_command="$nonopt" + + compile_rpath= + finalize_rpath= + compile_shlibpath= + finalize_shlibpath= + convenience= + old_convenience= + deplibs= + old_deplibs= + compiler_flags= + linker_flags= + dllsearchpath= + lib_search_path=`pwd` + inst_prefix_dir= + + avoid_version=no + dlfiles= + dlprefiles= + dlself=no + export_dynamic=no + export_symbols= + export_symbols_regex= + generated= + libobjs= + ltlibs= + module=no + no_install=no + objs= + prefer_static_libs=no + preload=no + prev= + prevarg= + release= + rpath= + xrpath= + perm_rpath= + temp_rpath= + thread_safe=no + vinfo= + + # We need to know -static, to get the right output filenames. + for arg + do + case $arg in + -all-static | -static) + if test "X$arg" = "X-all-static"; then + if test "$build_libtool_libs" = yes && test -z "$link_static_flag"; then + $echo "$modename: warning: complete static linking is impossible in this configuration" 1>&2 + fi + if test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + else + if test -z "$pic_flag" && test -n "$link_static_flag"; then + dlopen_self=$dlopen_self_static + fi + fi + build_libtool_libs=no + build_old_libs=yes + prefer_static_libs=yes + break + ;; + esac + done + + # See if our shared archives depend on static archives. + test -n "$old_archive_from_new_cmds" && build_old_libs=yes + + # Go through the arguments, transforming them on the way. + while test $# -gt 0; do + arg="$1" + shift + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + qarg=\"`$echo "X$arg" | $Xsed -e "$sed_quote_subst"`\" ### testsuite: skip nested quoting test + ;; + *) qarg=$arg ;; + esac + libtool_args="$libtool_args $qarg" + + # If the previous option needs an argument, assign it. + if test -n "$prev"; then + case $prev in + output) + compile_command="$compile_command @OUTPUT@" + finalize_command="$finalize_command @OUTPUT@" + ;; + esac + + case $prev in + dlfiles|dlprefiles) + if test "$preload" = no; then + # Add the symbol object into the linking commands. + compile_command="$compile_command @SYMFILE@" + finalize_command="$finalize_command @SYMFILE@" + preload=yes + fi + case $arg in + *.la | *.lo) ;; # We handle these cases below. + force) + if test "$dlself" = no; then + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + self) + if test "$prev" = dlprefiles; then + dlself=yes + elif test "$prev" = dlfiles && test "$dlopen_self" != yes; then + dlself=yes + else + dlself=needless + export_dynamic=yes + fi + prev= + continue + ;; + *) + if test "$prev" = dlfiles; then + dlfiles="$dlfiles $arg" + else + dlprefiles="$dlprefiles $arg" + fi + prev= + continue + ;; + esac + ;; + expsyms) + export_symbols="$arg" + if test ! -f "$arg"; then + $echo "$modename: symbol file \`$arg' does not exist" + exit 1 + fi + prev= + continue + ;; + expsyms_regex) + export_symbols_regex="$arg" + prev= + continue + ;; + inst_prefix) + inst_prefix_dir="$arg" + prev= + continue + ;; + release) + release="-$arg" + prev= + continue + ;; + rpath | xrpath) + # We need an absolute path. + case $arg in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + if test "$prev" = rpath; then + case "$rpath " in + *" $arg "*) ;; + *) rpath="$rpath $arg" ;; + esac + else + case "$xrpath " in + *" $arg "*) ;; + *) xrpath="$xrpath $arg" ;; + esac + fi + prev= + continue + ;; + xcompiler) + compiler_flags="$compiler_flags $qarg" + prev= + compile_command="$compile_command $qarg" + finalize_command="$finalize_command $qarg" + continue + ;; + xlinker) + linker_flags="$linker_flags $qarg" + compiler_flags="$compiler_flags $wl$qarg" + prev= + compile_command="$compile_command $wl$qarg" + finalize_command="$finalize_command $wl$qarg" + continue + ;; + *) + eval "$prev=\"\$arg\"" + prev= + continue + ;; + esac + fi # test -n $prev + + prevarg="$arg" + + case $arg in + -all-static) + if test -n "$link_static_flag"; then + compile_command="$compile_command $link_static_flag" + finalize_command="$finalize_command $link_static_flag" + fi + continue + ;; + + -allow-undefined) + # FIXME: remove this flag sometime in the future. + $echo "$modename: \`-allow-undefined' is deprecated because it is the default" 1>&2 + continue + ;; + + -avoid-version) + avoid_version=yes + continue + ;; + + -dlopen) + prev=dlfiles + continue + ;; + + -dlpreopen) + prev=dlprefiles + continue + ;; + + -export-dynamic) + export_dynamic=yes + continue + ;; + + -export-symbols | -export-symbols-regex) + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: more than one -exported-symbols argument is not allowed" + exit 1 + fi + if test "X$arg" = "X-export-symbols"; then + prev=expsyms + else + prev=expsyms_regex + fi + continue + ;; + + -inst-prefix-dir) + prev=inst_prefix + continue + ;; + + # The native IRIX linker understands -LANG:*, -LIST:* and -LNO:* + # so, if we see these flags be careful not to treat them like -L + -L[A-Z][A-Z]*:*) + case $with_gcc/$host in + no/*-*-irix*) + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + ;; + esac + continue + ;; + + -L*) + dir=`$echo "X$arg" | $Xsed -e 's/^-L//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: cannot determine absolute directory name of \`$dir'" 1>&2 + exit 1 + fi + dir="$absdir" + ;; + esac + case "$deplibs " in + *" -L$dir "*) ;; + *) + deplibs="$deplibs -L$dir" + lib_search_path="$lib_search_path $dir" + ;; + esac + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$dir:"*) ;; + *) dllsearchpath="$dllsearchpath:$dir";; + esac + ;; + esac + continue + ;; + + -l*) + if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then + case $host in + *-*-cygwin* | *-*-pw32* | *-*-beos*) + # These systems don't actually have a C or math library (as such) + continue + ;; + *-*-mingw* | *-*-os2*) + # These systems don't actually have a C library (as such) + test "X$arg" = "X-lc" && continue + ;; + *-*-openbsd*) + # Do not include libc due to us having libc/libc_r. + test "X$arg" = "X-lc" && continue + ;; + esac + elif test "X$arg" = "X-lc_r"; then + case $host in + *-*-openbsd*) + # Do not include libc_r directly, use -pthread flag. + continue + ;; + esac + fi + deplibs="$deplibs $arg" + continue + ;; + + -module) + module=yes + continue + ;; + + -no-fast-install) + fast_install=no + continue + ;; + + -no-install) + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + # The PATH hackery in wrapper scripts is required on Windows + # in order for the loader to find any dlls it needs. + $echo "$modename: warning: \`-no-install' is ignored for $host" 1>&2 + $echo "$modename: warning: assuming \`-no-fast-install' instead" 1>&2 + fast_install=no + ;; + *) no_install=yes ;; + esac + continue + ;; + + -no-undefined) + allow_undefined=no + continue + ;; + + -o) prev=output ;; + + -release) + prev=release + continue + ;; + + -rpath) + prev=rpath + continue + ;; + + -R) + prev=xrpath + continue + ;; + + -R*) + dir=`$echo "X$arg" | $Xsed -e 's/^-R//'` + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + $echo "$modename: only absolute run-paths are allowed" 1>&2 + exit 1 + ;; + esac + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + continue + ;; + + -static) + # The effects of -static are defined in a previous loop. + # We used to do the same as -all-static on platforms that + # didn't have a PIC flag, but the assumption that the effects + # would be equivalent was wrong. It would break on at least + # Digital Unix and AIX. + continue + ;; + + -thread-safe) + thread_safe=yes + continue + ;; + + -version-info) + prev=vinfo + continue + ;; + + -Wc,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wc,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Wl,*) + args=`$echo "X$arg" | $Xsed -e "$sed_quote_subst" -e 's/^-Wl,//'` + arg= + save_ifs="$IFS"; IFS=',' + for flag in $args; do + IFS="$save_ifs" + case $flag in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + flag="\"$flag\"" + ;; + esac + arg="$arg $wl$flag" + compiler_flags="$compiler_flags $wl$flag" + linker_flags="$linker_flags $flag" + done + IFS="$save_ifs" + arg=`$echo "X$arg" | $Xsed -e "s/^ //"` + ;; + + -Xcompiler) + prev=xcompiler + continue + ;; + + -Xlinker) + prev=xlinker + continue + ;; + + # Some other compiler flag. + -* | +*) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + + *.lo | *.$objext) + # A library or standard object. + if test "$prev" = dlfiles; then + # This file was specified with -dlopen. + if test "$build_libtool_libs" = yes && test "$dlopen_support" = yes; then + dlfiles="$dlfiles $arg" + prev= + continue + else + # If libtool objects are unsupported, then we need to preload. + prev=dlprefiles + fi + fi + + if test "$prev" = dlprefiles; then + # Preload the old-style object. + dlprefiles="$dlprefiles "`$echo "X$arg" | $Xsed -e "$lo2o"` + prev= + else + case $arg in + *.lo) libobjs="$libobjs $arg" ;; + *) objs="$objs $arg" ;; + esac + fi + ;; + + *.$libext) + # An archive. + deplibs="$deplibs $arg" + old_deplibs="$old_deplibs $arg" + continue + ;; + + *.la) + # A libtool-controlled library. + + if test "$prev" = dlfiles; then + # This library was specified with -dlopen. + dlfiles="$dlfiles $arg" + prev= + elif test "$prev" = dlprefiles; then + # The library was specified with -dlpreopen. + dlprefiles="$dlprefiles $arg" + prev= + else + deplibs="$deplibs $arg" + fi + continue + ;; + + # Some other compiler argument. + *) + # Unknown arguments in both finalize_command and compile_command need + # to be aesthetically quoted because they are evaled later. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*|"") + arg="\"$arg\"" + ;; + esac + ;; + esac # arg + + # Now actually substitute the argument into the commands. + if test -n "$arg"; then + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + done # argument parsing loop + + if test -n "$prev"; then + $echo "$modename: the \`$prevarg' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then + eval arg=\"$export_dynamic_flag_spec\" + compile_command="$compile_command $arg" + finalize_command="$finalize_command $arg" + fi + + # calculate the name of the file, without its directory + outputname=`$echo "X$output" | $Xsed -e 's%^.*/%%'` + libobjs_save="$libobjs" + + if test -n "$shlibpath_var"; then + # get the directories listed in $shlibpath_var + eval shlib_search_path=\`\$echo \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + else + shlib_search_path= + fi + eval sys_lib_search_path=\"$sys_lib_search_path_spec\" + eval sys_lib_dlsearch_path=\"$sys_lib_dlsearch_path_spec\" + + output_objdir=`$echo "X$output" | $Xsed -e 's%/[^/]*$%%'` + if test "X$output_objdir" = "X$output"; then + output_objdir="$objdir" + else + output_objdir="$output_objdir/$objdir" + fi + # Create the object directory. + if test ! -d "$output_objdir"; then + $show "$mkdir $output_objdir" + $run $mkdir $output_objdir + status=$? + if test "$status" -ne 0 && test ! -d "$output_objdir"; then + exit $status + fi + fi + + # Determine the type of output + case $output in + "") + $echo "$modename: you must specify an output file" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + *.$libext) linkmode=oldlib ;; + *.lo | *.$objext) linkmode=obj ;; + *.la) linkmode=lib ;; + *) linkmode=prog ;; # Anything else should be a program. + esac + + specialdeplibs= + libs= + # Find all interdependent deplibs by searching for libraries + # that are linked more than once (e.g. -la -lb -la) + for deplib in $deplibs; do + if test "X$duplicate_deps" = "Xyes" ; then + case "$libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + libs="$libs $deplib" + done + + if test "$linkmode" = lib; then + libs="$predeps $libs $compiler_lib_search_path $postdeps" + + # Compute libraries that are listed more than once in $predeps + # $postdeps and mark them as special (i.e., whose duplicates are + # not to be eliminated). + pre_post_deps= + if test "X$duplicate_deps" = "Xyes" ; then + for pre_post_dep in $predeps $postdeps; do + case "$pre_post_deps " in + *" $pre_post_dep "*) specialdeplibs="$specialdeplibs $pre_post_deps" ;; + esac + pre_post_deps="$pre_post_deps $pre_post_dep" + done + fi + pre_post_deps= + fi + + deplibs= + newdependency_libs= + newlib_search_path= + need_relink=no # whether we're linking any uninstalled libtool libraries + notinst_deplibs= # not-installed libtool libraries + notinst_path= # paths that contain not-installed libtool libraries + case $linkmode in + lib) + passes="conv link" + for file in $dlfiles $dlprefiles; do + case $file in + *.la) ;; + *) + $echo "$modename: libraries can \`-dlopen' only libtool libraries: $file" 1>&2 + exit 1 + ;; + esac + done + ;; + prog) + compile_deplibs= + finalize_deplibs= + alldeplibs=no + newdlfiles= + newdlprefiles= + passes="conv scan dlopen dlpreopen link" + ;; + *) passes="conv" + ;; + esac + for pass in $passes; do + if test "$linkmode" = prog; then + # Determine which files to process + case $pass in + dlopen) + libs="$dlfiles" + save_deplibs="$deplibs" # Collect dlpreopened libraries + deplibs= + ;; + dlpreopen) libs="$dlprefiles" ;; + link) libs="$deplibs %DEPLIBS% $dependency_libs" ;; + esac + fi + for deplib in $libs; do + lib= + found=no + case $deplib in + -l*) + if test "$linkmode" = oldlib && test "$linkmode" = obj; then + $echo "$modename: warning: \`-l' is ignored for archives/objects: $deplib" 1>&2 + continue + fi + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + name=`$echo "X$deplib" | $Xsed -e 's/^-l//'` + for searchdir in $newlib_search_path $lib_search_path $sys_lib_search_path $shlib_search_path; do + # Search the libtool library + lib="$searchdir/lib${name}.la" + if test -f "$lib"; then + found=yes + break + fi + done + if test "$found" != yes; then + # deplib doesn't seem to be a libtool library + if test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + deplibs="$deplib $deplibs" + test "$linkmode" = lib && newdependency_libs="$deplib $newdependency_libs" + fi + continue + fi + ;; # -l + -L*) + case $linkmode in + lib) + deplibs="$deplib $deplibs" + test "$pass" = conv && continue + newdependency_libs="$deplib $newdependency_libs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + ;; + prog) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + if test "$pass" = scan; then + deplibs="$deplib $deplibs" + newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'` + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + ;; + *) + $echo "$modename: warning: \`-L' is ignored for archives/objects: $deplib" 1>&2 + ;; + esac # linkmode + continue + ;; # -L + -R*) + if test "$pass" = link; then + dir=`$echo "X$deplib" | $Xsed -e 's/^-R//'` + # Make sure the xrpath contains only unique directories. + case "$xrpath " in + *" $dir "*) ;; + *) xrpath="$xrpath $dir" ;; + esac + fi + deplibs="$deplib $deplibs" + continue + ;; + *.la) lib="$deplib" ;; + *.$libext) + if test "$pass" = conv; then + deplibs="$deplib $deplibs" + continue + fi + case $linkmode in + lib) + if test "$deplibs_check_method" != pass_all; then + echo + echo "*** Warning: This library needs some functionality provided by $deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + else + echo + echo "*** Warning: Linking the shared library $output against the" + echo "*** static library $deplib is not portable!" + deplibs="$deplib $deplibs" + fi + continue + ;; + prog) + if test "$pass" != link; then + deplibs="$deplib $deplibs" + else + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + fi + continue + ;; + esac # linkmode + ;; # *.$libext + *.lo | *.$objext) + if test "$pass" = dlpreopen || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlopen support or we're linking statically, + # we need to preload. + newdlprefiles="$newdlprefiles $deplib" + compile_deplibs="$deplib $compile_deplibs" + finalize_deplibs="$deplib $finalize_deplibs" + else + newdlfiles="$newdlfiles $deplib" + fi + continue + ;; + %DEPLIBS%) + alldeplibs=yes + continue + ;; + esac # case $deplib + if test "$found" = yes || test -f "$lib"; then : + else + $echo "$modename: cannot find the library \`$lib'" 1>&2 + exit 1 + fi + + # Check to see that this really is a libtool archive. + if (sed -e '2q' $lib | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + + ladir=`$echo "X$lib" | $Xsed -e 's%/[^/]*$%%'` + test "X$ladir" = "X$lib" && ladir="." + + dlname= + dlopen= + dlpreopen= + libdir= + library_names= + old_library= + # If the library was installed with an old release of libtool, + # it will not redefine variable installed. + installed=yes + + # Read the .la file + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + + if test "$linkmode,$pass" = "lib,link" || + test "$linkmode,$pass" = "prog,scan" || + { test "$linkmode" = oldlib && test "$linkmode" = obj; }; then + # Add dl[pre]opened files of deplib + test -n "$dlopen" && dlfiles="$dlfiles $dlopen" + test -n "$dlpreopen" && dlprefiles="$dlprefiles $dlpreopen" + fi + + if test "$pass" = conv; then + # Only check for convenience libraries + deplibs="$lib $deplibs" + if test -z "$libdir"; then + if test -z "$old_library"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + # It is a libtool convenience library, so add in its objects. + convenience="$convenience $ladir/$objdir/$old_library" + old_convenience="$old_convenience $ladir/$objdir/$old_library" + tmp_libs= + for deplib in $dependency_libs; do + deplibs="$deplib $deplibs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + elif test "$linkmode" != prog && test "$linkmode" != lib; then + $echo "$modename: \`$lib' is not a convenience library" 1>&2 + exit 1 + fi + continue + fi # $pass = conv + + # Get the name of the library we link against. + linklib= + for l in $old_library $library_names; do + linklib="$l" + done + if test -z "$linklib"; then + $echo "$modename: cannot find name of link library for \`$lib'" 1>&2 + exit 1 + fi + + # This library was specified with -dlopen. + if test "$pass" = dlopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + if test -z "$dlname" || test "$dlopen_support" != yes || test "$build_libtool_libs" = no; then + # If there is no dlname, no dlopen support or we're linking + # statically, we need to preload. + dlprefiles="$dlprefiles $lib" + else + newdlfiles="$newdlfiles $lib" + fi + continue + fi # $pass = dlopen + + # We need an absolute path. + case $ladir in + [\\/]* | [A-Za-z]:[\\/]*) abs_ladir="$ladir" ;; + *) + abs_ladir=`cd "$ladir" && pwd` + if test -z "$abs_ladir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$ladir'" 1>&2 + $echo "$modename: passing it literally to the linker, although it might fail" 1>&2 + abs_ladir="$ladir" + fi + ;; + esac + laname=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + + # Find the relevant object directory and library name. + if test "X$installed" = Xyes; then + if test ! -f "$libdir/$linklib" && test -f "$abs_ladir/$linklib"; then + $echo "$modename: warning: library \`$lib' was moved." 1>&2 + dir="$ladir" + absdir="$abs_ladir" + libdir="$abs_ladir" + else + dir="$libdir" + absdir="$libdir" + fi + else + dir="$ladir/$objdir" + absdir="$abs_ladir/$objdir" + # Remove this search path later + notinst_path="$notinst_path $abs_ladir" + fi # $installed = yes + name=`$echo "X$laname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + + # This library was specified with -dlpreopen. + if test "$pass" = dlpreopen; then + if test -z "$libdir"; then + $echo "$modename: cannot -dlpreopen a convenience library: \`$lib'" 1>&2 + exit 1 + fi + # Prefer using a static library (so that no silly _DYNAMIC symbols + # are required to link). + if test -n "$old_library"; then + newdlprefiles="$newdlprefiles $dir/$old_library" + # Otherwise, use the dlname, so that lt_dlopen finds it. + elif test -n "$dlname"; then + newdlprefiles="$newdlprefiles $dir/$dlname" + else + newdlprefiles="$newdlprefiles $dir/$linklib" + fi + fi # $pass = dlpreopen + + if test -z "$libdir"; then + # Link the convenience library + if test "$linkmode" = lib; then + deplibs="$dir/$old_library $deplibs" + elif test "$linkmode,$pass" = "prog,link"; then + compile_deplibs="$dir/$old_library $compile_deplibs" + finalize_deplibs="$dir/$old_library $finalize_deplibs" + else + deplibs="$lib $deplibs" + fi + continue + fi + + if test "$linkmode" = prog && test "$pass" != link; then + newlib_search_path="$newlib_search_path $ladir" + deplibs="$lib $deplibs" + + linkalldeplibs=no + if test "$link_all_deplibs" != no || test -z "$library_names" || + test "$build_libtool_libs" = no; then + linkalldeplibs=yes + fi + + tmp_libs= + for deplib in $dependency_libs; do + case $deplib in + -L*) newlib_search_path="$newlib_search_path "`$echo "X$deplib" | $Xsed -e 's/^-L//'`;; ### testsuite: skip nested quoting test + esac + # Need to link against all dependency_libs? + if test "$linkalldeplibs" = yes; then + deplibs="$deplib $deplibs" + else + # Need to hardcode shared library paths + # or/and link against static libraries + newdependency_libs="$deplib $newdependency_libs" + fi + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done # for deplib + continue + fi # $linkmode = prog... + + link_static=no # Whether the deplib will be linked statically + if test -n "$library_names" && + { test "$prefer_static_libs" = no || test -z "$old_library"; }; then + # Link against this shared library + + if test "$linkmode,$pass" = "prog,link" || + { test "$linkmode" = lib && test "$hardcode_into_libs" = yes; }; then + # Hardcode the library path. + # Skip directories that are in the system default run-time + # search path. + case " $sys_lib_dlsearch_path " in + *" $absdir "*) ;; + *) + case "$compile_rpath " in + *" $absdir "*) ;; + *) compile_rpath="$compile_rpath $absdir" + esac + ;; + esac + case " $sys_lib_dlsearch_path " in + *" $libdir "*) ;; + *) + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" + esac + ;; + esac + if test "$linkmode" = prog; then + # We need to hardcode the library path + if test -n "$shlibpath_var"; then + # Make sure the rpath contains only unique directories. + case "$temp_rpath " in + *" $dir "*) ;; + *" $absdir "*) ;; + *) temp_rpath="$temp_rpath $dir" ;; + esac + fi + fi + fi # $linkmode,$pass = prog,link... + + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + if test "$installed" = no; then + notinst_deplibs="$notinst_deplibs $lib" + need_relink=yes + fi + + if test -n "$old_archive_from_expsyms_cmds"; then + # figure out the soname + set dummy $library_names + realname="$2" + shift; shift + libname=`eval \\$echo \"$libname_spec\"` + # use dlname if we got it. it's perfectly good, no? + if test -n "$dlname"; then + soname="$dlname" + elif test -n "$soname_spec"; then + # bleh windows + case $host in + *cygwin*) + major=`expr $current - $age` + versuffix="-$major" + ;; + esac + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + + # Make a new name for the extract_expsyms_cmds to use + soroot="$soname" + soname=`echo $soroot | sed -e 's/^.*\///'` + newlib="libimp-`echo $soname | sed 's/^lib//;s/\.dll$//'`.a" + + # If the library has no export list, then create one now + if test -f "$output_objdir/$soname-def"; then : + else + $show "extracting exported symbol list from \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$extract_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Create $newlib + if test -f "$output_objdir/$newlib"; then :; else + $show "generating import library for \`$soname'" + save_ifs="$IFS"; IFS='~' + eval cmds=\"$old_archive_from_expsyms_cmds\" + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + # make sure the library variables are pointing to the new library + dir=$output_objdir + linklib=$newlib + fi # test -n "$old_archive_from_expsyms_cmds" + + if test "$linkmode" = prog || test "$mode" != relink; then + add_shlibpath= + add_dir= + add= + lib_linked=yes + case $hardcode_action in + immediate | unsupported) + if test "$hardcode_direct" = no; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = no; then + case $host in + *-*-sunos*) add_shlibpath="$dir" ;; + esac + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = no; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + relink) + if test "$hardcode_direct" = yes; then + add="$dir/$linklib" + elif test "$hardcode_minus_L" = yes; then + add_dir="-L$dir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + add_shlibpath="$dir" + add="-l$name" + else + lib_linked=no + fi + ;; + *) lib_linked=no ;; + esac + + if test "$lib_linked" != yes; then + $echo "$modename: configuration error: unsupported hardcode properties" + exit 1 + fi + + if test -n "$add_shlibpath"; then + case :$compile_shlibpath: in + *":$add_shlibpath:"*) ;; + *) compile_shlibpath="$compile_shlibpath$add_shlibpath:" ;; + esac + fi + if test "$linkmode" = prog; then + test -n "$add_dir" && compile_deplibs="$add_dir $compile_deplibs" + test -n "$add" && compile_deplibs="$add $compile_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + if test "$hardcode_direct" != yes && \ + test "$hardcode_minus_L" != yes && \ + test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + fi + fi + fi + + if test "$linkmode" = prog || test "$mode" = relink; then + add_shlibpath= + add_dir= + add= + # Finalize command for both is simple: just hardcode it. + if test "$hardcode_direct" = yes; then + add="$libdir/$linklib" + elif test "$hardcode_minus_L" = yes; then + # Try looking first in the location we're being installed to. + add_dir= + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="-L$inst_prefix_dir$libdir" + ;; + esac + fi + add_dir="$add_dir -L$libdir" + add="-l$name" + elif test "$hardcode_shlibpath_var" = yes; then + case :$finalize_shlibpath: in + *":$libdir:"*) ;; + *) finalize_shlibpath="$finalize_shlibpath$libdir:" ;; + esac + add="-l$name" + else + # We cannot seem to hardcode it, guess we'll fake it. + # Try looking first in the location we're being installed to. + add_dir= + if test -n "$inst_prefix_dir"; then + case "$libdir" in + [\\/]*) + add_dir="-L$inst_prefix_dir$libdir" + ;; + esac + fi + add_dir="$add_dir -L$libdir" + add="-l$name" + fi + + if test "$linkmode" = prog; then + test -n "$add_dir" && finalize_deplibs="$add_dir $finalize_deplibs" + test -n "$add" && finalize_deplibs="$add $finalize_deplibs" + else + test -n "$add_dir" && deplibs="$add_dir $deplibs" + test -n "$add" && deplibs="$add $deplibs" + fi + fi + elif test "$linkmode" = prog; then + if test "$alldeplibs" = yes && + { test "$deplibs_check_method" = pass_all || + { test "$build_libtool_libs" = yes && + test -n "$library_names"; }; }; then + # We only need to search for static libraries + continue + fi + + # Try to link the static library + # Here we assume that one of hardcode_direct or hardcode_minus_L + # is not unsupported. This is valid on all known static and + # shared platforms. + if test "$hardcode_direct" != unsupported; then + test -n "$old_library" && linklib="$old_library" + compile_deplibs="$dir/$linklib $compile_deplibs" + finalize_deplibs="$dir/$linklib $finalize_deplibs" + else + compile_deplibs="-l$name -L$dir $compile_deplibs" + finalize_deplibs="-l$name -L$dir $finalize_deplibs" + fi + elif test "$build_libtool_libs" = yes; then + # Not a shared library + if test "$deplibs_check_method" != pass_all; then + # We're trying link a shared library against a static one + # but the system doesn't support it. + + # Just print a warning and add the library to dependency_libs so + # that the program can be linked against the static library. + echo + echo "*** Warning: This library needs some functionality provided by $lib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + if test "$module" = yes; then + echo "*** Therefore, libtool will create a static module, that should work " + echo "*** as long as the dlopening application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + else + convenience="$convenience $dir/$old_library" + old_convenience="$old_convenience $dir/$old_library" + deplibs="$dir/$old_library $deplibs" + link_static=yes + fi + fi # link shared/static library? + + if test "$linkmode" = lib; then + if test -n "$dependency_libs" && + { test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes || + test "$link_static" = yes; }; then + # Extract -R from dependency_libs + temp_deplibs= + for libdir in $dependency_libs; do + case $libdir in + -R*) temp_xrpath=`$echo "X$libdir" | $Xsed -e 's/^-R//'` + case " $xrpath " in + *" $temp_xrpath "*) ;; + *) xrpath="$xrpath $temp_xrpath";; + esac;; + *) temp_deplibs="$temp_deplibs $libdir";; + esac + done + dependency_libs="$temp_deplibs" + fi + + newlib_search_path="$newlib_search_path $absdir" + # Link against this library + test "$link_static" = no && newdependency_libs="$abs_ladir/$laname $newdependency_libs" + # ... and its dependency_libs + tmp_libs= + for deplib in $dependency_libs; do + newdependency_libs="$deplib $newdependency_libs" + if test "X$duplicate_deps" = "Xyes" ; then + case "$tmp_libs " in + *" $deplib "*) specialdeplibs="$specialdeplibs $deplib" ;; + esac + fi + tmp_libs="$tmp_libs $deplib" + done + + if test "$link_all_deplibs" != no; then + # Add the search paths of all dependency libraries + for deplib in $dependency_libs; do + case $deplib in + -L*) path="$deplib" ;; + *.la) + dir=`$echo "X$deplib" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$deplib" && dir="." + # We need an absolute path. + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) absdir="$dir" ;; + *) + absdir=`cd "$dir" && pwd` + if test -z "$absdir"; then + $echo "$modename: warning: cannot determine absolute directory name of \`$dir'" 1>&2 + absdir="$dir" + fi + ;; + esac + if grep "^installed=no" $deplib > /dev/null; then + path="-L$absdir/$objdir" + else + eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + if test "$absdir" != "$libdir"; then + $echo "$modename: warning: \`$deplib' seems to be moved" 1>&2 + fi + path="-L$absdir" + fi + ;; + *) continue ;; + esac + case " $deplibs " in + *" $path "*) ;; + *) deplibs="$deplibs $path" ;; + esac + done + fi # link_all_deplibs != no + fi # linkmode = lib + done # for deplib in $libs + if test "$pass" = dlpreopen; then + # Link the dlpreopened libraries before other libraries + for deplib in $save_deplibs; do + deplibs="$deplib $deplibs" + done + fi + if test "$pass" != dlopen; then + test "$pass" != scan && dependency_libs="$newdependency_libs" + if test "$pass" != conv; then + # Make sure lib_search_path contains only unique directories. + lib_search_path= + for dir in $newlib_search_path; do + case "$lib_search_path " in + *" $dir "*) ;; + *) lib_search_path="$lib_search_path $dir" ;; + esac + done + newlib_search_path= + fi + + if test "$linkmode,$pass" != "prog,link"; then + vars="deplibs" + else + vars="compile_deplibs finalize_deplibs" + fi + for var in $vars dependency_libs; do + # Add libraries to $var in reverse order + eval tmp_libs=\"\$$var\" + new_libs= + for deplib in $tmp_libs; do + case $deplib in + -L*) new_libs="$deplib $new_libs" ;; + *) + case " $specialdeplibs " in + *" $deplib "*) new_libs="$deplib $new_libs" ;; + *) + case " $new_libs " in + *" $deplib "*) ;; + *) new_libs="$deplib $new_libs" ;; + esac + ;; + esac + ;; + esac + done + tmp_libs= + for deplib in $new_libs; do + case $deplib in + -L*) + case " $tmp_libs " in + *" $deplib "*) ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + ;; + *) tmp_libs="$tmp_libs $deplib" ;; + esac + done + eval $var=\"$tmp_libs\" + done # for var + fi + if test "$pass" = "conv" && + { test "$linkmode" = "lib" || test "$linkmode" = "prog"; }; then + libs="$deplibs" # reset libs + deplibs= + fi + done # for pass + if test "$linkmode" = prog; then + dlfiles="$newdlfiles" + dlprefiles="$newdlprefiles" + fi + + case $linkmode in + oldlib) + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for archives" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for archives" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for archives" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for archives" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for archives" 1>&2 + fi + + if test -n "$export_symbols" || test -n "$export_symbols_regex"; then + $echo "$modename: warning: \`-export-symbols' is ignored for archives" 1>&2 + fi + + # Now set the variables for building old libraries. + build_libtool_libs=no + oldlibs="$output" + objs="$objs$old_deplibs" + ;; + + lib) + # Make sure we only generate libraries of the form `libNAME.la'. + case $outputname in + lib*) + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//' -e 's/^lib//'` + eval libname=\"$libname_spec\" + ;; + *) + if test "$module" = no; then + $echo "$modename: libtool library \`$output' must begin with \`lib'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + if test "$need_lib_prefix" != no; then + # Add the "lib" prefix for modules if required + name=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + eval libname=\"$libname_spec\" + else + libname=`$echo "X$outputname" | $Xsed -e 's/\.la$//'` + fi + ;; + esac + + if test -n "$objs"; then + if test "$deplibs_check_method" != pass_all; then + $echo "$modename: cannot build libtool library \`$output' from non-libtool objects on this host:$objs" 2>&1 + exit 1 + else + echo + echo "*** Warning: Linking the shared library $output against the non-libtool" + echo "*** objects $objs is not portable!" + libobjs="$libobjs $objs" + fi + fi + + if test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen self' is ignored for libtool libraries" 1>&2 + fi + + set dummy $rpath + if test "$#" -gt 2; then + $echo "$modename: warning: ignoring multiple \`-rpath's for a libtool library" 1>&2 + fi + install_libdir="$2" + + oldlibs= + if test -z "$rpath"; then + if test "$build_libtool_libs" = yes; then + # Building a libtool convenience library. + libext=al + oldlibs="$output_objdir/$libname.$libext $oldlibs" + build_libtool_libs=convenience + build_old_libs=yes + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for convenience libraries" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for convenience libraries" 1>&2 + fi + else + + # Parse the version information argument. + save_ifs="$IFS"; IFS=':' + set dummy $vinfo 0 0 0 + IFS="$save_ifs" + + if test -n "$8"; then + $echo "$modename: too many parameters to \`-version-info'" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + current="$2" + revision="$3" + age="$4" + + # Check that each of the things are valid numbers. + case $current in + [0-9]*) ;; + *) + $echo "$modename: CURRENT \`$current' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $revision in + [0-9]*) ;; + *) + $echo "$modename: REVISION \`$revision' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + case $age in + [0-9]*) ;; + *) + $echo "$modename: AGE \`$age' is not a nonnegative integer" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + ;; + esac + + if test "$age" -gt "$current"; then + $echo "$modename: AGE \`$age' is greater than the current interface number \`$current'" 1>&2 + $echo "$modename: \`$vinfo' is not valid version information" 1>&2 + exit 1 + fi + + # Calculate the version variables. + major= + versuffix= + verstring= + case $version_type in + none) ;; + + darwin) + # Like Linux, but with the current version available in + # verstring for coding it into the library header + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + # Darwin ld doesn't like 0 for these options... + minor_current=`expr $current + 1` + verstring="-compatibility_version $minor_current -current_version $minor_current.$revision" + ;; + + freebsd-aout) + major=".$current" + versuffix=".$current.$revision"; + ;; + + freebsd-elf) + major=".$current" + versuffix=".$current"; + ;; + + irix) + major=`expr $current - $age + 1` + verstring="sgi$major.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$revision + while test "$loop" -ne 0; do + iface=`expr $revision - $loop` + loop=`expr $loop - 1` + verstring="sgi$major.$iface:$verstring" + done + + # Before this point, $major must not contain `.'. + major=.$major + versuffix="$major.$revision" + ;; + + linux) + major=.`expr $current - $age` + versuffix="$major.$age.$revision" + ;; + + osf) + major=`expr $current - $age` + versuffix=".$current.$age.$revision" + verstring="$current.$age.$revision" + + # Add in all the interfaces that we are compatible with. + loop=$age + while test "$loop" -ne 0; do + iface=`expr $current - $loop` + loop=`expr $loop - 1` + verstring="$verstring:${iface}.0" + done + + # Make executables depend on our current version. + verstring="$verstring:${current}.0" + ;; + + sunos) + major=".$current" + versuffix=".$current.$revision" + ;; + + windows) + # Use '-' rather than '.', since we only want one + # extension on DOS 8.3 filesystems. + major=`expr $current - $age` + versuffix="-$major" + ;; + + *) + $echo "$modename: unknown library version type \`$version_type'" 1>&2 + echo "Fatal configuration error. See the $PACKAGE docs for more information." 1>&2 + exit 1 + ;; + esac + + # Clear the version info if we defaulted, and they specified a release. + if test -z "$vinfo" && test -n "$release"; then + major= + verstring="0.0" + case $version_type in + darwin) + # we can't check for "0.0" in archive_cmds due to quoting + # problems, so we reset it completely + verstring="" + ;; + *) + verstring="0.0" + ;; + esac + if test "$need_version" = no; then + versuffix= + else + versuffix=".0.0" + fi + fi + + # Remove version info from name if versioning should be avoided + if test "$avoid_version" = yes && test "$need_version" = no; then + major= + versuffix= + verstring="" + fi + + # Check to see if the archive will have undefined symbols. + if test "$allow_undefined" = yes; then + if test "$allow_undefined_flag" = unsupported; then + $echo "$modename: warning: undefined symbols not allowed in $host shared libraries" 1>&2 + build_libtool_libs=no + build_old_libs=yes + fi + else + # Don't allow undefined symbols. + allow_undefined_flag="$no_undefined_flag" + fi + fi + + if test "$mode" != relink; then + # Remove our outputs. + $show "${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.*" + $run ${rm}r $output_objdir/$outputname $output_objdir/$libname.* $output_objdir/${libname}${release}.* + fi + + # Now set the variables for building old libraries. + if test "$build_old_libs" = yes && test "$build_libtool_libs" != convenience ; then + oldlibs="$oldlibs $output_objdir/$libname.$libext" + + # Transform .lo files to .o files. + oldobjs="$objs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + fi + + # Eliminate all temporary directories. + for path in $notinst_path; do + lib_search_path=`echo "$lib_search_path " | sed -e 's% $path % %g'` + deplibs=`echo "$deplibs " | sed -e 's% -L$path % %g'` + dependency_libs=`echo "$dependency_libs " | sed -e 's% -L$path % %g'` + done + + if test -n "$xrpath"; then + # If the user specified any rpath flags, then add them. + temp_xrpath= + for libdir in $xrpath; do + temp_xrpath="$temp_xrpath -R$libdir" + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + if test "$hardcode_into_libs" != yes || test "$build_old_libs" = yes; then + dependency_libs="$temp_xrpath $dependency_libs" + fi + fi + + # Make sure dlfiles contains only unique files that won't be dlpreopened + old_dlfiles="$dlfiles" + dlfiles= + for lib in $old_dlfiles; do + case " $dlprefiles $dlfiles " in + *" $lib "*) ;; + *) dlfiles="$dlfiles $lib" ;; + esac + done + + # Make sure dlprefiles contains only unique files + old_dlprefiles="$dlprefiles" + dlprefiles= + for lib in $old_dlprefiles; do + case "$dlprefiles " in + *" $lib "*) ;; + *) dlprefiles="$dlprefiles $lib" ;; + esac + done + + if test "$build_libtool_libs" = yes; then + if test -n "$rpath"; then + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos*) + # these systems don't actually have a c library (as such)! + ;; + *-*-rhapsody* | *-*-darwin1.[012]) + # Rhapsody C library is in the System framework + deplibs="$deplibs -framework System" + ;; + *-*-netbsd*) + # Don't link with libc until the a.out ld.so is fixed. + ;; + *-*-openbsd*) + # Do not include libc due to us having libc/libc_r. + ;; + *) + # Add libc to deplibs on all other systems if necessary. + if test "$build_libtool_need_lc" = "yes"; then + deplibs="$deplibs -lc" + fi + ;; + esac + fi + + # Transform deplibs into only deplibs that can be linked in shared. + name_save=$name + libname_save=$libname + release_save=$release + versuffix_save=$versuffix + major_save=$major + # I'm not sure if I'm treating the release correctly. I think + # release should show up in the -l (ie -lgmp5) so we don't want to + # add it in twice. Is that correct? + release="" + versuffix="" + major="" + newdeplibs= + droppeddeps=no + case $deplibs_check_method in + pass_all) + # Don't check for shared/static. Everything works. + # This might be a little naive. We might want to check + # whether the library exists or not. But this is on + # osf3 & osf4 and I'm not really sure... Just + # implementing what was already the behaviour. + newdeplibs=$deplibs + ;; + test_compile) + # This code stresses the "libraries are programs" paradigm to its + # limits. Maybe even breaks it. We compile a program, linking it + # against the deplibs as a proxy for the library. Then we can check + # whether they linked in statically or dynamically with ldd. + $rm conftest.c + cat > conftest.c <<EOF + int main() { return 0; } +EOF + $rm conftest + $CC -o conftest conftest.c $deplibs + if test "$?" -eq 0 ; then + ldd_output=`ldd conftest` + for i in $deplibs; do + name="`expr $i : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + libname=`eval \\$echo \"$libname_spec\"` + deplib_matches=`eval \\$echo \"$library_names_spec\"` + set dummy $deplib_matches + deplib_match=$2 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $i." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + newdeplibs="$newdeplibs $i" + fi + done + else + # Error occured in the first compile. Let's try to salvage the situation: + # Compile a seperate program for each library. + for i in $deplibs; do + name="`expr $i : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + $rm conftest + $CC -o conftest conftest.c $i + # Did it work? + if test "$?" -eq 0 ; then + ldd_output=`ldd conftest` + libname=`eval \\$echo \"$libname_spec\"` + deplib_matches=`eval \\$echo \"$library_names_spec\"` + set dummy $deplib_matches + deplib_match=$2 + if test `expr "$ldd_output" : ".*$deplib_match"` -ne 0 ; then + newdeplibs="$newdeplibs $i" + else + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $i." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + droppeddeps=yes + echo + echo "*** Warning! Library $i is needed by this library but I was not able to" + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." + fi + else + newdeplibs="$newdeplibs $i" + fi + done + fi + ;; + file_magic*) + set dummy $deplibs_check_method + file_magic_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name="`expr $a_deplib : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + # Follow soft links. + if ls -lLd "$potent_lib" 2>/dev/null \ + | grep " -> " >/dev/null; then + continue + fi + # The statement above tries to avoid entering an + # endless loop below, in case of cyclic links. + # We might still enter an endless loop, since a link + # loop can be closed while we follow links, + # but so what? + potlib="$potent_lib" + while test -h "$potlib" 2>/dev/null; do + potliblink=`ls -ld $potlib | sed 's/.* -> //'` + case $potliblink in + [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; + *) potlib=`$echo "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + esac + done + if eval $file_magic_cmd \"\$potlib\" 2>/dev/null \ + | sed 10q \ + | egrep "$file_magic_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + match_pattern*) + set dummy $deplibs_check_method + match_pattern_regex=`expr "$deplibs_check_method" : "$2 \(.*\)"` + for a_deplib in $deplibs; do + name="`expr $a_deplib : '-l\(.*\)'`" + # If $name is empty we are operating on a -L argument. + if test -n "$name" && test "$name" != "0"; then + libname=`eval \\$echo \"$libname_spec\"` + for i in $lib_search_path $sys_lib_search_path $shlib_search_path; do + potential_libs=`ls $i/$libname[.-]* 2>/dev/null` + for potent_lib in $potential_libs; do + if eval echo \"$potent_lib\" 2>/dev/null \ + | sed 10q \ + | egrep "$match_pattern_regex" > /dev/null; then + newdeplibs="$newdeplibs $a_deplib" + a_deplib="" + break 2 + fi + done + done + if test -n "$a_deplib" ; then + droppeddeps=yes + echo + echo "*** Warning: This library needs some functionality provided by $a_deplib." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." + fi + else + # Add a -L argument. + newdeplibs="$newdeplibs $a_deplib" + fi + done # Gone through all deplibs. + ;; + none | unknown | *) + newdeplibs="" + if $echo "X $deplibs" | $Xsed -e 's/ -lc$//' \ + -e 's/ -[LR][^ ]*//g' -e 's/[ ]//g' | + grep . >/dev/null; then + echo + if test "X$deplibs_check_method" = "Xnone"; then + echo "*** Warning: inter-library dependencies are not supported in this platform." + else + echo "*** Warning: inter-library dependencies are not known to be supported." + fi + echo "*** All declared inter-library dependencies are being dropped." + droppeddeps=yes + fi + ;; + esac + versuffix=$versuffix_save + major=$major_save + release=$release_save + libname=$libname_save + name=$name_save + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + newdeplibs=`$echo "X $newdeplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + if test "$droppeddeps" = yes; then + if test "$module" = yes; then + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" + echo "*** dependencies of module $libname. Therefore, libtool will create" + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." + if test -z "$global_symbol_pipe"; then + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." + fi + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + else + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." + + if test "$allow_undefined" = no; then + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." + if test "$build_old_libs" = no; then + oldlibs="$output_objdir/$libname.$libext" + build_libtool_libs=module + build_old_libs=yes + else + build_libtool_libs=no + fi + fi + fi + fi + # Done checking deplibs! + deplibs=$newdeplibs + fi + + # All the library-specific variables (install_libdir is set above). + library_names= + old_library= + dlname= + + # Test again, we may have decided not to build it any more + if test "$build_libtool_libs" = yes; then + if test "$hardcode_into_libs" = yes; then + # Hardcode the library paths + hardcode_libdirs= + dep_rpath= + rpath="$finalize_rpath" + test "$mode" != relink && rpath="$compile_rpath$rpath" + for libdir in $rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + dep_rpath="$dep_rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval dep_rpath=\"$hardcode_libdir_flag_spec\" + fi + if test -n "$runpath_var" && test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + eval "$runpath_var='$rpath\$$runpath_var'; export $runpath_var" + fi + test -n "$dep_rpath" && deplibs="$dep_rpath $deplibs" + fi + + shlibpath="$finalize_shlibpath" + test "$mode" != relink && shlibpath="$compile_shlibpath$shlibpath" + if test -n "$shlibpath"; then + eval "$shlibpath_var='$shlibpath\$$shlibpath_var'; export $shlibpath_var" + fi + + # Get the real and link names of the library. + eval library_names=\"$library_names_spec\" + set dummy $library_names + realname="$2" + shift; shift + + if test -n "$soname_spec"; then + eval soname=\"$soname_spec\" + else + soname="$realname" + fi + test -z "$dlname" && dlname=$soname + + lib="$output_objdir/$realname" + for link + do + linknames="$linknames $link" + done + + # Ensure that we have .o objects for linkers which dislike .lo + # (e.g. aix) in case we are running --disable-static + for obj in $libobjs; do + xdir=`$echo "X$obj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$obj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$obj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + if test ! -f $xdir/$oldobj; then + $show "(cd $xdir && ${LN_S} $baseobj $oldobj)" + $run eval '(cd $xdir && ${LN_S} $baseobj $oldobj)' || exit $? + fi + done + + # Use standard objects if they are pic + test -z "$pic_flag" && libobjs=`$echo "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + if test "$always_export_symbols" = yes || test -n "$export_symbols_regex"; then + $show "generating symbol list for \`$libname.la'" + export_symbols="$output_objdir/$libname.exp" + $run $rm $export_symbols + eval cmds=\"$export_symbols_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + if test -n "$export_symbols_regex"; then + $show "egrep -e \"$export_symbols_regex\" \"$export_symbols\" > \"${export_symbols}T\"" + $run eval 'egrep -e "$export_symbols_regex" "$export_symbols" > "${export_symbols}T"' + $show "$mv \"${export_symbols}T\" \"$export_symbols\"" + $run eval '$mv "${export_symbols}T" "$export_symbols"' + fi + fi + fi + + if test -n "$export_symbols" && test -n "$include_expsyms"; then + $run eval '$echo "X$include_expsyms" | $SP2NL >> "$export_symbols"' + fi + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval libobjs=\"\$libobjs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + libobjs="$libobjs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + if test "$thread_safe" = yes && test -n "$thread_safe_flag_spec"; then + eval flag=\"$thread_safe_flag_spec\" + linker_flags="$linker_flags $flag" + fi + + # Make a backup of the uninstalled library when relinking + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}U && $mv $realname ${realname}U)' || exit $? + fi + + # Do each of the archive commands. + if test -n "$export_symbols" && test -n "$archive_expsym_cmds"; then + eval cmds=\"$archive_expsym_cmds\" + else + eval cmds=\"$archive_cmds\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Restore the uninstalled library and exit + if test "$mode" = relink; then + $run eval '(cd $output_objdir && $rm ${realname}T && $mv $realname ${realname}T && $mv "$realname"U $realname)' || exit $? + exit 0 + fi + + # Create links to the real library. + for linkname in $linknames; do + if test "$realname" != "$linkname"; then + $show "(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval '(cd $output_objdir && $rm $linkname && $LN_S $realname $linkname)' || exit $? + fi + done + + # If -module or -export-dynamic was specified, set the dlname. + if test "$module" = yes || test "$export_dynamic" = yes; then + # On all known operating systems, these are identical. + dlname="$soname" + fi + fi + ;; + + obj) + if test -n "$deplibs"; then + $echo "$modename: warning: \`-l' and \`-L' are ignored for objects" 1>&2 + fi + + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + $echo "$modename: warning: \`-dlopen' is ignored for objects" 1>&2 + fi + + if test -n "$rpath"; then + $echo "$modename: warning: \`-rpath' is ignored for objects" 1>&2 + fi + + if test -n "$xrpath"; then + $echo "$modename: warning: \`-R' is ignored for objects" 1>&2 + fi + + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for objects" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for objects" 1>&2 + fi + + case $output in + *.lo) + if test -n "$objs$old_deplibs"; then + $echo "$modename: cannot build library object \`$output' from non-libtool objects" 1>&2 + exit 1 + fi + libobj="$output" + obj=`$echo "X$output" | $Xsed -e "$lo2o"` + ;; + *) + libobj= + obj="$output" + ;; + esac + + # Delete the old objects. + $run $rm $obj $libobj + + # Objects from convenience libraries. This assumes + # single-version convenience libraries. Whenever we create + # different ones for PIC/non-PIC, this we'll have to duplicate + # the extraction. + reload_conv_objs= + gentop= + # reload_cmds runs $LD directly, so let us get rid of + # -Wl from whole_archive_flag_spec + wl= + + if test -n "$convenience"; then + if test -n "$whole_archive_flag_spec"; then + eval reload_conv_objs=\"\$reload_objs $whole_archive_flag_spec\" + else + gentop="$output_objdir/${obj}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + for xlib in $convenience; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + reload_conv_objs="$reload_objs "`find $xdir -name \*.o -print -o -name \*.lo -print | $NL2SP` + done + fi + fi + + # Create the old-style object. + reload_objs="$objs$old_deplibs "`$echo "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + + output="$obj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + + # Exit if we aren't doing a library object file. + if test -z "$libobj"; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + fi + + if test "$build_libtool_libs" != yes; then + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + # Create an invalid libtool object if no PIC, so that we don't + # accidentally link it into a program. + $show "echo timestamp > $libobj" + $run eval "echo timestamp > $libobj" || exit $? + exit 0 + fi + + if test -n "$pic_flag" || test "$pic_mode" != default; then + # Only do commands if we really have different PIC objects. + reload_objs="$libobjs $reload_conv_objs" + output="$libobj" + eval cmds=\"$reload_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + else + # Just create a symlink. + $show $rm $libobj + $run $rm $libobj + xdir=`$echo "X$libobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$libobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$libobj" | $Xsed -e 's%^.*/%%'` + oldobj=`$echo "X$baseobj" | $Xsed -e "$lo2o"` + $show "(cd $xdir && $LN_S $oldobj $baseobj)" + $run eval '(cd $xdir && $LN_S $oldobj $baseobj)' || exit $? + fi + + if test -n "$gentop"; then + $show "${rm}r $gentop" + $run ${rm}r $gentop + fi + + exit 0 + ;; + + prog) + case $host in + *cygwin*) output=`echo $output | sed -e 's,.exe$,,;s,$,.exe,'` ;; + esac + if test -n "$vinfo"; then + $echo "$modename: warning: \`-version-info' is ignored for programs" 1>&2 + fi + + if test -n "$release"; then + $echo "$modename: warning: \`-release' is ignored for programs" 1>&2 + fi + + if test "$preload" = yes; then + if test "$dlopen_support" = unknown && test "$dlopen_self" = unknown && + test "$dlopen_self_static" = unknown; then + $echo "$modename: warning: \`AC_LIBTOOL_DLOPEN' not used. Assuming no dlopen support." + fi + fi + + case $host in + *-*-rhapsody* | *-*-darwin1.[012]) + # On Rhapsody replace the C library is the System framework + compile_deplibs=`$echo "X $compile_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + finalize_deplibs=`$echo "X $finalize_deplibs" | $Xsed -e 's/ -lc / -framework System /'` + ;; + esac + + compile_command="$compile_command $compile_deplibs" + finalize_command="$finalize_command $finalize_deplibs" + + if test -n "$rpath$xrpath"; then + # If the user specified any rpath flags, then add them. + for libdir in $rpath $xrpath; do + # This is the magic to use -rpath. + case "$finalize_rpath " in + *" $libdir "*) ;; + *) finalize_rpath="$finalize_rpath $libdir" ;; + esac + done + fi + + # Now hardcode the library paths + rpath= + hardcode_libdirs= + for libdir in $compile_rpath $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$perm_rpath " in + *" $libdir "*) ;; + *) perm_rpath="$perm_rpath $libdir" ;; + esac + fi + case $host in + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2*) + case :$dllsearchpath: in + *":$libdir:"*) ;; + *) dllsearchpath="$dllsearchpath:$libdir";; + esac + ;; + esac + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + compile_rpath="$rpath" + + rpath= + hardcode_libdirs= + for libdir in $finalize_rpath; do + if test -n "$hardcode_libdir_flag_spec"; then + if test -n "$hardcode_libdir_separator"; then + if test -z "$hardcode_libdirs"; then + hardcode_libdirs="$libdir" + else + # Just accumulate the unique libdirs. + case $hardcode_libdir_separator$hardcode_libdirs$hardcode_libdir_separator in + *"$hardcode_libdir_separator$libdir$hardcode_libdir_separator"*) + ;; + *) + hardcode_libdirs="$hardcode_libdirs$hardcode_libdir_separator$libdir" + ;; + esac + fi + else + eval flag=\"$hardcode_libdir_flag_spec\" + rpath="$rpath $flag" + fi + elif test -n "$runpath_var"; then + case "$finalize_perm_rpath " in + *" $libdir "*) ;; + *) finalize_perm_rpath="$finalize_perm_rpath $libdir" ;; + esac + fi + done + # Substitute the hardcoded libdirs into the rpath. + if test -n "$hardcode_libdir_separator" && + test -n "$hardcode_libdirs"; then + libdir="$hardcode_libdirs" + eval rpath=\" $hardcode_libdir_flag_spec\" + fi + finalize_rpath="$rpath" + + if test -n "$libobjs" && test "$build_old_libs" = yes; then + # Transform all the library objects into standard objects. + compile_command=`$echo "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + finalize_command=`$echo "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + fi + + dlsyms= + if test -n "$dlfiles$dlprefiles" || test "$dlself" != no; then + if test -n "$NM" && test -n "$global_symbol_pipe"; then + dlsyms="${outputname}S.c" + else + $echo "$modename: not configured to extract global symbols from dlpreopened files" 1>&2 + fi + fi + + if test -n "$dlsyms"; then + case $dlsyms in + "") ;; + *.c) + # Discover the nlist of each of the dlfiles. + nlist="$output_objdir/${outputname}.nm" + + $show "$rm $nlist ${nlist}S ${nlist}T" + $run $rm "$nlist" "${nlist}S" "${nlist}T" + + # Parse the name list into a source file. + $show "creating $output_objdir/$dlsyms" + + test -z "$run" && $echo > "$output_objdir/$dlsyms" "\ +/* $dlsyms - symbol resolution table for \`$outputname' dlsym emulation. */ +/* Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP */ + +#ifdef __cplusplus +extern \"C\" { +#endif + +/* Prevent the only kind of declaration conflicts we can make. */ +#define lt_preloaded_symbols some_other_symbol + +/* External symbol declarations for the compiler. */\ +" + + if test "$dlself" = yes; then + $show "generating symbol list for \`$output'" + + test -z "$run" && $echo ': @PROGRAM@ ' > "$nlist" + + # Add our own program objects to the symbol list. + progfiles=`$echo "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + for arg in $progfiles; do + $show "extracting global C symbols from \`$arg'" + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -n "$exclude_expsyms"; then + $run eval 'egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + if test -n "$export_symbols_regex"; then + $run eval 'egrep -e "$export_symbols_regex" "$nlist" > "$nlist"T' + $run eval '$mv "$nlist"T "$nlist"' + fi + + # Prepare the list of exported symbols + if test -z "$export_symbols"; then + export_symbols="$output_objdir/$output.exp" + $run $rm $export_symbols + $run eval "sed -n -e '/^: @PROGRAM@$/d' -e 's/^.* \(.*\)$/\1/p' "'< "$nlist" > "$export_symbols"' + else + $run eval "sed -e 's/\([][.*^$]\)/\\\1/g' -e 's/^/ /' -e 's/$/$/'"' < "$export_symbols" > "$output_objdir/$output.exp"' + $run eval 'grep -f "$output_objdir/$output.exp" < "$nlist" > "$nlist"T' + $run eval 'mv "$nlist"T "$nlist"' + fi + fi + + for arg in $dlprefiles; do + $show "extracting global C symbols from \`$arg'" + name=`echo "$arg" | sed -e 's%^.*/%%'` + $run eval 'echo ": $name " >> "$nlist"' + $run eval "$NM $arg | $global_symbol_pipe >> '$nlist'" + done + + if test -z "$run"; then + # Make sure we have at least an empty file. + test -f "$nlist" || : > "$nlist" + + if test -n "$exclude_expsyms"; then + egrep -v " ($exclude_expsyms)$" "$nlist" > "$nlist"T + $mv "$nlist"T "$nlist" + fi + + # Try sorting and uniquifying the output. + if grep -v "^: " < "$nlist" | sort +2 | uniq > "$nlist"S; then + : + else + grep -v "^: " < "$nlist" > "$nlist"S + fi + + if test -f "$nlist"S; then + eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$dlsyms"' + else + echo '/* NONE */' >> "$output_objdir/$dlsyms" + fi + + $echo >> "$output_objdir/$dlsyms" "\ + +#undef lt_preloaded_symbols + +#if defined (__STDC__) && __STDC__ +# define lt_ptr void * +#else +# define lt_ptr char * +# define const +#endif + +/* The mapping between symbol names and symbols. */ +const struct { + const char *name; + lt_ptr address; +} +lt_preloaded_symbols[] = +{\ +" + + eval "$global_symbol_to_c_name_address" < "$nlist" >> "$output_objdir/$dlsyms" + + $echo >> "$output_objdir/$dlsyms" "\ + {0, (lt_ptr) 0} +}; + +/* This works around a problem in FreeBSD linker */ +#ifdef FREEBSD_WORKAROUND +static const void *lt_preloaded_setup() { + return lt_preloaded_symbols; +} +#endif + +#ifdef __cplusplus +} +#endif\ +" + fi + + pic_flag_for_symtable= + case $host in + # compiling the symbol table file with pic_flag works around + # a FreeBSD bug that causes programs to crash when -lm is + # linked before any other PIC object. But we must not use + # pic_flag when linking with -static. The problem exists in + # FreeBSD 2.2.6 and is fixed in FreeBSD 3.1. + *-*-freebsd2*|*-*-freebsd3.0*|*-*-freebsdelf3.0*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC -DFREEBSD_WORKAROUND";; + esac;; + *-*-hpux*) + case "$compile_command " in + *" -static "*) ;; + *) pic_flag_for_symtable=" $pic_flag -DPIC";; + esac + esac + + # Now compile the dynamic symbol file. + $show "(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable \"$dlsyms\")" + $run eval '(cd $output_objdir && $CC -c$no_builtin_flag$pic_flag_for_symtable "$dlsyms")' || exit $? + + # Clean up the generated files. + $show "$rm $output_objdir/$dlsyms $nlist ${nlist}S ${nlist}T" + $run $rm "$output_objdir/$dlsyms" "$nlist" "${nlist}S" "${nlist}T" + + # Transform the symbol file into the correct name. + compile_command=`$echo "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/${outputname}S.${objext}%"` + ;; + *) + $echo "$modename: unknown suffix for \`$dlsyms'" 1>&2 + exit 1 + ;; + esac + else + # We keep going just in case the user didn't refer to + # lt_preloaded_symbols. The linker will fail if global_symbol_pipe + # really was required. + + # Nullify the symbol file. + compile_command=`$echo "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` + finalize_command=`$echo "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + fi + + if test "$need_relink" = no || test "$build_libtool_libs" != yes; then + # Replace the output file specification. + compile_command=`$echo "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command="$compile_command$compile_rpath" + + # We have no uninstalled library dependencies, so finalize right now. + $show "$link_command" + $run eval "$link_command" + status=$? + + # Delete the generated files. + if test -n "$dlsyms"; then + $show "$rm $output_objdir/${outputname}S.${objext}" + $run $rm "$output_objdir/${outputname}S.${objext}" + fi + + exit $status + fi + + if test -n "$shlibpath_var"; then + # We should set the shlibpath_var + rpath= + for dir in $temp_rpath; do + case $dir in + [\\/]* | [A-Za-z]:[\\/]*) + # Absolute path. + rpath="$rpath$dir:" + ;; + *) + # Relative path: add a thisdir entry. + rpath="$rpath\$thisdir/$dir:" + ;; + esac + done + temp_rpath="$rpath" + fi + + if test -n "$compile_shlibpath$finalize_shlibpath"; then + compile_command="$shlibpath_var=\"$compile_shlibpath$finalize_shlibpath\$$shlibpath_var\" $compile_command" + fi + if test -n "$finalize_shlibpath"; then + finalize_command="$shlibpath_var=\"$finalize_shlibpath\$$shlibpath_var\" $finalize_command" + fi + + compile_var= + finalize_var= + if test -n "$runpath_var"; then + if test -n "$perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $perm_rpath; do + rpath="$rpath$dir:" + done + compile_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + if test -n "$finalize_perm_rpath"; then + # We should set the runpath_var. + rpath= + for dir in $finalize_perm_rpath; do + rpath="$rpath$dir:" + done + finalize_var="$runpath_var=\"$rpath\$$runpath_var\" " + fi + fi + + if test "$no_install" = yes; then + # We don't need to create a wrapper script. + link_command="$compile_var$compile_command$compile_rpath" + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + # Delete the old output file. + $run $rm $output + # Link the executable and exit + $show "$link_command" + $run eval "$link_command" || exit $? + exit 0 + fi + + if test "$hardcode_action" = relink; then + # Fast installation is not supported + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + + $echo "$modename: warning: this platform does not like uninstalled shared libraries" 1>&2 + $echo "$modename: \`$output' will be relinked during installation" 1>&2 + else + if test "$fast_install" != no; then + link_command="$finalize_var$compile_command$finalize_rpath" + if test "$fast_install" = yes; then + relink_command=`$echo "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + else + # fast_install is set to needless + relink_command= + fi + else + link_command="$compile_var$compile_command$compile_rpath" + relink_command="$finalize_var$finalize_command$finalize_rpath" + fi + fi + + # Replace the output file specification. + link_command=`$echo "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + + # Delete the old output files. + $run $rm $output $output_objdir/$outputname $output_objdir/lt-$outputname + + $show "$link_command" + $run eval "$link_command" || exit $? + + # Now create the wrapper script. + $show "creating $output" + + # Quote the relink command for shipping. + if test -n "$relink_command"; then + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + relink_command="(cd `pwd`; $relink_command)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + fi + + # Quote $echo for shipping. + if test "X$echo" = "X$SHELL $0 --fallback-echo"; then + case $0 in + [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $0 --fallback-echo";; + *) qecho="$SHELL `pwd`/$0 --fallback-echo";; + esac + qecho=`$echo "X$qecho" | $Xsed -e "$sed_quote_subst"` + else + qecho=`$echo "X$echo" | $Xsed -e "$sed_quote_subst"` + fi + + # Only actually do things if our run command is non-null. + if test -z "$run"; then + # win32 will think the script is a binary if it has + # a .exe suffix, so we strip it off here. + case $output in + *.exe) output=`echo $output|sed 's,.exe$,,'` ;; + esac + # test for cygwin because mv fails w/o .exe extensions + case $host in + *cygwin*) exeext=.exe ;; + *) exeext= ;; + esac + $rm $output + trap "$rm $output; exit 1" 1 2 15 + + $echo > $output "\ +#! $SHELL + +# $output - temporary wrapper script for $objdir/$outputname +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# The $output program cannot be directly executed until all the libtool +# libraries that it depends on are installed. +# +# This wrapper script should never be moved out of the build directory. +# If it is, it will not operate correctly. + +# Sed substitution that helps us do robust quoting. It backslashifies +# metacharacters that are still active within double-quoted strings. +Xsed='sed -e 1s/^X//' +sed_quote_subst='$sed_quote_subst' + +# The HP-UX ksh and POSIX shell print the target directory to stdout +# if CDPATH is set. +if test \"\${CDPATH+set}\" = set; then CDPATH=:; export CDPATH; fi + +relink_command=\"$relink_command\" + +# This environment variable determines our operation mode. +if test \"\$libtool_install_magic\" = \"$magic\"; then + # install mode needs the following variable: + notinst_deplibs='$notinst_deplibs' +else + # When we are sourced in execute mode, \$file and \$echo are already set. + if test \"\$libtool_execute_magic\" != \"$magic\"; then + echo=\"$qecho\" + file=\"\$0\" + # Make sure echo works. + if test \"X\$1\" = X--no-reexec; then + # Discard the --no-reexec flag, and continue. + shift + elif test \"X\`(\$echo '\t') 2>/dev/null\`\" = 'X\t'; then + # Yippee, \$echo works! + : + else + # Restart under the correct shell, and then maybe \$echo will work. + exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} + fi + fi\ +" + $echo >> $output "\ + + # Find the directory that this script lives in. + thisdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + test \"x\$thisdir\" = \"x\$file\" && thisdir=. + + # Follow symbolic links until we get to the real thisdir. + file=\`ls -ld \"\$file\" | sed -n 's/.*-> //p'\` + while test -n \"\$file\"; do + destdir=\`\$echo \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + + # If there was a directory component, then change thisdir. + if test \"x\$destdir\" != \"x\$file\"; then + case \"\$destdir\" in + [\\\\/]* | [A-Za-z]:[\\\\/]*) thisdir=\"\$destdir\" ;; + *) thisdir=\"\$thisdir/\$destdir\" ;; + esac + fi + + file=\`\$echo \"X\$file\" | \$Xsed -e 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | sed -n 's/.*-> //p'\` + done + + # Try to get the absolute directory name. + absdir=\`cd \"\$thisdir\" && pwd\` + test -n \"\$absdir\" && thisdir=\"\$absdir\" +" + + if test "$fast_install" = yes; then + echo >> $output "\ + program=lt-'$outputname'$exeext + progdir=\"\$thisdir/$objdir\" + + if test ! -f \"\$progdir/\$program\" || \\ + { file=\`ls -1dt \"\$progdir/\$program\" \"\$progdir/../\$program\" 2>/dev/null | sed 1q\`; \\ + test \"X\$file\" != \"X\$progdir/\$program\"; }; then + + file=\"\$\$-\$program\" + + if test ! -d \"\$progdir\"; then + $mkdir \"\$progdir\" + else + $rm \"\$progdir/\$file\" + fi" + + echo >> $output "\ + + # relink executable if necessary + if test -n \"\$relink_command\"; then + if relink_command_output=\`eval \$relink_command 2>&1\`; then : + else + $echo \"\$relink_command_output\" >&2 + $rm \"\$progdir/\$file\" + exit 1 + fi + fi + + $mv \"\$progdir/\$file\" \"\$progdir/\$program\" 2>/dev/null || + { $rm \"\$progdir/\$program\"; + $mv \"\$progdir/\$file\" \"\$progdir/\$program\"; } + $rm \"\$progdir/\$file\" + fi" + else + echo >> $output "\ + program='$outputname' + progdir=\"\$thisdir/$objdir\" +" + fi + + echo >> $output "\ + + if test -f \"\$progdir/\$program\"; then" + + # Export our shlibpath_var if we have one. + if test "$shlibpath_overrides_runpath" = yes && test -n "$shlibpath_var" && test -n "$temp_rpath"; then + $echo >> $output "\ + # Add our own library path to $shlibpath_var + $shlibpath_var=\"$temp_rpath\$$shlibpath_var\" + + # Some systems cannot cope with colon-terminated $shlibpath_var + # The second colon is a workaround for a bug in BeOS R4 sed + $shlibpath_var=\`\$echo \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + + export $shlibpath_var +" + fi + + # fixup the dll searchpath if we need to. + if test -n "$dllsearchpath"; then + $echo >> $output "\ + # Add the dll search path components to the executable PATH + PATH=$dllsearchpath:\$PATH +" + fi + + $echo >> $output "\ + if test \"\$libtool_execute_magic\" != \"$magic\"; then + # Run the actual program with our arguments. +" + case $host in + # win32 systems need to use the prog path for dll + # lookup to work + *-*-cygwin* | *-*-pw32*) + $echo >> $output "\ + exec \$progdir/\$program \${1+\"\$@\"} +" + ;; + + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2*) + $echo >> $output "\ + exec \$progdir\\\\\$program \${1+\"\$@\"} +" + ;; + + *) + $echo >> $output "\ + # Export the path to the program. + PATH=\"\$progdir:\$PATH\" + export PATH + + exec \$program \${1+\"\$@\"} +" + ;; + esac + $echo >> $output "\ + \$echo \"\$0: cannot exec \$program \${1+\"\$@\"}\" + exit 1 + fi + else + # The program doesn't exist. + \$echo \"\$0: error: \$progdir/\$program does not exist\" 1>&2 + \$echo \"This script is just a wrapper for \$program.\" 1>&2 + echo \"See the $PACKAGE documentation for more information.\" 1>&2 + exit 1 + fi +fi\ +" + chmod +x $output + fi + exit 0 + ;; + esac + + # See if we need to build an old-fashioned archive. + for oldlib in $oldlibs; do + + if test "$build_libtool_libs" = convenience; then + oldobjs="$libobjs_save" + addlibs="$convenience" + build_libtool_libs=no + else + if test "$build_libtool_libs" = module; then + oldobjs="$libobjs_save" + build_libtool_libs=no + else + oldobjs="$objs$old_deplibs "`$echo "X$libobjs_save" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP` + fi + addlibs="$old_convenience" + fi + + if test -n "$addlibs"; then + gentop="$output_objdir/${outputname}x" + $show "${rm}r $gentop" + $run ${rm}r "$gentop" + $show "mkdir $gentop" + $run mkdir "$gentop" + status=$? + if test "$status" -ne 0 && test ! -d "$gentop"; then + exit $status + fi + generated="$generated $gentop" + + # Add in members from convenience archives. + for xlib in $addlibs; do + # Extract the objects. + case $xlib in + [\\/]* | [A-Za-z]:[\\/]*) xabs="$xlib" ;; + *) xabs=`pwd`"/$xlib" ;; + esac + xlib=`$echo "X$xlib" | $Xsed -e 's%^.*/%%'` + xdir="$gentop/$xlib" + + $show "${rm}r $xdir" + $run ${rm}r "$xdir" + $show "mkdir $xdir" + $run mkdir "$xdir" + status=$? + if test "$status" -ne 0 && test ! -d "$xdir"; then + exit $status + fi + $show "(cd $xdir && $AR x $xabs)" + $run eval "(cd \$xdir && $AR x \$xabs)" || exit $? + + oldobjs="$oldobjs "`find $xdir -name \*.${objext} -print -o -name \*.lo -print | $NL2SP` + done + fi + + # Do each command in the archive commands. + if test -n "$old_archive_from_new_cmds" && test "$build_libtool_libs" = yes; then + eval cmds=\"$old_archive_from_new_cmds\" + else + # Ensure that we have .o objects in place in case we decided + # not to build a shared library, and have fallen back to building + # static libs even though --disable-static was passed! + for oldobj in $oldobjs; do + if test ! -f $oldobj; then + xdir=`$echo "X$oldobj" | $Xsed -e 's%/[^/]*$%%'` + if test "X$xdir" = "X$oldobj"; then + xdir="." + else + xdir="$xdir" + fi + baseobj=`$echo "X$oldobj" | $Xsed -e 's%^.*/%%'` + obj=`$echo "X$baseobj" | $Xsed -e "$o2lo"` + $show "(cd $xdir && ${LN_S} $obj $baseobj)" + $run eval '(cd $xdir && ${LN_S} $obj $baseobj)' || exit $? + fi + done + + eval cmds=\"$old_archive_cmds\" + fi + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$generated"; then + $show "${rm}r$generated" + $run ${rm}r$generated + fi + + # Now create the libtool archive. + case $output in + *.la) + old_library= + test "$build_old_libs" = yes && old_library="$libname.$libext" + $show "creating $output" + + # Preserve any variables that may affect compiler behavior + for var in $variables_saved_for_relink; do + if eval test -z \"\${$var+set}\"; then + relink_command="{ test -z \"\${$var+set}\" || unset $var || { $var=; export $var; }; }; $relink_command" + elif eval var_value=\$$var; test -z "$var_value"; then + relink_command="$var=; export $var; $relink_command" + else + var_value=`$echo "X$var_value" | $Xsed -e "$sed_quote_subst"` + relink_command="$var=\"$var_value\"; export $var; $relink_command" + fi + done + # Quote the link command for shipping. + relink_command="(cd `pwd`; $SHELL $0 --mode=relink $libtool_args @inst_prefix_dir@)" + relink_command=`$echo "X$relink_command" | $Xsed -e "$sed_quote_subst"` + + # Only create the output if not a dry run. + if test -z "$run"; then + for installed in no yes; do + if test "$installed" = yes; then + if test -z "$install_libdir"; then + break + fi + output="$output_objdir/$outputname"i + # Replace all uninstalled libtool libraries with the installed ones + newdependency_libs= + for deplib in $dependency_libs; do + case $deplib in + *.la) + name=`$echo "X$deplib" | $Xsed -e 's%^.*/%%'` + eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $deplib` + if test -z "$libdir"; then + $echo "$modename: \`$deplib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdependency_libs="$newdependency_libs $libdir/$name" + ;; + *) newdependency_libs="$newdependency_libs $deplib" ;; + esac + done + dependency_libs="$newdependency_libs" + newdlfiles= + for lib in $dlfiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlfiles="$newdlfiles $libdir/$name" + done + dlfiles="$newdlfiles" + newdlprefiles= + for lib in $dlprefiles; do + name=`$echo "X$lib" | $Xsed -e 's%^.*/%%'` + eval libdir=`sed -n -e 's/^libdir=\(.*\)$/\1/p' $lib` + if test -z "$libdir"; then + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + exit 1 + fi + newdlprefiles="$newdlprefiles $libdir/$name" + done + dlprefiles="$newdlprefiles" + fi + $rm $output + # place dlname in correct position for cygwin + tdlname=$dlname + case $host,$output,$installed,$module,$dlname in + *cygwin*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + esac + $echo > $output "\ +# $outputname - a libtool library file +# Generated by $PROGRAM - GNU $PACKAGE $VERSION$TIMESTAMP +# +# Please DO NOT delete this file! +# It is necessary for linking the library. + +# The name that we can dlopen(3). +dlname='$tdlname' + +# Names of this library. +library_names='$library_names' + +# The name of the static archive. +old_library='$old_library' + +# Libraries that this one depends upon. +dependency_libs='$dependency_libs' + +# Version information for $libname. +current=$current +age=$age +revision=$revision + +# Is this an already installed library? +installed=$installed + +# Files to dlopen/dlpreopen +dlopen='$dlfiles' +dlpreopen='$dlprefiles' + +# Directory that this library needs to be installed in: +libdir='$install_libdir'" + if test "$installed" = no && test "$need_relink" = yes; then + $echo >> $output "\ +relink_command=\"$relink_command\"" + fi + done + fi + + # Do a symbolic link so that the libtool archive can be found in + # LD_LIBRARY_PATH before the program is installed. + $show "(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)" + $run eval '(cd $output_objdir && $rm $outputname && $LN_S ../$outputname $outputname)' || exit $? + ;; + esac + exit 0 + ;; + + # libtool install mode + install) + modename="$modename: install" + + # There may be an optional sh(1) argument at the beginning of + # install_prog (especially on Windows NT). + if test "$nonopt" = "$SHELL" || test "$nonopt" = /bin/sh || + # Allow the use of GNU shtool's install command. + $echo "X$nonopt" | $Xsed | grep shtool > /dev/null; then + # Aesthetically quote it. + arg=`$echo "X$nonopt" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$arg " + arg="$1" + shift + else + install_prog= + arg="$nonopt" + fi + + # The real first argument should be the name of the installation program. + # Aesthetically quote it. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog$arg" + + # We need to accept at least all the BSD install flags. + dest= + files= + opts= + prev= + install_type= + isdir=no + stripme= + for arg + do + if test -n "$dest"; then + files="$files $dest" + dest="$arg" + continue + fi + + case $arg in + -d) isdir=yes ;; + -f) prev="-f" ;; + -g) prev="-g" ;; + -m) prev="-m" ;; + -o) prev="-o" ;; + -s) + stripme=" -s" + continue + ;; + -*) ;; + + *) + # If the previous option needed an argument, then skip it. + if test -n "$prev"; then + prev= + else + dest="$arg" + continue + fi + ;; + esac + + # Aesthetically quote the argument. + arg=`$echo "X$arg" | $Xsed -e "$sed_quote_subst"` + case $arg in + *[\[\~\#\^\&\*\(\)\{\}\|\;\<\>\?\'\ \ ]*|*]*) + arg="\"$arg\"" + ;; + esac + install_prog="$install_prog $arg" + done + + if test -z "$install_prog"; then + $echo "$modename: you must specify an install program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -n "$prev"; then + $echo "$modename: the \`$prev' option requires an argument" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + if test -z "$files"; then + if test -z "$dest"; then + $echo "$modename: no file or destination specified" 1>&2 + else + $echo "$modename: you must specify a destination" 1>&2 + fi + $echo "$help" 1>&2 + exit 1 + fi + + # Strip any trailing slash from the destination. + dest=`$echo "X$dest" | $Xsed -e 's%/$%%'` + + # Check to see that the destination is a directory. + test -d "$dest" && isdir=yes + if test "$isdir" = yes; then + destdir="$dest" + destname= + else + destdir=`$echo "X$dest" | $Xsed -e 's%/[^/]*$%%'` + test "X$destdir" = "X$dest" && destdir=. + destname=`$echo "X$dest" | $Xsed -e 's%^.*/%%'` + + # Not a directory, so check to see that there is only one file specified. + set dummy $files + if test "$#" -gt 2; then + $echo "$modename: \`$dest' is not a directory" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + fi + case $destdir in + [\\/]* | [A-Za-z]:[\\/]*) ;; + *) + for file in $files; do + case $file in + *.lo) ;; + *) + $echo "$modename: \`$destdir' must be an absolute directory name" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + done + ;; + esac + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + staticlibs= + future_libdirs= + current_libdirs= + for file in $files; do + + # Do each installation. + case $file in + *.$libext) + # Do the static libraries later. + staticlibs="$staticlibs $file" + ;; + + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$file' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + library_names= + old_library= + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Add the libdir to current_libdirs if it is the destination. + if test "X$destdir" = "X$libdir"; then + case "$current_libdirs " in + *" $libdir "*) ;; + *) current_libdirs="$current_libdirs $libdir" ;; + esac + else + # Note the libdir as a future libdir. + case "$future_libdirs " in + *" $libdir "*) ;; + *) future_libdirs="$future_libdirs $libdir" ;; + esac + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'`/ + test "X$dir" = "X$file/" && dir= + dir="$dir$objdir" + + if test -n "$relink_command"; then + # Determine the prefix the user has applied to our future dir. + inst_prefix_dir=`$echo "$destdir" | sed "s%$libdir\$%%"` + + # Don't allow the user to place us outside of our expected + # location b/c this prevents finding dependent libraries that + # are installed to the same prefix. + if test "$inst_prefix_dir" = "$destdir"; then + $echo "$modename: error: cannot install \`$file' to a directory not ending in $libdir" 1>&2 + exit 1 + fi + + if test -n "$inst_prefix_dir"; then + # Stick the inst_prefix_dir data into the link command. + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + else + relink_command=`$echo "$relink_command" | sed "s%@inst_prefix_dir@%%"` + fi + + $echo "$modename: warning: relinking \`$file'" 1>&2 + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + exit 1 + fi + fi + + # See the names of the shared library. + set dummy $library_names + if test -n "$2"; then + realname="$2" + shift + shift + + srcname="$realname" + test -n "$relink_command" && srcname="$realname"T + + # Install the shared library and build the symlinks. + $show "$install_prog $dir/$srcname $destdir/$realname" + $run eval "$install_prog $dir/$srcname $destdir/$realname" || exit $? + if test -n "$stripme" && test -n "$striplib"; then + $show "$striplib $destdir/$realname" + $run eval "$striplib $destdir/$realname" || exit $? + fi + + if test "$#" -gt 0; then + # Delete the old symlinks, and create new ones. + for linkname + do + if test "$linkname" != "$realname"; then + $show "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + $run eval "(cd $destdir && $rm $linkname && $LN_S $realname $linkname)" + fi + done + fi + + # Do each command in the postinstall commands. + lib="$destdir/$realname" + eval cmds=\"$postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + fi + + # Install the pseudo-library for information purposes. + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + instname="$dir/$name"i + $show "$install_prog $instname $destdir/$name" + $run eval "$install_prog $instname $destdir/$name" || exit $? + + # Maybe install the static library, too. + test -n "$old_library" && staticlibs="$staticlibs $dir/$old_library" + ;; + + *.lo) + # Install (i.e. copy) a libtool object. + + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Deduce the name of the destination old-style object file. + case $destfile in + *.lo) + staticdest=`$echo "X$destfile" | $Xsed -e "$lo2o"` + ;; + *.$objext) + staticdest="$destfile" + destfile= + ;; + *) + $echo "$modename: cannot copy a libtool object to \`$destfile'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; + esac + + # Install the libtool object if requested. + if test -n "$destfile"; then + $show "$install_prog $file $destfile" + $run eval "$install_prog $file $destfile" || exit $? + fi + + # Install the old object if enabled. + if test "$build_old_libs" = yes; then + # Deduce the name of the old-style object file. + staticobj=`$echo "X$file" | $Xsed -e "$lo2o"` + + $show "$install_prog $staticobj $staticdest" + $run eval "$install_prog \$staticobj \$staticdest" || exit $? + fi + exit 0 + ;; + + *) + # Figure out destination file name, if it wasn't already specified. + if test -n "$destname"; then + destfile="$destdir/$destname" + else + destfile=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + destfile="$destdir/$destfile" + fi + + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + notinst_deplibs= + relink_command= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Check the variables that should have been set. + if test -z "$notinst_deplibs"; then + $echo "$modename: invalid libtool wrapper script \`$file'" 1>&2 + exit 1 + fi + + finalize=yes + for lib in $notinst_deplibs; do + # Check to see that each library is installed. + libdir= + if test -f "$lib"; then + # If there is no directory component, then add one. + case $lib in + */* | *\\*) . $lib ;; + *) . ./$lib ;; + esac + fi + libfile="$libdir/"`$echo "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + if test -n "$libdir" && test ! -f "$libfile"; then + $echo "$modename: warning: \`$lib' has not been installed in \`$libdir'" 1>&2 + finalize=no + fi + done + + relink_command= + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + outputname= + if test "$fast_install" = no && test -n "$relink_command"; then + if test "$finalize" = yes && test -z "$run"; then + tmpdir="/tmp" + test -n "$TMPDIR" && tmpdir="$TMPDIR" + tmpdir=`mktemp -d $tmpdir/libtool-XXXXXX 2> /dev/null` + if test $? = 0 ; then : + else + tmpdir="$tmpdir/libtool-$$" + fi + if $mkdir -p "$tmpdir" && chmod 700 "$tmpdir"; then : + else + $echo "$modename: error: cannot create temporary directory \`$tmpdir'" 1>&2 + continue + fi + file=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + outputname="$tmpdir/$file" + # Replace the output file specification. + relink_command=`$echo "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + + $show "$relink_command" + if $run eval "$relink_command"; then : + else + $echo "$modename: error: relink \`$file' with the above command before installing it" 1>&2 + ${rm}r "$tmpdir" + continue + fi + file="$outputname" + else + $echo "$modename: warning: cannot relink \`$file'" 1>&2 + fi + else + # Install the binary that we compiled earlier. + file=`$echo "X$file" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + fi + fi + + # remove .exe since cygwin /usr/bin/install will append another + # one anyways + case $install_prog,$host in + /usr/bin/install*,*cygwin*) + case $file:$destfile in + *.exe:*.exe) + # this is ok + ;; + *.exe:*) + destfile=$destfile.exe + ;; + *:*.exe) + destfile=`echo $destfile | sed -e 's,.exe$,,'` + ;; + esac + ;; + esac + $show "$install_prog$stripme $file $destfile" + $run eval "$install_prog\$stripme \$file \$destfile" || exit $? + test -n "$outputname" && ${rm}r "$tmpdir" + ;; + esac + done + + for file in $staticlibs; do + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + + # Set up the ranlib parameters. + oldlib="$destdir/$name" + + $show "$install_prog $file $oldlib" + $run eval "$install_prog \$file \$oldlib" || exit $? + + if test -n "$stripme" && test -n "$striplib"; then + $show "$old_striplib $oldlib" + $run eval "$old_striplib $oldlib" || exit $? + fi + + # Do each command in the postinstall commands. + eval cmds=\"$old_postinstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || exit $? + done + IFS="$save_ifs" + done + + if test -n "$future_libdirs"; then + $echo "$modename: warning: remember to run \`$progname --finish$future_libdirs'" 1>&2 + fi + + if test -n "$current_libdirs"; then + # Maybe just do a dry run. + test -n "$run" && current_libdirs=" -n$current_libdirs" + exec_cmd='$SHELL $0 --finish$current_libdirs' + else + exit 0 + fi + ;; + + # libtool finish mode + finish) + modename="$modename: finish" + libdirs="$nonopt" + admincmds= + + if test -n "$finish_cmds$finish_eval" && test -n "$libdirs"; then + for dir + do + libdirs="$libdirs $dir" + done + + for libdir in $libdirs; do + if test -n "$finish_cmds"; then + # Do each command in the finish commands. + eval cmds=\"$finish_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" || admincmds="$admincmds + $cmd" + done + IFS="$save_ifs" + fi + if test -n "$finish_eval"; then + # Do the single finish_eval. + eval cmds=\"$finish_eval\" + $run eval "$cmds" || admincmds="$admincmds + $cmds" + fi + done + fi + + # Exit here if they wanted silent mode. + test "$show" = : && exit 0 + + echo "----------------------------------------------------------------------" + echo "Libraries have been installed in:" + for libdir in $libdirs; do + echo " $libdir" + done + echo + echo "If you ever happen to want to link against installed libraries" + echo "in a given directory, LIBDIR, you must either use libtool, and" + echo "specify the full pathname of the library, or use the \`-LLIBDIR'" + echo "flag during linking and do at least one of the following:" + if test -n "$shlibpath_var"; then + echo " - add LIBDIR to the \`$shlibpath_var' environment variable" + echo " during execution" + fi + if test -n "$runpath_var"; then + echo " - add LIBDIR to the \`$runpath_var' environment variable" + echo " during linking" + fi + if test -n "$hardcode_libdir_flag_spec"; then + libdir=LIBDIR + eval flag=\"$hardcode_libdir_flag_spec\" + + echo " - use the \`$flag' linker flag" + fi + if test -n "$admincmds"; then + echo " - have your system administrator run these commands:$admincmds" + fi + if test -f /etc/ld.so.conf; then + echo " - have your system administrator add LIBDIR to \`/etc/ld.so.conf'" + fi + echo + echo "See any operating system documentation about shared libraries for" + echo "more information, such as the ld(1) and ld.so(8) manual pages." + echo "----------------------------------------------------------------------" + exit 0 + ;; + + # libtool execute mode + execute) + modename="$modename: execute" + + # The first argument is the command name. + cmd="$nonopt" + if test -z "$cmd"; then + $echo "$modename: you must specify a COMMAND" 1>&2 + $echo "$help" + exit 1 + fi + + # Handle -dlopen flags immediately. + for file in $execute_dlfiles; do + if test ! -f "$file"; then + $echo "$modename: \`$file' is not a file" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + dir= + case $file in + *.la) + # Check to see that this really is a libtool archive. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then : + else + $echo "$modename: \`$lib' is not a valid libtool archive" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + # Read the libtool library. + dlname= + library_names= + + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Skip this library if it cannot be dlopened. + if test -z "$dlname"; then + # Warn if it was a shared library. + test -n "$library_names" && $echo "$modename: warning: \`$file' was not linked with \`-export-dynamic'" + continue + fi + + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + + if test -f "$dir/$objdir/$dlname"; then + dir="$dir/$objdir" + else + $echo "$modename: cannot find \`$dlname' in \`$dir' or \`$dir/$objdir'" 1>&2 + exit 1 + fi + ;; + + *.lo) + # Just add the directory containing the .lo file. + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + test "X$dir" = "X$file" && dir=. + ;; + + *) + $echo "$modename: warning \`-dlopen' is ignored for non-libtool libraries and objects" 1>&2 + continue + ;; + esac + + # Get the absolute pathname. + absdir=`cd "$dir" && pwd` + test -n "$absdir" && dir="$absdir" + + # Now add the directory to shlibpath_var. + if eval "test -z \"\$$shlibpath_var\""; then + eval "$shlibpath_var=\"\$dir\"" + else + eval "$shlibpath_var=\"\$dir:\$$shlibpath_var\"" + fi + done + + # This variable tells wrapper scripts just to set shlibpath_var + # rather than running their programs. + libtool_execute_magic="$magic" + + # Check if any of the arguments is a wrapper script. + args= + for file + do + case $file in + -*) ;; + *) + # Do a test to see if this is really a libtool program. + if (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + # If there is no directory component, then add one. + case $file in + */* | *\\*) . $file ;; + *) . ./$file ;; + esac + + # Transform arg to wrapped name. + file="$progdir/$program" + fi + ;; + esac + # Quote arguments (to preserve shell metacharacters). + file=`$echo "X$file" | $Xsed -e "$sed_quote_subst"` + args="$args \"$file\"" + done + + if test -z "$run"; then + if test -n "$shlibpath_var"; then + # Export the shlibpath_var. + eval "export $shlibpath_var" + fi + + # Restore saved enviroment variables + if test "${save_LC_ALL+set}" = set; then + LC_ALL="$save_LC_ALL"; export LC_ALL + fi + if test "${save_LANG+set}" = set; then + LANG="$save_LANG"; export LANG + fi + + # Now prepare to actually exec the command. + exec_cmd="\$cmd$args" + else + # Display what would be done. + if test -n "$shlibpath_var"; then + eval "\$echo \"\$shlibpath_var=\$$shlibpath_var\"" + $echo "export $shlibpath_var" + fi + $echo "$cmd$args" + exit 0 + fi + ;; + + # libtool clean and uninstall mode + clean | uninstall) + modename="$modename: $mode" + rm="$nonopt" + files= + rmforce= + exit_status=0 + + # This variable tells wrapper scripts just to set variables rather + # than running their programs. + libtool_install_magic="$magic" + + for arg + do + case $arg in + -f) rm="$rm $arg"; rmforce=yes ;; + -*) rm="$rm $arg" ;; + *) files="$files $arg" ;; + esac + done + + if test -z "$rm"; then + $echo "$modename: you must specify an RM program" 1>&2 + $echo "$help" 1>&2 + exit 1 + fi + + rmdirs= + + for file in $files; do + dir=`$echo "X$file" | $Xsed -e 's%/[^/]*$%%'` + if test "X$dir" = "X$file"; then + dir=. + objdir="$objdir" + else + objdir="$dir/$objdir" + fi + name=`$echo "X$file" | $Xsed -e 's%^.*/%%'` + test "$mode" = uninstall && objdir="$dir" + + # Remember objdir for removal later, being careful to avoid duplicates + if test "$mode" = clean; then + case " $rmdirs " in + *" $objdir "*) ;; + *) rmdirs="$rmdirs $objdir" ;; + esac + fi + + # Don't error if the file doesn't exist and rm -f was used. + if (test -L "$file") >/dev/null 2>&1 \ + || (test -h "$file") >/dev/null 2>&1 \ + || test -f "$file"; then + : + elif test -d "$file"; then + exit_status=1 + continue + elif test "$rmforce" = yes; then + continue + fi + + rmfiles="$file" + + case $name in + *.la) + # Possibly a libtool archive, so verify it. + if (sed -e '2q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + . $dir/$name + + # Delete the libtool libraries and symlinks. + for n in $library_names; do + rmfiles="$rmfiles $objdir/$n" + done + test -n "$old_library" && rmfiles="$rmfiles $objdir/$old_library" + test "$mode" = clean && rmfiles="$rmfiles $objdir/$name $objdir/${name}i" + + if test "$mode" = uninstall; then + if test -n "$library_names"; then + # Do each command in the postuninstall commands. + eval cmds=\"$postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + + if test -n "$old_library"; then + # Do each command in the old_postuninstall commands. + eval cmds=\"$old_postuninstall_cmds\" + save_ifs="$IFS"; IFS='~' + for cmd in $cmds; do + IFS="$save_ifs" + $show "$cmd" + $run eval "$cmd" + if test "$?" -ne 0 && test "$rmforce" != yes; then + exit_status=1 + fi + done + IFS="$save_ifs" + fi + # FIXME: should reinstall the best remaining shared library. + fi + fi + ;; + + *.lo) + if test "$build_old_libs" = yes; then + oldobj=`$echo "X$name" | $Xsed -e "$lo2o"` + rmfiles="$rmfiles $dir/$oldobj" + fi + ;; + + *) + # Do a test to see if this is a libtool program. + if test "$mode" = clean && + (sed -e '4q' $file | egrep "^# Generated by .*$PACKAGE") >/dev/null 2>&1; then + relink_command= + . $dir/$file + + rmfiles="$rmfiles $objdir/$name $objdir/${name}S.${objext}" + if test "$fast_install" = yes && test -n "$relink_command"; then + rmfiles="$rmfiles $objdir/lt-$name" + fi + fi + ;; + esac + $show "$rm $rmfiles" + $run $rm $rmfiles || exit_status=1 + done + + # Try to remove the ${objdir}s in the directories where we deleted files + for dir in $rmdirs; do + if test -d "$dir"; then + $show "rmdir $dir" + $run rmdir $dir >/dev/null 2>&1 + fi + done + + exit $exit_status + ;; + + "") + $echo "$modename: you must specify a MODE" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + ;; + esac + + if test -z "$exec_cmd"; then + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$generic_help" 1>&2 + exit 1 + fi +fi # test -z "$show_help" + +if test -n "$exec_cmd"; then + eval exec $exec_cmd + exit 1 +fi + +# We need to display help for each of the modes. +case $mode in +"") $echo \ +"Usage: $modename [OPTION]... [MODE-ARG]... + +Provide generalized library-building support services. + + --config show all configuration variables + --debug enable verbose shell tracing +-n, --dry-run display commands without modifying any files + --features display basic configuration information and exit + --finish same as \`--mode=finish' + --help display this help message and exit + --mode=MODE use operation mode MODE [default=inferred from MODE-ARGS] + --quiet same as \`--silent' + --silent don't print informational messages + --version print version information + +MODE must be one of the following: + + clean remove files from the build directory + compile compile a source file into a libtool object + execute automatically set library path, then run a program + finish complete the installation of libtool libraries + install install libraries or executables + link create a library or an executable + uninstall remove libraries from an installed directory + +MODE-ARGS vary depending on the MODE. Try \`$modename --help --mode=MODE' for +a more detailed description of MODE." + exit 0 + ;; + +clean) + $echo \ +"Usage: $modename [OPTION]... --mode=clean RM [RM-OPTION]... FILE... + +Remove files from the build directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, object or program, all the files associated +with it are deleted. Otherwise, only FILE itself is deleted using RM." + ;; + +compile) + $echo \ +"Usage: $modename [OPTION]... --mode=compile COMPILE-COMMAND... SOURCEFILE + +Compile a source file into a libtool library object. + +This mode accepts the following additional options: + + -o OUTPUT-FILE set the output file name to OUTPUT-FILE + -prefer-pic try to building PIC objects only + -prefer-non-pic try to building non-PIC objects only + -static always build a \`.o' file suitable for static linking + +COMPILE-COMMAND is a command to be used in creating a \`standard' object file +from the given SOURCEFILE. + +The output file name is determined by removing the directory component from +SOURCEFILE, then substituting the C source code suffix \`.c' with the +library object suffix, \`.lo'." + ;; + +execute) + $echo \ +"Usage: $modename [OPTION]... --mode=execute COMMAND [ARGS]... + +Automatically set library path, then run a program. + +This mode accepts the following additional options: + + -dlopen FILE add the directory containing FILE to the library path + +This mode sets the library path environment variable according to \`-dlopen' +flags. + +If any of the ARGS are libtool executable wrappers, then they are translated +into their corresponding uninstalled binary, and any of their required library +directories are added to the library path. + +Then, COMMAND is executed, with ARGS as arguments." + ;; + +finish) + $echo \ +"Usage: $modename [OPTION]... --mode=finish [LIBDIR]... + +Complete the installation of libtool libraries. + +Each LIBDIR is a directory that contains libtool libraries. + +The commands that this mode executes may require superuser privileges. Use +the \`--dry-run' option if you just want to see what would be executed." + ;; + +install) + $echo \ +"Usage: $modename [OPTION]... --mode=install INSTALL-COMMAND... + +Install executables or libraries. + +INSTALL-COMMAND is the installation command. The first component should be +either the \`install' or \`cp' program. + +The rest of the components are interpreted as arguments to that command (only +BSD-compatible install options are recognized)." + ;; + +link) + $echo \ +"Usage: $modename [OPTION]... --mode=link LINK-COMMAND... + +Link object files or libraries together to form another library, or to +create an executable program. + +LINK-COMMAND is a command using the C compiler that you would use to create +a program from several object files. + +The following components of LINK-COMMAND are treated specially: + + -all-static do not do any dynamic linking at all + -avoid-version do not add a version suffix if possible + -dlopen FILE \`-dlpreopen' FILE if it cannot be dlopened at runtime + -dlpreopen FILE link in FILE and add its symbols to lt_preloaded_symbols + -export-dynamic allow symbols from OUTPUT-FILE to be resolved with dlsym(3) + -export-symbols SYMFILE + try to export only the symbols listed in SYMFILE + -export-symbols-regex REGEX + try to export only the symbols matching REGEX + -LLIBDIR search LIBDIR for required installed libraries + -lNAME OUTPUT-FILE requires the installed library libNAME + -module build a library that can dlopened + -no-fast-install disable the fast-install mode + -no-install link a not-installable executable + -no-undefined declare that a library does not refer to external symbols + -o OUTPUT-FILE create OUTPUT-FILE from the specified objects + -release RELEASE specify package release information + -rpath LIBDIR the created library will eventually be installed in LIBDIR + -R[ ]LIBDIR add LIBDIR to the runtime path of programs and libraries + -static do not do any dynamic linking of libtool libraries + -version-info CURRENT[:REVISION[:AGE]] + specify library version info [each variable defaults to 0] + +All other options (arguments beginning with \`-') are ignored. + +Every other argument is treated as a filename. Files ending in \`.la' are +treated as uninstalled libtool libraries, other files are standard or library +object files. + +If the OUTPUT-FILE ends in \`.la', then a libtool library is created, +only library objects (\`.lo' files) may be specified, and \`-rpath' is +required, except when creating a convenience library. + +If OUTPUT-FILE ends in \`.a' or \`.lib', then a standard library is created +using \`ar' and \`ranlib', or on Windows using \`lib'. + +If OUTPUT-FILE ends in \`.lo' or \`.${objext}', then a reloadable object file +is created, otherwise an executable program is created." + ;; + +uninstall) + $echo \ +"Usage: $modename [OPTION]... --mode=uninstall RM [RM-OPTION]... FILE... + +Remove libraries from an installation directory. + +RM is the name of the program to use to delete files associated with each FILE +(typically \`/bin/rm'). RM-OPTIONS are options (such as \`-f') to be passed +to RM. + +If FILE is a libtool library, all the files associated with it are deleted. +Otherwise, only FILE itself is deleted using RM." + ;; + +*) + $echo "$modename: invalid operation mode \`$mode'" 1>&2 + $echo "$help" 1>&2 + exit 1 + ;; +esac + +echo +$echo "Try \`$modename --help' for more information about other modes." + +exit 0 + +# Local Variables: +# mode:shell-script +# sh-indentation:2 +# End: diff --git a/trunk/m4/Makefile.am b/trunk/m4/Makefile.am new file mode 100644 index 0000000..d9fab43 --- /dev/null +++ b/trunk/m4/Makefile.am @@ -0,0 +1,4 @@ +## Process this file with automake to produce Makefile.in -*-Makefile-*- + +##m4-files-begin +EXTRA_DIST = libelf.m4 diff --git a/trunk/m4/Makefile.in b/trunk/m4/Makefile.in new file mode 100644 index 0000000..e7a76bf --- /dev/null +++ b/trunk/m4/Makefile.in @@ -0,0 +1,186 @@ +# Makefile.in generated automatically by automake 1.4-p5 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AS = @AS@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +DLLTOOL = @DLLTOOL@ +GELFINCLUDE = @GELFINCLUDE@ +GETCONF = @GETCONF@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +MAKEINFO = @MAKEINFO@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +VERSION = @VERSION@ + +EXTRA_DIST = libelf.m4 +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = gtar +GZIP_ENV = --best +all: all-redirect +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu m4/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status $(BUILT_SOURCES) + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + +tags: TAGS +TAGS: + + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = m4 + +distdir: $(DISTFILES) + here=`cd $(top_builddir) && pwd`; \ + top_distdir=`cd $(top_distdir) && pwd`; \ + distdir=`cd $(distdir) && pwd`; \ + cd $(top_srcdir) \ + && $(AUTOMAKE) --include-deps --build-dir=$$here --srcdir-name=$(top_srcdir) --output-dir=$$top_distdir --gnu m4/Makefile + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-generic clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: tags distdir info-am info dvi-am dvi check check-am \ +installcheck-am installcheck install-exec-am install-exec \ +install-data-am install-data install-am install uninstall-am uninstall \ +all-redirect all-am all installdirs mostlyclean-generic \ +distclean-generic clean-generic maintainer-clean-generic clean \ +mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/m4/libelf.m4 b/trunk/m4/libelf.m4 new file mode 100644 index 0000000..7e80a5d --- /dev/null +++ b/trunk/m4/libelf.m4 @@ -0,0 +1,118 @@ +#serial 7 + +dnl Some libelf versions have bugs in Elf64_Sxword conversions. +dnl Detect it. + +dnl Written by Jakub Jelinek <jakub@redhat.com>. + +AC_DEFUN(AC_LIBELF_SXWORD, + [AC_TRY_RUN([ +#include <errno.h> +#include <fcntl.h> +#include <elf.h> +#include <libelf.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +static unsigned char sparc64_elf[] = { +0x7f,0x45,0x4c,0x46,0x02,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x01,0x00,0x2b,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x02,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x08,0x00,0x05, +0x00,0x00,0x07,0xff,0xf0,0x00,0x00,0x00,0x00,0x2e,0x73,0x79,0x6d,0x74,0x61,0x62, +0x00,0x2e,0x73,0x74,0x72,0x74,0x61,0x62,0x00,0x2e,0x73,0x68,0x73,0x74,0x72,0x74, +0x61,0x62,0x00,0x2e,0x74,0x65,0x78,0x74,0x00,0x2e,0x64,0x61,0x74,0x61,0x00,0x2e, +0x62,0x73,0x73,0x00,0x66,0x6f,0x6f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x1b,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x21,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x27,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x2c,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x40,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x11,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x48,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x30, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0x78,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x78, +0x00,0x00,0x00,0x07,0x00,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x08, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x00,0x00,0x00,0x09,0x00,0x00,0x00,0x03, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x02,0xf0,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x02, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,0x00,0x00,0x04, +0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, +0x00 }; + +int main (void) +{ + Elf *elf; + int fd; + Elf64_Ehdr *ehdr; + Elf64_Addr val; + Elf_Scn *scn; + + fd = open ("conflibelftest", O_RDWR | O_CREAT | O_EXCL); if (fd == -1) exit (1); + unlink ("conflibelftest"); + if (write (fd, sparc64_elf, sizeof(sparc64_elf)) != sizeof(sparc64_elf)) + exit (1); + if (lseek (fd, 0, SEEK_SET) != 0) exit (1); + elf_version (EV_CURRENT); + elf = elf_begin (fd, ELF_C_RDWR, NULL); if (elf == NULL) exit (2); + if ((ehdr = elf64_getehdr (elf)) == NULL) exit (3); + scn = NULL; + while ((scn = elf_nextscn (elf, scn)) != NULL) + { + char *name = NULL; + Elf64_Shdr *shdr; + Elf_Data *src, *dst; + + if ((shdr = elf64_getshdr (scn)) + && (name = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name)) + && !strcmp (name, "foo")) + { + src = elf_rawdata (scn, NULL); + if (shdr->sh_size != 8 || src->d_off || src->d_size != 8) exit (4); + if (src == NULL || elf_rawdata (scn, src) != NULL) exit (5); + if ((dst = elf_newdata (scn)) == NULL) exit (6); + dst->d_buf = &val; + dst->d_size = 8; + dst->d_off = 0; + dst->d_type = ELF_T_SXWORD; + src->d_type = ELF_T_SXWORD; + if (elf64_xlatetom (dst, src, ELFDATA2MSB) == NULL) exit (7); + if (val != 0x7fff0000000) + exit (42); + elf_end (elf); + exit (0); + } + } + exit (8); +} + ],,[AC_MSG_ERROR([libelf does not properly convert Elf64_Sxword quantities. +If you are using libelf-0.7.0, please use patches/libelf-0.7.0.patch.])], +[AC_MSG_WARN([Could not test whether libelf properly converts Elf64_Sxword quantities. +If you are using libelf-0.7.0 and your libelf is buggy, please use +patches/libelf-0.7.0.patch.])]) + ]) diff --git a/trunk/missing b/trunk/missing new file mode 100755 index 0000000..dd58370 --- /dev/null +++ b/trunk/missing @@ -0,0 +1,336 @@ +#! /bin/sh +# Common stub for a few missing GNU programs while installing. +# Copyright 1996, 1997, 1999, 2000 Free Software Foundation, Inc. +# Originally by Fran,cois Pinard <pinard@iro.umontreal.ca>, 1996. + +# 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, 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., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +# As a special exception to the GNU General Public License, if you +# distribute this file as part of a program that contains a +# configuration script generated by Autoconf, you may include it under +# the same distribution terms that you use for the rest of that program. + +if test $# -eq 0; then + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 +fi + +run=: + +# In the cases where this matters, `missing' is being run in the +# srcdir already. +if test -f configure.ac; then + configure_ac=configure.ac +else + configure_ac=configure.in +fi + +case "$1" in +--run) + # Try to run requested program, and just exit if it succeeds. + run= + shift + "$@" && exit 0 + ;; +esac + +# If it does not exist, or fails to run (possibly an outdated version), +# try to emulate it. +case "$1" in + + -h|--h|--he|--hel|--help) + echo "\ +$0 [OPTION]... PROGRAM [ARGUMENT]... + +Handle \`PROGRAM [ARGUMENT]...' for when PROGRAM is missing, or return an +error status if there is no known handling for PROGRAM. + +Options: + -h, --help display this help and exit + -v, --version output version information and exit + --run try to run the given command, and emulate it if it fails + +Supported PROGRAM values: + aclocal touch file \`aclocal.m4' + autoconf touch file \`configure' + autoheader touch file \`config.h.in' + automake touch all \`Makefile.in' files + bison create \`y.tab.[ch]', if possible, from existing .[ch] + flex create \`lex.yy.c', if possible, from existing .c + help2man touch the output file + lex create \`lex.yy.c', if possible, from existing .c + makeinfo touch the output file + tar try tar, gnutar, gtar, then tar without non-portable flags + yacc create \`y.tab.[ch]', if possible, from existing .[ch]" + ;; + + -v|--v|--ve|--ver|--vers|--versi|--versio|--version) + echo "missing 0.4 - GNU automake" + ;; + + -*) + echo 1>&2 "$0: Unknown \`$1' option" + echo 1>&2 "Try \`$0 --help' for more information" + exit 1 + ;; + + aclocal*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acinclude.m4' or \`${configure_ac}'. You might want + to install the \`Automake' and \`Perl' packages. Grab them from + any GNU archive site." + touch aclocal.m4 + ;; + + autoconf) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`${configure_ac}'. You might want to install the + \`Autoconf' and \`GNU m4' packages. Grab them from any GNU + archive site." + touch configure + ;; + + autoheader) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`acconfig.h' or \`${configure_ac}'. You might want + to install the \`Autoconf' and \`GNU m4' packages. Grab them + from any GNU archive site." + files=`sed -n 's/^[ ]*A[CM]_CONFIG_HEADER(\([^)]*\)).*/\1/p' ${configure_ac}` + test -z "$files" && files="config.h" + touch_files= + for f in $files; do + case "$f" in + *:*) touch_files="$touch_files "`echo "$f" | + sed -e 's/^[^:]*://' -e 's/:.*//'`;; + *) touch_files="$touch_files $f.in";; + esac + done + touch $touch_files + ;; + + automake*) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified \`Makefile.am', \`acinclude.m4' or \`${configure_ac}'. + You might want to install the \`Automake' and \`Perl' packages. + Grab them from any GNU archive site." + find . -type f -name Makefile.am -print | + sed 's/\.am$/.in/' | + while read f; do touch "$f"; done + ;; + + autom4te) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. + You can get \`$1Help2man' as part of \`Autoconf' from any GNU + archive site." + + file=`echo "$*" | sed -n 's/.*--output[ =]*\([^ ]*\).*/\1/p'` + test -z "$file" && file=`echo "$*" | sed -n 's/.*-o[ ]*\([^ ]*\).*/\1/p'` + if test -f "$file"; then + touch $file + else + test -z "$file" || exec >$file + echo "#! /bin/sh" + echo "# Created by GNU Automake missing as a replacement of" + echo "# $ $@" + echo "exit 0" + chmod +x $file + exit 1 + fi + ;; + + bison|yacc) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.y' file. You may need the \`Bison' package + in order for those modifications to take effect. You can get + \`Bison' from any GNU archive site." + rm -f y.tab.c y.tab.h + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.y) + SRCFILE=`echo "$LASTARG" | sed 's/y$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.c + fi + SRCFILE=`echo "$LASTARG" | sed 's/y$/h/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" y.tab.h + fi + ;; + esac + fi + if [ ! -f y.tab.h ]; then + echo >y.tab.h + fi + if [ ! -f y.tab.c ]; then + echo 'main() { return 0; }' >y.tab.c + fi + ;; + + lex|flex) + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.l' file. You may need the \`Flex' package + in order for those modifications to take effect. You can get + \`Flex' from any GNU archive site." + rm -f lex.yy.c + if [ $# -ne 1 ]; then + eval LASTARG="\${$#}" + case "$LASTARG" in + *.l) + SRCFILE=`echo "$LASTARG" | sed 's/l$/c/'` + if [ -f "$SRCFILE" ]; then + cp "$SRCFILE" lex.yy.c + fi + ;; + esac + fi + if [ ! -f lex.yy.c ]; then + echo 'main() { return 0; }' >lex.yy.c + fi + ;; + + help2man) + if test -z "$run" && ($1 --version) > /dev/null 2>&1; then + # We have it, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a dependency of a manual page. You may need the + \`Help2man' package in order for those modifications to take + effect. You can get \`Help2man' from any GNU archive site." + + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed -n 's/.*--output=\([^ ]*\).*/\1/p'` + fi + if [ -f "$file" ]; then + touch $file + else + test -z "$file" || exec >$file + echo ".ab help2man is required to generate this page" + exit 1 + fi + ;; + + makeinfo) + if test -z "$run" && (makeinfo --version) > /dev/null 2>&1; then + # We have makeinfo, but it failed. + exit 1 + fi + + echo 1>&2 "\ +WARNING: \`$1' is missing on your system. You should only need it if + you modified a \`.texi' or \`.texinfo' file, or any other file + indirectly affecting the aspect of the manual. The spurious + call might also be the consequence of using a buggy \`make' (AIX, + DU, IRIX). You might want to install the \`Texinfo' package or + the \`GNU make' package. Grab either from any GNU archive site." + file=`echo "$*" | sed -n 's/.*-o \([^ ]*\).*/\1/p'` + if test -z "$file"; then + file=`echo "$*" | sed 's/.* \([^ ]*\) *$/\1/'` + file=`sed -n '/^@setfilename/ { s/.* \([^ ]*\) *$/\1/; p; q; }' $file` + fi + touch $file + ;; + + tar) + shift + if test -n "$run"; then + echo 1>&2 "ERROR: \`tar' requires --run" + exit 1 + fi + + # We have already tried tar in the generic part. + # Look for gnutar/gtar before invocation to avoid ugly error + # messages. + if (gnutar --version > /dev/null 2>&1); then + gnutar ${1+"$@"} && exit 0 + fi + if (gtar --version > /dev/null 2>&1); then + gtar ${1+"$@"} && exit 0 + fi + firstarg="$1" + if shift; then + case "$firstarg" in + *o*) + firstarg=`echo "$firstarg" | sed s/o//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + case "$firstarg" in + *h*) + firstarg=`echo "$firstarg" | sed s/h//` + tar "$firstarg" ${1+"$@"} && exit 0 + ;; + esac + fi + + echo 1>&2 "\ +WARNING: I can't seem to be able to run \`tar' with the given arguments. + You may want to install GNU tar or Free paxutils, or check the + command line arguments." + exit 1 + ;; + + *) + echo 1>&2 "\ +WARNING: \`$1' is needed, and you do not seem to have it handy on your + system. You might have modified some files without having the + proper tools for further handling them. Check the \`README' file, + it often tells you about the needed prerequirements for installing + this package. You may also peek at any GNU archive site, in case + some other package would contain this missing \`$1' program." + exit 1 + ;; +esac + +exit 0 diff --git a/trunk/mkinstalldirs b/trunk/mkinstalldirs new file mode 100755 index 0000000..f9c37af --- /dev/null +++ b/trunk/mkinstalldirs @@ -0,0 +1,101 @@ +#! /bin/sh +# mkinstalldirs --- make directory hierarchy +# Author: Noah Friedman <friedman@prep.ai.mit.edu> +# Created: 1993-05-16 +# Public domain + +# $Id: mkinstalldirs,v 1.13 1999/01/05 03:18:55 bje Exp $ + +errstatus=0 +dirmode="" + +usage="\ +Usage: mkinstalldirs [-h] [--help] [-m mode] dir ..." + +# process command line arguments +while test $# -gt 0 ; do + case "${1}" in + -h | --help | --h* ) # -h for help + echo "${usage}" 1>&2; exit 0 ;; + -m ) # -m PERM arg + shift + test $# -eq 0 && { echo "${usage}" 1>&2; exit 1; } + dirmode="${1}" + shift ;; + -- ) shift; break ;; # stop option processing + -* ) echo "${usage}" 1>&2; exit 1 ;; # unknown option + * ) break ;; # first non-opt arg + esac +done + +for file +do + if test -d "$file"; then + shift + else + break + fi +done + +case $# in +0) exit 0 ;; +esac + +case $dirmode in +'') + if mkdir -p -- . 2>/dev/null; then + echo "mkdir -p -- $*" + exec mkdir -p -- "$@" + fi ;; +*) + if mkdir -m "$dirmode" -p -- . 2>/dev/null; then + echo "mkdir -m $dirmode -p -- $*" + exec mkdir -m "$dirmode" -p -- "$@" + fi ;; +esac + +for file +do + set fnord `echo ":$file" | sed -ne 's/^:\//#/;s/^://;s/\// /g;s/^#/\//;p'` + shift + + pathcomp= + for d + do + pathcomp="$pathcomp$d" + case "$pathcomp" in + -* ) pathcomp=./$pathcomp ;; + esac + + if test ! -d "$pathcomp"; then + echo "mkdir $pathcomp" + + mkdir "$pathcomp" || lasterr=$? + + if test ! -d "$pathcomp"; then + errstatus=$lasterr + else + if test ! -z "$dirmode"; then + echo "chmod $dirmode $pathcomp" + + lasterr="" + chmod "$dirmode" "$pathcomp" || lasterr=$? + + if test ! -z "$lasterr"; then + errstatus=$lasterr + fi + fi + fi + fi + + pathcomp="$pathcomp/" + done +done + +exit $errstatus + +# Local Variables: +# mode: shell-script +# sh-indentation: 3 +# End: +# mkinstalldirs ends here diff --git a/trunk/patches/Makefile.am b/trunk/patches/Makefile.am new file mode 100644 index 0000000..efe5d40 --- /dev/null +++ b/trunk/patches/Makefile.am @@ -0,0 +1,5 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +EXTRA_DIST = libelf-0.7.0.patch libelf-0.7.0-hash.patch linux-2.4.10.patch diff --git a/trunk/patches/Makefile.in b/trunk/patches/Makefile.in new file mode 100644 index 0000000..8412943 --- /dev/null +++ b/trunk/patches/Makefile.in @@ -0,0 +1,231 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +EXTRA_DIST = libelf-0.7.0.patch libelf-0.7.0-hash.patch linux-2.4.10.patch +subdir = patches +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu patches/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +tags: TAGS +TAGS: + +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-am clean clean-generic clean-libtool \ + distclean distclean-generic distclean-libtool distdir dvi \ + dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool uninstall uninstall-am uninstall-info-am + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/patches/libelf-0.7.0-hash.patch b/trunk/patches/libelf-0.7.0-hash.patch new file mode 100644 index 0000000..7fcf7f3 --- /dev/null +++ b/trunk/patches/libelf-0.7.0-hash.patch @@ -0,0 +1,20 @@ +2002-06-14 Jakub Jelinek <jakub@redhat.com> + + * update.c (_elf64_layout): Don't overwrite sh_entsize + unconditionally for ELF64 - some platforms use + 64 bit DT_HASH entries. + +--- libelf-0.7.0/lib/update.c.jj Fri Jun 12 15:42:39 1998 ++++ libelf-0.7.0/lib/update.c Fri Jun 14 10:22:19 2002 +@@ -317,7 +317,10 @@ _elf64_layout(Elf *elf, unsigned *flag) + + entsize = scn_entsize(elf, version, shdr->sh_type); + if (entsize > 1) { +- rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags); ++ /* Some architectures use 64-bit hash entries. */ ++ if (shdr->sh_type != SHT_HASH ++ || shdr->sh_entsize != _fsize(elf->e_class, version, ELF_T_ADDR)) ++ rewrite(shdr->sh_entsize, entsize, scn->s_shdr_flags); + } + + if (layout) { diff --git a/trunk/patches/libelf-0.7.0.patch b/trunk/patches/libelf-0.7.0.patch new file mode 100644 index 0000000..1e9e57a --- /dev/null +++ b/trunk/patches/libelf-0.7.0.patch @@ -0,0 +1,16 @@ +2001-09-26 Jakub Jelinek <jakub@redhat.com> + + * lib/64.xlatetof.c (__load_i64M): Don't blow away upper 32 bits + if 31th bit is set. + +--- libelf-0.7.0/lib/64.xlatetof.c.jj Tue Aug 25 17:22:24 1998 ++++ libelf-0.7.0/lib/64.xlatetof.c Wed Sep 26 15:00:18 2001 +@@ -42,7 +42,7 @@ __load_i64L(const unsigned char *from) { + + static __libelf_i64_t + __load_i64M(const unsigned char *from) { +- return ((__libelf_u64_t)__load_u32M(from) << 32) | (__libelf_i64_t)__load_i32M(from + 4); ++ return ((__libelf_i64_t)__load_i32M(from) << 32) | (__libelf_u64_t)__load_u32M(from + 4); + } + + static void diff --git a/trunk/patches/linux-2.4.10.patch b/trunk/patches/linux-2.4.10.patch new file mode 100644 index 0000000..dbd6702 --- /dev/null +++ b/trunk/patches/linux-2.4.10.patch @@ -0,0 +1,50 @@ +--- linux/fs/binfmt_elf.c.jj Thu Sep 6 16:12:04 2001 ++++ linux/fs/binfmt_elf.c Mon Oct 1 08:22:06 2001 +@@ -400,7 +400,6 @@ static int load_elf_binary(struct linux_ + int load_addr_set = 0; + char * elf_interpreter = NULL; + unsigned int interpreter_type = INTERPRETER_NONE; +- mm_segment_t old_fs; + unsigned long error; + struct elf_phdr * elf_ppnt, *elf_phdata; + unsigned long elf_bss, k, elf_brk; +@@ -574,8 +573,6 @@ static int load_elf_binary(struct linux_ + the image should be loaded at fixed address, not at a variable + address. */ + +- old_fs = get_fs(); +- set_fs(get_ds()); + for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) { + int elf_prot = 0, elf_flags; + unsigned long vaddr; +@@ -583,6 +580,22 @@ static int load_elf_binary(struct linux_ + if (elf_ppnt->p_type != PT_LOAD) + continue; + ++ if (unlikely (elf_brk > elf_bss)) { ++ unsigned long nbyte; ++ ++ /* There was a PT_LOAD segment with p_memsz > p_filesz ++ before this one. Map anonymous pages, if needed, ++ and clear the area. */ ++ set_brk (elf_bss + load_bias, elf_brk + load_bias); ++ nbyte = ELF_PAGEOFFSET(elf_bss); ++ if (nbyte) { ++ nbyte = ELF_MIN_ALIGN - nbyte; ++ if (nbyte > elf_brk - elf_bss) ++ nbyte = elf_brk - elf_bss; ++ clear_user((void *) elf_bss + elf_bias, nbyte); ++ } ++ } ++ + if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ; + if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE; + if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC; +@@ -626,7 +639,6 @@ static int load_elf_binary(struct linux_ + if (k > elf_brk) + elf_brk = k; + } +- set_fs(old_fs); + + elf_entry += load_bias; + elf_bss += load_bias; diff --git a/trunk/src/Makefile.am b/trunk/src/Makefile.am new file mode 100644 index 0000000..6981801 --- /dev/null +++ b/trunk/src/Makefile.am @@ -0,0 +1,34 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall +AM_CPPFLAGS = -DSBINDIR='"@sbindir@"' -DBINDIR='"@bindir@"' +INCLUDES = @GELFINCLUDE@ + +sbin_PROGRAMS = prelink prelink-rtld +bin_PROGRAMS = execstack + +arch_SOURCES = arch-i386.c arch-alpha.c arch-ppc.c arch-ppc64.c \ + arch-sparc.c arch-sparc64.c arch-x86_64.c arch-mips.c \ + arch-s390.c arch-s390x.c arch-arm.c arch-sh.c arch-ia64.c +common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \ + hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c \ + wrap-file.c canonicalize.c +prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \ + gather.c layout.c main.c prelink.c \ + prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \ + verify.c md5.c md5.h sha.c sha.h \ + $(common_SOURCES) $(arch_SOURCES) +prelink_LDADD = @LIBGELF@ -liberty +prelink_LDFLAGS = -all-static + +execstack_SOURCES = execstack.c $(common_SOURCES) $(arch_SOURCES) + +prelink_rtld_LDADD = @LIBGELF@ -liberty +prelink_rtld_SOURCES = data.c dso-readonly.c ld-libs.c ld-lookup.c \ + canonicalize.c wrap-file.c ld-lookup64.c +prelink_rtld_LDFLAGS = -all-static + +extra_DIST = makecrc.c diff --git a/trunk/src/Makefile.in b/trunk/src/Makefile.in new file mode 100644 index 0000000..7dbe941 --- /dev/null +++ b/trunk/src/Makefile.in @@ -0,0 +1,500 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall +AM_CPPFLAGS = -DSBINDIR='"@sbindir@"' +INCLUDES = @GELFINCLUDE@ + +sbin_PROGRAMS = prelink +bin_PROGRAMS = execstack + +arch_SOURCES = arch-i386.c arch-alpha.c arch-ppc.c arch-ppc64.c \ + arch-sparc.c arch-sparc64.c arch-x86_64.c arch-mips.c \ + arch-s390.c arch-s390x.c arch-arm.c arch-sh.c arch-ia64.c + +common_SOURCES = checksum.c data.c dso.c dwarf2.c dwarf2.h fptr.c fptr.h \ + hashtab.c hashtab.h mdebug.c prelink.h stabs.c crc32.c + +prelink_SOURCES = cache.c conflict.c cxx.c doit.c exec.c execle_open.c get.c \ + gather.c layout.c main.c prelink.c \ + prelinktab.h reloc.c reloc.h space.c undo.c undoall.c \ + verify.c canonicalize.c md5.c md5.h sha.c sha.h \ + $(common_SOURCES) $(arch_SOURCES) + +prelink_LDADD = @LIBGELF@ +prelink_LDFLAGS = -all-static + +execstack_SOURCES = execstack.c $(common_SOURCES) $(arch_SOURCES) + +extra_DIST = makecrc.c +subdir = src +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +bin_PROGRAMS = execstack$(EXEEXT) +sbin_PROGRAMS = prelink$(EXEEXT) +PROGRAMS = $(bin_PROGRAMS) $(sbin_PROGRAMS) + +am__objects_1 = checksum.$(OBJEXT) data.$(OBJEXT) dso.$(OBJEXT) \ + dwarf2.$(OBJEXT) fptr.$(OBJEXT) hashtab.$(OBJEXT) \ + mdebug.$(OBJEXT) stabs.$(OBJEXT) crc32.$(OBJEXT) +am__objects_2 = arch-i386.$(OBJEXT) arch-alpha.$(OBJEXT) \ + arch-ppc.$(OBJEXT) arch-ppc64.$(OBJEXT) arch-sparc.$(OBJEXT) \ + arch-sparc64.$(OBJEXT) arch-x86_64.$(OBJEXT) \ + arch-mips.$(OBJEXT) arch-s390.$(OBJEXT) arch-s390x.$(OBJEXT) \ + arch-arm.$(OBJEXT) arch-sh.$(OBJEXT) arch-ia64.$(OBJEXT) +am_execstack_OBJECTS = execstack.$(OBJEXT) $(am__objects_1) \ + $(am__objects_2) +execstack_OBJECTS = $(am_execstack_OBJECTS) +execstack_LDADD = $(LDADD) +execstack_DEPENDENCIES = +execstack_LDFLAGS = +am_prelink_OBJECTS = cache.$(OBJEXT) conflict.$(OBJEXT) cxx.$(OBJEXT) \ + doit.$(OBJEXT) exec.$(OBJEXT) execle_open.$(OBJEXT) \ + get.$(OBJEXT) gather.$(OBJEXT) layout.$(OBJEXT) main.$(OBJEXT) \ + prelink.$(OBJEXT) reloc.$(OBJEXT) space.$(OBJEXT) \ + undo.$(OBJEXT) undoall.$(OBJEXT) verify.$(OBJEXT) \ + canonicalize.$(OBJEXT) md5.$(OBJEXT) sha.$(OBJEXT) \ + $(am__objects_1) $(am__objects_2) +prelink_OBJECTS = $(am_prelink_OBJECTS) +prelink_DEPENDENCIES = +DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/arch-alpha.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-arm.Po ./$(DEPDIR)/arch-i386.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-ia64.Po ./$(DEPDIR)/arch-mips.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-ppc.Po ./$(DEPDIR)/arch-ppc64.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-s390.Po ./$(DEPDIR)/arch-s390x.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-sh.Po ./$(DEPDIR)/arch-sparc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-sparc64.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/arch-x86_64.Po ./$(DEPDIR)/cache.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/canonicalize.Po ./$(DEPDIR)/checksum.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/conflict.Po ./$(DEPDIR)/crc32.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/cxx.Po ./$(DEPDIR)/data.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/doit.Po ./$(DEPDIR)/dso.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/dwarf2.Po ./$(DEPDIR)/exec.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/execle_open.Po ./$(DEPDIR)/execstack.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/fptr.Po ./$(DEPDIR)/gather.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/get.Po ./$(DEPDIR)/hashtab.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/layout.Po ./$(DEPDIR)/main.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/md5.Po ./$(DEPDIR)/mdebug.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/prelink.Po ./$(DEPDIR)/reloc.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/sha.Po ./$(DEPDIR)/space.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/stabs.Po ./$(DEPDIR)/undo.Po \ +@AMDEP_TRUE@ ./$(DEPDIR)/undoall.Po ./$(DEPDIR)/verify.Po +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \ + $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +CFLAGS = @CFLAGS@ +DIST_SOURCES = $(execstack_SOURCES) $(prelink_SOURCES) +DIST_COMMON = Makefile.am Makefile.in +SOURCES = $(execstack_SOURCES) $(prelink_SOURCES) + +all: all-am + +.SUFFIXES: +.SUFFIXES: .c .lo .o .obj +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu src/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) +binPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(bindir) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(binPROGRAMS_INSTALL) $$p $(DESTDIR)$(bindir)/$$f; \ + else :; fi; \ + done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(bindir)/$$f"; \ + rm -f $(DESTDIR)$(bindir)/$$f; \ + done + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + if test -f $$p \ + || test -f $$p1 \ + ; then \ + f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) $$p $(DESTDIR)$(sbindir)/$$f; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \ + echo " rm -f $(DESTDIR)$(sbindir)/$$f"; \ + rm -f $(DESTDIR)$(sbindir)/$$f; \ + done + +clean-sbinPROGRAMS: + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f $$p $$f"; \ + rm -f $$p $$f ; \ + done +execstack$(EXEEXT): $(execstack_OBJECTS) $(execstack_DEPENDENCIES) + @rm -f execstack$(EXEEXT) + $(LINK) $(execstack_LDFLAGS) $(execstack_OBJECTS) $(execstack_LDADD) $(LIBS) +prelink$(EXEEXT): $(prelink_OBJECTS) $(prelink_DEPENDENCIES) + @rm -f prelink$(EXEEXT) + $(LINK) $(prelink_LDFLAGS) $(prelink_OBJECTS) $(prelink_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) core *.core + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-alpha.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-arm.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-i386.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-ia64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-mips.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-ppc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-ppc64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-s390.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-s390x.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-sh.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-sparc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-sparc64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arch-x86_64.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cache.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/canonicalize.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/checksum.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/conflict.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/crc32.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/cxx.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/data.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/doit.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dso.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dwarf2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/exec.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execle_open.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/execstack.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/fptr.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gather.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/get.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hashtab.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/layout.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/md5.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mdebug.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prelink.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/reloc.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/sha.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/space.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/stabs.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/undo.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/undoall.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/verify.Po@am__quote@ + +distclean-depend: + -rm -rf ./$(DEPDIR) + +.c.o: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$< + +.c.obj: +@AMDEP_TRUE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(COMPILE) -c `cygpath -w $<` + +.c.lo: +@AMDEP_TRUE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@ +@AMDEP_TRUE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ + $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$< +CCDEPMODE = @CCDEPMODE@ + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: + +ETAGS = etags +ETAGSFLAGS = + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES) + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + mkid -fID $$unique + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \ + unique=`for i in $$list; do \ + if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ + done | \ + $(AWK) ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$tags$$unique" \ + || $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$tags $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && cd $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) $$here + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) + +installdirs: + $(mkinstalldirs) $(DESTDIR)$(bindir) $(DESTDIR)$(sbindir) + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool \ + clean-sbinPROGRAMS mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-compile distclean-depend \ + distclean-generic distclean-libtool distclean-tags + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: install-binPROGRAMS install-sbinPROGRAMS + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +uninstall-am: uninstall-binPROGRAMS uninstall-info-am \ + uninstall-sbinPROGRAMS + +.PHONY: GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool clean-sbinPROGRAMS distclean \ + distclean-compile distclean-depend distclean-generic \ + distclean-libtool distclean-tags distdir dvi dvi-am info \ + info-am install install-am install-binPROGRAMS install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-sbinPROGRAMS install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool tags uninstall \ + uninstall-am uninstall-binPROGRAMS uninstall-info-am \ + uninstall-sbinPROGRAMS + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/src/arch-alpha.c b/trunk/src/arch-alpha.c new file mode 100644 index 0000000..51182ed --- /dev/null +++ b/trunk/src/arch-alpha.c @@ -0,0 +1,497 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +alpha_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + return 0; +} + +static int +alpha_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: Alpha doesn't support REL relocs", dso->filename); + return 1; +} + +static int +alpha_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (GELF_R_TYPE (rela->r_info) == R_ALPHA_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_ALPHA_JMP_SLOT) + { + GElf_Addr val = read_ule64 (dso, rela->r_offset); + + if (val >= start) + { + write_le64 (dso, rela->r_offset, val + adjust); + if (val == rela->r_addend) + rela->r_addend += adjust; + } + } + else if (GELF_R_TYPE (rela->r_info) == R_ALPHA_GLOB_DAT) + { + GElf_Addr val = read_ule64 (dso, rela->r_offset) - rela->r_addend; + + if (val && val >= start) + write_le64 (dso, rela->r_offset, val + adjust + rela->r_addend); + } + return 0; +} + +static int +alpha_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: Alpha doesn't support REL relocs", info->dso->filename); + return 1; +} + +static void +alpha_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr, + GElf_Addr value) +{ + Elf64_Sxword disp; + Elf64_Addr plt; + + relaaddr -= dso->info[DT_JMPREL]; + relaaddr /= sizeof (Elf64_Rela); + relaaddr *= 12; + plt = dso->info[DT_PLTGOT] + 32 + relaaddr; + disp = ((Elf64_Sxword) (value - plt - 12)) / 4; + if (disp >= -0x100000 && disp < 0x100000) + { + int32_t hi, lo; + + hi = value - plt; + lo = (int16_t) hi; + hi = (hi - lo) >> 16; + + /* ldah $27,hi($27) + lda $27,lo($27) + br $31,value */ + write_le32 (dso, plt, 0x277b0000 | (hi & 0xffff)); + write_le32 (dso, plt + 4, 0x237b0000 | (lo & 0xffff)); + write_le32 (dso, plt + 8, 0xc3e00000 | (disp & 0x1fffff)); + } + else + { + int32_t hi, lo; + + hi = rela->r_offset - plt; + lo = (int16_t) hi; + hi = (hi - lo) >> 16; + + /* ldah $27,hi($27) + ldq $27,lo($27) + jmp $31,($27) */ + write_le32 (dso, plt, 0x277b0000 | (hi & 0xffff)); + write_le32 (dso, plt + 4, 0xa77b0000 | (lo & 0xffff)); + write_le32 (dso, plt + 8, 0x6bfb0000); + } +} + +static int +alpha_is_indirect_plt (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + Elf64_Addr pltaddr; + uint32_t plt[3]; + int32_t hi, lo; + + relaaddr -= dso->info[DT_JMPREL]; + relaaddr /= sizeof (Elf64_Rela); + relaaddr *= 12; + pltaddr = dso->info[DT_PLTGOT] + 32 + relaaddr; + hi = rela->r_offset - pltaddr; + lo = (int16_t) hi; + hi = (hi - lo) >> 16; + plt[0] = read_ule32 (dso, pltaddr); + plt[1] = read_ule32 (dso, pltaddr + 4); + plt[2] = read_ule32 (dso, pltaddr + 8); + if (plt[0] == (0x277b0000 | (hi & 0xffff)) + && plt[1] == (0xa77b0000 | (lo & 0xffff)) + && plt[2] == 0x6bfb0000) + return 1; + return 0; +} + +static int +alpha_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_ALPHA_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_ALPHA_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ALPHA_GLOB_DAT: + case R_ALPHA_REFQUAD: + case R_ALPHA_DTPREL64: + write_le64 (dso, rela->r_offset, value); + break; + case R_ALPHA_JMP_SLOT: + write_le64 (dso, rela->r_offset, value); + alpha_fixup_plt (dso, rela, relaaddr, value); + break; + /* DTPMOD64 and TPREL64 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_ALPHA_DTPMOD64: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_ALPHA_DTPMOD64 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_ALPHA_TPREL64: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_le64 (dso, rela->r_offset, value + info->resolvetls->offset); + break; + default: + error (0, 0, "%s: Unknown alpha relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +alpha_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info) & 0xff) + { + case R_ALPHA_GLOB_DAT: + case R_ALPHA_REFQUAD: + case R_ALPHA_JMP_SLOT: + buf_write_le64 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +alpha_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: Alpha doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +alpha_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ALPHA_NONE: + break; + case R_ALPHA_GLOB_DAT: + case R_ALPHA_REFQUAD: + case R_ALPHA_JMP_SLOT: + buf_write_le64 (buf, value + rela->r_addend); + break; + case R_ALPHA_RELATIVE: + error (0, 0, "%s: R_ALPHA_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +alpha_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: Alpha doesn't support REL relocs", dso->filename); + return 1; +} + +static int +alpha_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_ALPHA_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_ALPHA_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD64 and TPREL64 relocs need conflicts. */ + case R_ALPHA_DTPMOD64: + case R_ALPHA_TPREL64: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPREL64 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_ALPHA_DTPREL64 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ALPHA_GLOB_DAT: + case R_ALPHA_REFQUAD: + ret->r_addend = value + rela->r_addend; + break; + case R_ALPHA_JMP_SLOT: + ret->r_addend = value + rela->r_addend; + if (alpha_is_indirect_plt (dso, rela, relaaddr)) + ret->r_info = GELF_R_INFO (0, R_ALPHA_GLOB_DAT); + else + { + relaaddr -= dso->info[DT_JMPREL]; + relaaddr /= sizeof (Elf64_Rela); + if (relaaddr > 0xffffff) + { + error (0, 0, "%s: Cannot create R_ALPHA_JMP_SLOT conflict against .rel.plt with more than 16M entries", + dso->filename); + return 1; + } + ret->r_info = GELF_R_INFO (0, (relaaddr << 8) | R_ALPHA_JMP_SLOT); + } + break; + case R_ALPHA_DTPMOD64: + case R_ALPHA_DTPREL64: + case R_ALPHA_TPREL64: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_ALPHA_GLOB_DAT); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ALPHA_DTPMOD64: + ret->r_addend = tls->modid; + break; + case R_ALPHA_DTPREL64: + ret->r_addend = value + rela->r_addend; + break; + case R_ALPHA_TPREL64: + ret->r_addend = value + rela->r_addend + tls->offset; + break; + } + break; + default: + error (0, 0, "%s: Unknown Alpha relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +alpha_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: Alpha doesn't support REL relocs", dso->filename); + return 1; +} + +static int +alpha_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +alpha_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + + /* Correct sh_entsize on .plt sections. */ + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT] + 16); + assert (sec != -1); + if (dso->shdr[sec].sh_type == SHT_PROGBITS + && dso->shdr[sec].sh_entsize == 32) + dso->shdr[sec].sh_entsize = 0; + } + return 0; +} + +static int +alpha_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + Elf_Scn *scn; + Elf_Data *data; + GElf_Sym sym; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ALPHA_NONE: + case R_ALPHA_RELATIVE: + break; + case R_ALPHA_JMP_SLOT: + relaaddr -= dso->info[DT_JMPREL]; + relaaddr /= sizeof (Elf64_Rela); + relaaddr *= 12; + relaaddr += dso->info[DT_PLTGOT] + 32; + /* br at,.plt */ + write_le32 (dso, relaaddr, + 0xc39fffff - (relaaddr - dso->info[DT_PLTGOT]) / 4); + write_le64 (dso, relaaddr + 4, 0); + write_le64 (dso, rela->r_offset, relaaddr); + break; + case R_ALPHA_GLOB_DAT: + /* This is ugly. Linker doesn't clear memory at r_offset of GLOB_DAT + reloc, but instead puts in sym.st_value + addend. */ + sec = addr_to_sec (dso, relaaddr); + assert (sec != -1); + sec = dso->shdr[sec].sh_link; + assert (sec > 0 && sec < dso->ehdr.e_shnum); + scn = dso->scn[sec]; + data = elf_getdata (scn, NULL); + assert (data != NULL && elf_getdata (scn, data) == NULL); + assert (GELF_R_SYM (rela->r_info) + <= dso->shdr[sec].sh_size / sizeof (Elf64_Sym)); + gelfx_getsym (dso->elf, data, GELF_R_SYM (rela->r_info), &sym); + write_le64 (dso, rela->r_offset, sym.st_value + rela->r_addend); + break; + case R_ALPHA_REFQUAD: + case R_ALPHA_DTPMOD64: + case R_ALPHA_DTPREL64: + case R_ALPHA_TPREL64: + write_le64 (dso, rela->r_offset, 0); + break; + default: + error (0, 0, "%s: Unknown alpha relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +alpha_reloc_size (int reloc_type) +{ + return 8; +} + +static int +alpha_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_ALPHA_JMP_SLOT: + return RTYPE_CLASS_PLT; + case R_ALPHA_DTPMOD64: + case R_ALPHA_DTPREL64: + case R_ALPHA_TPREL64: + return RTYPE_CLASS_TLS; + default: + return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "Alpha", + .class = ELFCLASS64, + .machine = EM_ALPHA, + .alternate_machine = { EM_FAKE_ALPHA }, + .R_JMP_SLOT = R_ALPHA_JMP_SLOT, + .R_COPY = -1, + .R_RELATIVE = R_ALPHA_RELATIVE, + .dynamic_linker = "/lib/ld-linux.so.2", + .adjust_dyn = alpha_adjust_dyn, + .adjust_rel = alpha_adjust_rel, + .adjust_rela = alpha_adjust_rela, + .prelink_rel = alpha_prelink_rel, + .prelink_rela = alpha_prelink_rela, + .prelink_conflict_rel = alpha_prelink_conflict_rel, + .prelink_conflict_rela = alpha_prelink_conflict_rela, + .apply_conflict_rela = alpha_apply_conflict_rela, + .apply_rel = alpha_apply_rel, + .apply_rela = alpha_apply_rela, + .rel_to_rela = alpha_rel_to_rela, + .need_rel_to_rela = alpha_need_rel_to_rela, + .reloc_size = alpha_reloc_size, + .reloc_class = alpha_reloc_class, + .max_reloc_size = 8, + .arch_prelink = alpha_arch_prelink, + .undo_prelink_rela = alpha_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x0000020000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x0000020001000000LL, + .mmap_end = 0x0000020100000000LL, + .max_page_size = 0x10000, + .page_size = 0x02000 +}; diff --git a/trunk/src/arch-arm.c b/trunk/src/arch-arm.c new file mode 100644 index 0000000..12b8f3d --- /dev/null +++ b/trunk/src/arch-arm.c @@ -0,0 +1,856 @@ +/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +#ifndef R_ARM_TLS_DTPMOD32 +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#endif + +static int +arm_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf32_Addr data; + + if (sec == -1) + return 0; + + data = read_une32 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_ne32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_une32 (dso, dyn->d_un.d_ptr + 4); + /* If .got.plt[1] points to .plt, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_ne32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + break; + } + } + } + return 0; +} + +static int +arm_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_RELATIVE: + case R_ARM_JUMP_SLOT: + data = read_une32 (dso, rel->r_offset); + if (data >= start) + write_ne32 (dso, rel->r_offset, data + adjust); + break; + } + return 0; +} + +static int +arm_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_RELATIVE: + if ((Elf32_Addr) rela->r_addend >= start) + { + rela->r_addend += (Elf32_Sword) adjust; + /* Write it to the memory location as well. + Not necessary, but we can do it. */ + write_ne32 (dso, rela->r_offset, rela->r_addend); + } + break; + case R_ARM_JUMP_SLOT: + data = read_une32 (dso, rela->r_offset); + if (data >= start) + write_ne32 (dso, rela->r_offset, data + adjust); + break; + break; + } + return 0; +} + +static int +arm_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + DSO *dso; + GElf_Addr value; + + if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE + || GELF_R_TYPE (rel->r_info) == R_ARM_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + write_ne32 (dso, rel->r_offset, value); + break; + case R_ARM_ABS32: + { + if (read_une32 (dso, rel->r_offset)) + { + error (0, 0, "%s: R_ARM_ABS32 relocs with non-zero addend should not be present in prelinked REL sections", + dso->filename); + return 1; + } + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_GLOB_DAT); + write_ne32 (dso, rel->r_offset, value); + /* Tell prelink_rel routine *rel has changed. */ + return 2; + } + case R_ARM_PC24: + error (0, 0, "%s: R_ARM_PC24 relocs with non-zero addend should not be present in prelinked REL sections", + dso->filename); + return 1; + case R_ARM_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); + return 1; + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rel->r_offset, value); + break; + /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_ARM_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_ARM_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC) + error (0, 0, "%s: R_ARM_TLS_TPOFF32 relocs should not be present in " + "prelinked ET_EXEC REL sections", + dso->filename); + break; + default: + error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +arm_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + Elf32_Sword val; + + if (GELF_R_TYPE (rela->r_info) == R_ARM_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_ARM_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + write_ne32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_ARM_ABS32: + write_ne32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_ARM_PC24: + val = value + rela->r_addend - rela->r_offset; + val >>= 2; + if ((Elf32_Word) val + 0x800000 >= 0x1000000) + { + error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename); + return 1; + } + val &= 0xffffff; + write_ne32 (dso, rela->r_offset, + (read_une32 (dso, rela->r_offset) & 0xff000000) | val); + break; + case R_ARM_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); + return 1; + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_ARM_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_ARM_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_ARM_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_ne32 (dso, rela->r_offset, + value + rela->r_addend + info->resolvetls->offset); + break; + default: + error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +arm_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + case R_ARM_ABS32: + buf_write_ne32 (info->dso, buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +arm_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + GElf_Addr value; + Elf32_Sword val; + + value = info->resolve (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_NONE: + break; + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + buf_write_ne32 (info->dso, buf, value); + break; + case R_ARM_ABS32: + buf_write_ne32 (info->dso, buf, value + read_une32 (info->dso, rel->r_offset)); + break; + case R_ARM_PC24: + val = value + rel->r_offset; + value = read_une32 (info->dso, rel->r_offset) << 8; + value = ((Elf32_Sword) value) >> 6; + val += value; + val >>= 2; + if ((Elf32_Word) val + 0x800000 >= 0x1000000) + { + error (0, 0, "%s: R_ARM_PC24 overflow", info->dso->filename); + return 1; + } + val &= 0xffffff; + buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val); + break; + case R_ARM_COPY: + abort (); + case R_ARM_RELATIVE: + error (0, 0, "%s: R_ARM_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +arm_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + Elf32_Sword val; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_NONE: + break; + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + case R_ARM_ABS32: + buf_write_ne32 (info->dso, buf, value + rela->r_addend); + break; + case R_ARM_PC24: + val = value + rela->r_addend - rela->r_offset; + val >>= 2; + if ((Elf32_Word) val + 0x800000 >= 0x1000000) + { + error (0, 0, "%s: R_ARM_PC24 overflow", info->dso->filename); + return 1; + } + val &= 0xffffff; + buf_write_ne32 (info->dso, buf, (buf_read_une32 (info->dso, buf) & 0xff000000) | val); + break; + case R_ARM_COPY: + abort (); + case R_ARM_RELATIVE: + error (0, 0, "%s: R_ARM_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +arm_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rel->r_info) == R_ARM_RELATIVE + || GELF_R_TYPE (rel->r_info) == R_ARM_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + + switch (GELF_R_TYPE (rel->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_TPOFF32: + break; + + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rel->r_info) == R_ARM_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rel->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + ret->r_addend = (Elf32_Sword) value; + break; + case R_ARM_ABS32: + case R_ARM_PC24: + error (0, 0, "%s: R_ARM_%s relocs should not be present in prelinked REL sections", + dso->filename, GELF_R_TYPE (rel->r_info) == R_ARM_ABS32 ? "ABS32" : "PC24"); + return 1; + case R_ARM_COPY: + error (0, 0, "R_ARM_COPY should not be present in shared libraries"); + return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_ARM_TLS_DTPOFF32: + ret->r_addend = value; + break; + case R_ARM_TLS_TPOFF32: + ret->r_addend = (value + read_une32 (dso, rel->r_offset) + + tls->offset); + break; + } + break; + default: + error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +arm_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + Elf32_Sword val; + + if (GELF_R_TYPE (rela->r_info) == R_ARM_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_ARM_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_TPOFF32: + break; + + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_ARM_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_GLOB_DAT: + case R_ARM_JUMP_SLOT: + case R_ARM_ABS32: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + break; + case R_ARM_PC24: + val = value + rela->r_addend - rela->r_offset; + val >>= 2; + if ((Elf32_Word) val + 0x800000 >= 0x1000000) + { + error (0, 0, "%s: R_ARM_PC24 overflow", dso->filename); + return 1; + } + value = read_une32 (dso, rela->r_offset) & 0xff000000; + ret->r_addend = (Elf32_Sword) (value | (val & 0xffffff)); + ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); + break; + case R_ARM_COPY: + error (0, 0, "R_ARM_COPY should not be present in shared libraries"); + return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_ARM_ABS32); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_ARM_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_ARM_TLS_DTPOFF32: + ret->r_addend = value; + break; + case R_ARM_TLS_TPOFF32: + ret->r_addend = value + rela->r_offset + tls->offset; + break; + } + break; + default: + error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +arm_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + rela->r_offset = rel->r_offset; + rela->r_info = rel->r_info; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_JUMP_SLOT: + /* We should be never converting .rel.plt into .rela.plt. */ + abort (); + case R_ARM_RELATIVE: + case R_ARM_ABS32: + case R_ARM_TLS_TPOFF32: + rela->r_addend = (Elf32_Sword) read_une32 (dso, rel->r_offset); + break; + case R_ARM_PC24: + rela->r_addend = read_une32 (dso, rel->r_offset) << 8; + rela->r_addend = ((Elf32_Sword) rela->r_addend) >> 6; + break; + case R_ARM_COPY: + case R_ARM_GLOB_DAT: + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + rela->r_addend = 0; + break; + } + return 0; +} + +static int +arm_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel) +{ + rel->r_offset = rela->r_offset; + rel->r_info = rela->r_info; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_JUMP_SLOT: + /* We should be never converting .rel.plt into .rela.plt + and thus never .rela.plt back to .rel.plt. */ + abort (); + case R_ARM_RELATIVE: + case R_ARM_ABS32: + case R_ARM_TLS_TPOFF32: + write_ne32 (dso, rela->r_offset, rela->r_addend); + break; + case R_ARM_PC24: + write_ne32 (dso, rela->r_offset, + (read_une32 (dso, rela->r_offset) & 0xff000000) + | ((rela->r_addend >> 2) & 0xffffff)); + break; + case R_ARM_GLOB_DAT: + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rela->r_offset, 0); + break; + } + return 0; +} + +static int +arm_need_rel_to_rela (DSO *dso, int first, int last) +{ + Elf_Data *data; + Elf_Scn *scn; + Elf32_Rel *rel, *relend; + unsigned int val; + + while (first <= last) + { + data = NULL; + scn = dso->scn[first++]; + while ((data = elf_getdata (scn, data)) != NULL) + { + rel = (Elf32_Rel *) data->d_buf; + relend = rel + data->d_size / sizeof (Elf32_Rel); + for (; rel < relend; rel++) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_ARM_ABS32: + val = read_une32 (dso, rel->r_offset); + /* R_ARM_ABS32 with addend 0 can be converted + to R_ARM_GLOB_DAT and we don't have to convert + to RELA because of that. */ + if (val == 0) + break; + /* FALLTHROUGH */ + case R_ARM_PC24: + return 1; + case R_ARM_TLS_TPOFF32: + /* In shared libraries TPOFF is changed always into + conflicts, for executables we need to preserve + original addend. */ + if (dso->ehdr.e_type == ET_EXEC) + return 1; + + break; + } + } + } + return 0; +} + +static int +arm_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt into got[1]. + .plt is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr; + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data); + } + + return 0; +} + +static int +arm_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_une32 (dso, dso->info[DT_PLTGOT] + 4); + if (data == dso->shdr[i].sh_addr) + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0); + } + + return 0; +} + +static int +arm_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rel->r_info)) + { + case R_ARM_RELATIVE: + case R_ARM_NONE: + break; + case R_ARM_JUMP_SLOT: + sec = addr_to_sec (dso, rel->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_ARM_JMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4); + + assert (rel->r_offset >= dso->shdr[sec].sh_addr + 12); + assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + write_ne32 (dso, rel->r_offset, data); + } + break; + case R_ARM_GLOB_DAT: + sec = addr_to_sec (dso, rel->r_offset); + + write_ne32 (dso, rel->r_offset, 0); + if (sec != -1) + { + if (strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[sec].sh_name), + ".got")) + { + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_ARM_ABS32); + return 2; + } + } + break; + case R_ARM_ABS32: + case R_ARM_PC24: + error (0, 0, "%s: R_ARM_%s relocs should not be present in prelinked REL sections", + GELF_R_TYPE (rel->r_info) == R_ARM_ABS32 ? "ABS32" : "PC24", + dso->filename); + return 1; + case R_ARM_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_ARM_COPY reloc in shared library?", dso->filename); + return 1; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + write_ne32 (dso, rel->r_offset, 0); + break; + case R_ARM_TLS_TPOFF32: + break; + default: + error (0, 0, "%s: Unknown arm relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +arm_reloc_size (int reloc_type) +{ + assert (reloc_type != R_ARM_COPY); + return 4; +} + +static int +arm_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_ARM_COPY: return RTYPE_CLASS_COPY; + case R_ARM_JUMP_SLOT: return RTYPE_CLASS_PLT; + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "ARM", + .class = ELFCLASS32, + .machine = EM_ARM, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_ARM_JUMP_SLOT, + .R_COPY = R_ARM_COPY, + .R_RELATIVE = R_ARM_RELATIVE, + .dynamic_linker = "/lib/ld-linux.so.2", + .dynamic_linker_alt = "/lib/ld-linux.so.3", + .adjust_dyn = arm_adjust_dyn, + .adjust_rel = arm_adjust_rel, + .adjust_rela = arm_adjust_rela, + .prelink_rel = arm_prelink_rel, + .prelink_rela = arm_prelink_rela, + .prelink_conflict_rel = arm_prelink_conflict_rel, + .prelink_conflict_rela = arm_prelink_conflict_rela, + .apply_conflict_rela = arm_apply_conflict_rela, + .apply_rel = arm_apply_rel, + .apply_rela = arm_apply_rela, + .rel_to_rela = arm_rel_to_rela, + .rela_to_rel = arm_rela_to_rel, + .need_rel_to_rela = arm_need_rel_to_rela, + .reloc_size = arm_reloc_size, + .reloc_class = arm_reloc_class, + .max_reloc_size = 4, + .arch_prelink = arm_arch_prelink, + .arch_undo_prelink = arm_arch_undo_prelink, + .undo_prelink_rel = arm_undo_prelink_rel, + /* Although TASK_UNMAPPED_BASE is 0x40000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x41000000, + .mmap_end = 0x50000000, + .max_page_size = 0x8000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-cris.c b/trunk/src/arch-cris.c new file mode 100644 index 0000000..6b56016 --- /dev/null +++ b/trunk/src/arch-cris.c @@ -0,0 +1,404 @@ +/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +cris_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf32_Addr data; + + if (sec == -1) + return 0; + + data = read_ule32 (dso, dyn->d_un.d_ptr); + /* If .got[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_le32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ule32 (dso, dyn->d_un.d_ptr + 4); + /* If .got[1] points to .plt + 28, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 28 + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_le32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + break; + } + } + } + return 0; +} + +static int +cris_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: CRIS doesn't support REL relocs", dso->filename); + return 1; +} + +static int +cris_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_CRIS_RELATIVE: + if ((Elf32_Addr) rela->r_addend >= start) + rela->r_addend += (Elf32_Sword) adjust; + break; + case R_CRIS_JUMP_SLOT: + data = read_ule32 (dso, rela->r_offset); + if (data >= start) + write_le32 (dso, rela->r_offset, data + adjust); + break; + break; + } + return 0; +} + +static int +cris_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: CRIS doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +cris_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + dso = info->dso; + if (GELF_R_TYPE (rela->r_info) == R_CRIS_NONE) + /* Fast path: nothing to do. */ + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_CRIS_RELATIVE) + { + write_le32 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + write_le32 (dso, rela->r_offset, value); + break; + case R_CRIS_16: + write_le16 (dso, rela->r_offset, value); + break; + case R_CRIS_8: + write_8 (dso, rela->r_offset, value); + break; + case R_CRIS_32_PCREL: + write_le32 (dso, rela->r_offset, value - rela->r_offset - 4); + break; + case R_CRIS_16_PCREL: + write_le16 (dso, rela->r_offset, value - rela->r_offset - 2); + break; + case R_CRIS_8_PCREL: + write_8 (dso, rela->r_offset, value - rela->r_offset - 1); + break; + case R_CRIS_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_CRIS_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown cris relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +cris_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + buf_write_le32 (buf, rela->r_addend); + break; + case R_CRIS_16: + buf_write_le16 (buf, rela->r_addend); + break; + case R_CRIS_8: + buf_write_8 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +cris_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: CRIS doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +cris_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_CRIS_NONE: + break; + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + buf_write_le32 (buf, value); + break; + case R_CRIS_16: + buf_write_le16 (buf, value); + break; + case R_CRIS_8: + buf_write_8 (buf, value); + break; + case R_CRIS_32_PCREL: + buf_write_le32 (buf, value - rela->r_offset - 4); + break; + case R_CRIS_16_PCREL: + buf_write_le16 (buf, value - rela->r_offset - 2); + break; + case R_CRIS_8: + buf_write_8 (buf, value - rela->r_offset - 1); + break; + case R_CRIS_COPY: + abort (); + case R_CRIS_RELATIVE: + error (0, 0, "%s: R_CRIS_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +cris_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: CRIS doesn't support REL relocs", dso->filename); + return 1; +} + +static int +cris_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_CRIS_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_CRIS_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + return 0; + value = conflict_lookup_value (conflict); + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_CRIS_GLOB_DAT: + case R_CRIS_JUMP_SLOT: + case R_CRIS_32: + case R_CRIS_16: + case R_CRIS_8: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + break; + case R_CRIS_32_PCREL: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend + - rela->r_offset - 4); + ret->r_info = GELF_R_INFO (0, R_CRIS_32); + break; + case R_CRIS_16_PCREL: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend + - rela->r_offset - 2); + ret->r_info = GELF_R_INFO (0, R_CRIS_16); + break; + case R_CRIS_8_PCREL: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend + - rela->r_offset - 1); + ret->r_info = GELF_R_INFO (0, R_CRIS_8); + break; + case R_CRIS_COPY: + error (0, 0, "R_CRIS_COPY should not be present in shared libraries"); + return 1; + default: + error (0, 0, "%s: Unknown cris relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +cris_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + return 0; +} + +static int +cris_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +cris_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 28 into got[1]. + .plt + 28 is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + assert (i < dso->ehdr.e_shnum); + data = dso->shdr[i].sh_addr + 28; + write_le32 (dso, dso->info[DT_PLTGOT] + 4, data); + } + + return 0; +} + +static int +cris_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_CRIS_16: + case R_CRIS_16_PCREL: + return 2; + case R_CRIS_8: + case R_CRIS_8_PCREL: + return 1; + default: + return 4; + } +} + +static int +cris_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_CRIS_COPY: return RTYPE_CLASS_COPY; + case R_CRIS_JUMP_SLOT: return RTYPE_CLASS_PLT; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "CRIS", + .class = ELFCLASS32, + .machine = EM_CRIS, + .alternate_machine = { EM_NONE }, + .R_JUMP_SLOT = R_CRIS_JUMP_SLOT, + .R_COPY = R_CRIS_COPY, + .R_RELATIVE = R_CRIS_RELATIVE, + .dynamic_linker = "/lib/ld.so.1", + .adjust_dyn = cris_adjust_dyn, + .adjust_rel = cris_adjust_rel, + .adjust_rela = cris_adjust_rela, + .prelink_rel = cris_prelink_rel, + .prelink_rela = cris_prelink_rela, + .prelink_conflict_rel = cris_prelink_conflict_rel, + .prelink_conflict_rela = cris_prelink_conflict_rela, + .apply_conflict_rela = cris_apply_conflict_rela, + .apply_rel = cris_apply_rel, + .apply_rela = cris_apply_rela, + .rel_to_rela = cris_rel_to_rela, + .need_rel_to_rela = cris_need_rel_to_rela, + .reloc_size = cris_reloc_size, + .reloc_class = cris_reloc_class, + .max_reloc_size = 4, + .arch_prelink = cris_arch_prelink, + /* Although TASK_UNMAPPED_BASE is 0x3aaaa000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x3c000000, + .mmap_end = 0x48000000, + .max_page_size = 0x2000, + .page_size = 0x2000 +}; diff --git a/trunk/src/arch-i386.c b/trunk/src/arch-i386.c new file mode 100644 index 0000000..d5211b2 --- /dev/null +++ b/trunk/src/arch-i386.c @@ -0,0 +1,1087 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" +#include "layout.h" + +static int +i386_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf32_Addr data; + + if (sec == -1) + return 0; + + data = read_ule32 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_le32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ule32 (dso, dyn->d_un.d_ptr + 4); + /* If .got.plt[1] points to .plt + 0x16, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 0x16 + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_le32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + break; + } + } + } + return 0; +} + +static int +i386_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_RELATIVE: + case R_386_JMP_SLOT: + data = read_ule32 (dso, rel->r_offset); + if (data >= start) + write_le32 (dso, rel->r_offset, data + adjust); + break; + } + return 0; +} + +static int +i386_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_RELATIVE: + if ((Elf32_Addr) rela->r_addend >= start) + { + rela->r_addend += (Elf32_Sword) adjust; + /* Write it to the memory location as well. + Not necessary, but we can do it. */ + write_le32 (dso, rela->r_offset, rela->r_addend); + } + break; + case R_386_JMP_SLOT: + data = read_ule32 (dso, rela->r_offset); + if (data >= start) + write_le32 (dso, rela->r_offset, data + adjust); + break; + break; + } + return 0; +} + +static int +i386_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + DSO *dso; + GElf_Addr value; + + if (GELF_R_TYPE (rel->r_info) == R_386_RELATIVE + || GELF_R_TYPE (rel->r_info) == R_386_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + write_le32 (dso, rel->r_offset, value); + break; + case R_386_32: + { + if (read_ule32 (dso, rel->r_offset)) + { + error (0, 0, "%s: R_386_32 relocs with non-zero addend should not be present in prelinked REL sections", + dso->filename); + return 1; + } + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_386_GLOB_DAT); + write_le32 (dso, rel->r_offset, value); + /* Tell prelink_rel routine *rel has changed. */ + return 2; + } + case R_386_PC32: + error (0, 0, "%s: R_386_PC32 relocs should not be present in prelinked REL sections", + dso->filename); + return 1; + case R_386_TLS_DTPOFF32: + write_le32 (dso, rel->r_offset, value); + break; + /* DTPMOD32 and TPOFF{32,} is impossible to predict unless prelink + sets the rules. Also for TPOFF{32,} there is REL->RELA problem. */ + case R_386_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_386_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + if (dso->ehdr.e_type == ET_EXEC) + error (0, 0, "%s: R_386_TLS_TPOFF relocs should not be present in prelinked ET_EXEC REL sections", + dso->filename); + break; + case R_386_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_386_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown i386 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +i386_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_386_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_386_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + write_le32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_386_32: + write_le32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_386_PC32: + write_le32 (dso, rela->r_offset, value + rela->r_addend - rela->r_offset); + break; + case R_386_TLS_DTPOFF32: + write_le32 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD32 and TPOFF{32,} is impossible to predict unless prelink + sets the rules. */ + case R_386_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_386_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_386_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_le32 (dso, rela->r_offset, + -(value + rela->r_addend - info->resolvetls->offset)); + break; + case R_386_TLS_TPOFF: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_le32 (dso, rela->r_offset, + value + rela->r_addend - info->resolvetls->offset); + break; + case R_386_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_386_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown i386 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +i386_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + case R_386_32: + buf_write_le32 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +i386_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_NONE: + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + buf_write_le32 (buf, value); + break; + case R_386_32: + buf_write_le32 (buf, value + read_ule32 (info->dso, rel->r_offset)); + break; + case R_386_PC32: + buf_write_le32 (buf, value + read_ule32 (info->dso, rel->r_offset) + - rel->r_offset); + break; + case R_386_COPY: + abort (); + case R_386_RELATIVE: + error (0, 0, "%s: R_386_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +i386_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_NONE: + break; + case R_386_GLOB_DAT: + case R_386_JMP_SLOT: + case R_386_32: + buf_write_le32 (buf, value + rela->r_addend); + break; + case R_386_PC32: + buf_write_le32 (buf, value + rela->r_addend - rela->r_offset); + break; + case R_386_COPY: + abort (); + case R_386_RELATIVE: + error (0, 0, "%s: R_386_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +i386_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rel->r_info) == R_386_RELATIVE + || GELF_R_TYPE (rel->r_info) == R_386_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rel->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_386_TLS_DTPMOD32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rel->r_info) == R_386_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rel->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rel->r_info)); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_GLOB_DAT: + ret->r_info = GELF_R_INFO (0, R_386_32); + /* FALLTHROUGH */ + case R_386_JMP_SLOT: + ret->r_addend = (Elf32_Sword) value; + break; + case R_386_32: + case R_386_PC32: + error (0, 0, "%s: R_386_%s32 relocs should not be present in prelinked REL sections", + dso->filename, GELF_R_TYPE (rel->r_info) == R_386_32 ? "" : "PC"); + return 1; + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: R_386_TLS not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_386_32); + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_386_TLS_DTPOFF32: + ret->r_addend = value; + break; + case R_386_TLS_TPOFF32: + ret->r_addend = -(value + read_ule32 (dso, rel->r_offset) + - tls->offset); + break; + case R_386_TLS_TPOFF: + ret->r_addend = value + read_ule32 (dso, rel->r_offset) + - tls->offset; + } + break; + case R_386_COPY: + error (0, 0, "R_386_COPY should not be present in shared libraries"); + return 1; + default: + error (0, 0, "%s: Unknown i386 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +i386_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_386_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_386_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_386_TLS_DTPMOD32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_386_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_GLOB_DAT: + ret->r_info = GELF_R_INFO (0, R_386_32); + /* FALLTHROUGH */ + case R_386_JMP_SLOT: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + break; + case R_386_32: + value += rela->r_addend; + ret->r_addend = (Elf32_Sword) value; + break; + case R_386_PC32: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend - rela->r_offset); + ret->r_info = GELF_R_INFO (0, R_386_32); + break; + case R_386_COPY: + error (0, 0, "R_386_COPY should not be present in shared libraries"); + return 1; + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: R_386_TLS not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_386_32); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_386_TLS_DTPMOD32: + ret->r_addend = tls->modid; + break; + case R_386_TLS_DTPOFF32: + ret->r_addend += value; + break; + case R_386_TLS_TPOFF32: + ret->r_addend = -(value + rela->r_addend - tls->offset); + break; + case R_386_TLS_TPOFF: + ret->r_addend = value + rela->r_addend - tls->offset; + break; + } + break; + default: + error (0, 0, "%s: Unknown i386 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +i386_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + rela->r_offset = rel->r_offset; + rela->r_info = rel->r_info; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_JMP_SLOT: + /* We should be never converting .rel.plt into .rela.plt. */ + abort (); + case R_386_RELATIVE: + case R_386_32: + case R_386_PC32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + rela->r_addend = (Elf32_Sword) read_ule32 (dso, rel->r_offset); + break; + case R_386_COPY: + case R_386_GLOB_DAT: + case R_386_TLS_DTPOFF32: + case R_386_TLS_DTPMOD32: + rela->r_addend = 0; + break; + } + return 0; +} + +static int +i386_need_rel_to_rela (DSO *dso, int first, int last) +{ + Elf_Data *data; + Elf_Scn *scn; + Elf32_Rel *rel, *relend; + unsigned int val; + + while (first <= last) + { + data = NULL; + scn = dso->scn[first++]; + while ((data = elf_getdata (scn, data)) != NULL) + { + rel = (Elf32_Rel *) data->d_buf; + relend = rel + data->d_size / sizeof (Elf32_Rel); + for (; rel < relend; rel++) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_386_32: + val = read_ule32 (dso, rel->r_offset); + /* R_386_32 with addend 0 can be converted + to R_386_GLOB_DAT and we don't have to convert + to RELA because of that. */ + if (val == 0) + break; + /* FALLTHROUGH */ + case R_386_PC32: + return 1; + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + /* In shared libraries TPOFF is changed always into + conflicts, for executables we need to preserve + original addend. */ + if (dso->ehdr.e_type == ET_EXEC) + return 1; + break; + } + } + } + return 0; +} + +static int +i386_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 0x16 into got[1]. + .plt + 0x16 is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr + 0x16; + write_le32 (dso, dso->info[DT_PLTGOT] + 4, data); + } + + return 0; +} + +static int +i386_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt + 0x16. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_ule32 (dso, dso->info[DT_PLTGOT] + 4); + if (data == dso->shdr[i].sh_addr + 0x16) + write_le32 (dso, dso->info[DT_PLTGOT] + 4, 0); + } + + return 0; +} + +static int +i386_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_NONE: + case R_386_RELATIVE: + break; + case R_386_JMP_SLOT: + sec = addr_to_sec (dso, rel->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_386_JMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf32_Addr data = read_ule32 (dso, dso->shdr[sec].sh_addr + 4); + + assert (rel->r_offset >= dso->shdr[sec].sh_addr + 12); + assert (((rel->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + write_le32 (dso, rel->r_offset, + 4 * (rel->r_offset - dso->shdr[sec].sh_addr - 12) + + data); + } + break; + case R_386_GLOB_DAT: + sec = addr_to_sec (dso, rel->r_offset); + + write_le32 (dso, rel->r_offset, 0); + if (sec != -1) + { + if (strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[sec].sh_name), + ".got")) + { + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_386_32); + return 2; + } + } + break; + case R_386_32: + case R_386_PC32: + error (0, 0, "%s: R_386_%s32 relocs should not be present in prelinked REL sections", + GELF_R_TYPE (rel->r_info) == R_386_32 ? "" : "PC", dso->filename); + return 1; + case R_386_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_386_COPY reloc in shared library?", dso->filename); + return 1; + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + write_le32 (dso, rel->r_offset, 0); + break; + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + break; + default: + error (0, 0, "%s: Unknown i386 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +i386_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel) +{ + rel->r_offset = rela->r_offset; + rel->r_info = rela->r_info; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_386_JMP_SLOT: + /* We should be never converting .rel.plt into .rela.plt + and thus never .rela.plt back to .rel.plt. */ + abort (); + case R_386_RELATIVE: + case R_386_32: + case R_386_PC32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + write_le32 (dso, rela->r_offset, rela->r_addend); + break; + case R_386_COPY: + case R_386_GLOB_DAT: + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + write_le32 (dso, rela->r_offset, 0); + break; + } + return 0; +} + +static int +i386_reloc_size (int reloc_type) +{ + assert (reloc_type != R_386_COPY); + return 4; +} + +static int +i386_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_386_COPY: return RTYPE_CLASS_COPY; + case R_386_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +/* Library memory regions if --exec-shield in order of precedence: + 0x00101000 + (rand % 0x00cff000) .. 0x00e00000 bottom to top + 0x00101000 .. 0x00101000 + (rand % 0x00cff000) bottom to top + 0x02000000 + (rand % 0x06000000) .. 0x08000000 bottom to top + 0x02000000 .. 0x02000000 + (rand % 0x06000000) bottom to top + 0x41000000 + (rand % 0x0f000000) .. 0x50000000 bottom to top + 0x41000000 .. 0x41000000 + (rand % 0x0f000000) bottom to top */ + +#define REG0S 0x00101000 +#define REG0E 0x00e00000 +#define REG1S 0x02000000 +#define REG1E 0x08000000 +#define REG2S 0x41000000 +#define REG2E 0x50000000 + +struct i386_layout_data +{ + struct prelink_entry e[6]; + Elf32_Addr addrs[12]; +}; + +static inline void +list_append (struct prelink_entry *x, struct prelink_entry *e) +{ + x->prev->next = e; + e->prev = x->prev; + e->next = NULL; + x->prev = e; +} + +static inline void +list_merge (struct prelink_entry *x, struct prelink_entry *e) +{ + struct prelink_entry *end = e->prev; + x->prev->next = e; + e->prev = x->prev; + x->prev = end; +} + +static int +i386_layout_libs_init (struct layout_libs *l) +{ + if (exec_shield) + { + int i; + struct prelink_entry *e; + + l->mmap_base = REG0S; + l->mmap_end = REG2E; + /* Don't allow this to be overridden. */ + mmap_reg_start = ~(GElf_Addr) 0; + mmap_reg_end = ~(GElf_Addr) 0; + for (i = 0; i < l->nlibs; ++i) + { + e = l->libs[i]; + if (e->done == 0) + continue; + if (e->base < REG0S + || (e->base < REG1S && e->layend > REG0E) + || (e->base < REG2S && e->layend > REG1E) + || e->layend > REG2E) + e->done = 0; + } + } + else + { + l->mmap_base = REG2S; + l->mmap_end = REG2E; + } + return 0; +} + +static void +i386_find_free_addr (struct layout_libs *l, Elf32_Addr *ret, + Elf32_Addr beg, Elf32_Addr end, Elf32_Addr start) +{ + struct prelink_entry *e; + Elf32_Addr low, hi; + + ret[0] = beg; + ret[3] = end; + for (e = l->list; e != NULL; e = e->next) + if (e->base >= start) + break; + if (e == l->list) + { + ret[1] = ret[2] = start; + return; + } + + if (e == NULL) + e = l->list; + low = start; + for (e = e->prev; ; e = e->prev) + { + if (e->base < beg) + break; + if (e->layend > low) + low = e->base; + if (e == l->list) + break; + } + + if (low == start) + { + ret[1] = ret[2] = start; + return; + } + + hi = start; + for (; e; e = e->next) + { + if (e->base >= end) + break; + if (e->base >= hi) + break; + if (e->layend > hi) + hi = e->layend; + } + + assert (low >= beg && hi <= end); + + if (hi - start > start - low) + start = low; + else + start = hi; + + ret[1] = ret[2] = start; +} + +static int +i386_layout_libs_pre (struct layout_libs *l) +{ + Elf32_Addr mmap_start, virt; + struct prelink_entry *e, *next; + struct i386_layout_data *pld; + int i; + + if (!exec_shield) + { + l->mmap_fin = l->mmap_end; + l->fake = NULL; + l->fakecnt = 0; + return 0; + } + + pld = calloc (sizeof (*pld), 1); + if (pld == NULL) + error (EXIT_FAILURE, ENOMEM, "Cannot lay libraries out"); + + l->arch_data = pld; + + mmap_start = l->mmap_start - REG0S; + /* Unless not randomizing, try not to make the first region + too small, because otherwise it is likely libc.so as first + big library would often end up at REG0S. */ + virt = mmap_start % (REG0E - REG0S - 0x200000); + i386_find_free_addr (l, pld->addrs + 0, REG0S, REG0E, REG0S + virt); + virt = mmap_start % (REG1E - REG1S - 0x200000); + i386_find_free_addr (l, pld->addrs + 4, REG1S, REG1E, REG1S + virt); + virt = mmap_start % (REG0E - REG0S - 0x200000); + i386_find_free_addr (l, pld->addrs + 8, REG2S, REG2E, REG2S + virt); + i = 0; + virt = pld->addrs[3] - pld->addrs[2]; + pld->e[0].u.tmp = -1; + pld->e[0].base = virt; + pld->e[0].end = pld->e[0].base; + pld->e[0].layend = pld->e[0].end; + pld->e[0].prev = &pld->e[0]; + next = NULL; + for (e = l->list; e != NULL; e = next) + { + next = e->next; + while (i < 5 + && (e->base >= pld->addrs[2 * i + 1] + || pld->addrs[2 * i] == pld->addrs[2 * i + 1])) + { + ++i; + pld->e[i].u.tmp = -1; + if (i & 1) + virt -= pld->addrs[2 * i + 1] - pld->addrs[2 * i]; + else + { + virt += pld->addrs[2 * i - 1] - pld->addrs[2 * i - 4]; + virt += pld->addrs[2 * i + 3] - pld->addrs[2 * i + 2]; + } + pld->e[i].base = virt; + pld->e[i].end = pld->e[i].base; + pld->e[i].layend = pld->e[i].end; + pld->e[i].prev = &pld->e[i]; + } + e->base += (Elf32_Sword) (virt - pld->addrs[2 * i]); + e->end += (Elf32_Sword) (virt - pld->addrs[2 * i]); + e->layend += (Elf32_Sword) (virt - pld->addrs[2 * i]); + list_append (&pld->e[i], e); + } + while (i < 5) + { + ++i; + pld->e[i].u.tmp = -1; + if (i & 1) + virt -= pld->addrs[2 * i + 1] - pld->addrs[2 * i]; + else + { + virt += pld->addrs[2 * i - 1] - pld->addrs[2 * i - 4]; + virt += pld->addrs[2 * i + 3] - pld->addrs[2 * i + 2]; + } + pld->e[i].base = virt; + pld->e[i].end = pld->e[i].base; + pld->e[i].layend = pld->e[i].end; + pld->e[i].prev = &pld->e[i]; + } + l->list = &pld->e[1]; + list_merge (&pld->e[1], &pld->e[0]); + list_merge (&pld->e[1], &pld->e[3]); + list_merge (&pld->e[1], &pld->e[2]); + list_merge (&pld->e[1], &pld->e[5]); + list_merge (&pld->e[1], &pld->e[4]); + + l->mmap_start = 0; + l->mmap_base = 0; + l->mmap_fin = virt + pld->addrs[2 * i + 1] - pld->addrs[2 * i]; + l->mmap_end = l->mmap_fin; + l->fakecnt = 6; + l->fake = pld->e; + + return 0; +} + +static int +i386_layout_libs_post (struct layout_libs *l) +{ + struct prelink_entry *e; + struct i386_layout_data *pld = (struct i386_layout_data *) l->arch_data; + Elf32_Sword adj = 0; + int i; + + if (!exec_shield) + return 0; + + for (i = 0, e = l->list; e != NULL; e = e->next) + { + if (e == &pld->e[i ^ 1]) + { + adj = pld->addrs[2 * (i ^ 1)] - e->base; + ++i; + } + else + { + e->base += adj; + e->end += adj; + e->layend += adj; + } + } + + free (l->arch_data); + return 0; +} + +PL_ARCH = { + .name = "i386", + .class = ELFCLASS32, + .machine = EM_386, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_386_JMP_SLOT, + .R_COPY = R_386_COPY, + .R_RELATIVE = R_386_RELATIVE, + .dynamic_linker = "/lib/ld-linux.so.2", + .adjust_dyn = i386_adjust_dyn, + .adjust_rel = i386_adjust_rel, + .adjust_rela = i386_adjust_rela, + .prelink_rel = i386_prelink_rel, + .prelink_rela = i386_prelink_rela, + .prelink_conflict_rel = i386_prelink_conflict_rel, + .prelink_conflict_rela = i386_prelink_conflict_rela, + .apply_conflict_rela = i386_apply_conflict_rela, + .apply_rel = i386_apply_rel, + .apply_rela = i386_apply_rela, + .rel_to_rela = i386_rel_to_rela, + .rela_to_rel = i386_rela_to_rel, + .need_rel_to_rela = i386_need_rel_to_rela, + .reloc_size = i386_reloc_size, + .reloc_class = i386_reloc_class, + .max_reloc_size = 4, + .arch_prelink = i386_arch_prelink, + .arch_undo_prelink = i386_arch_undo_prelink, + .undo_prelink_rel = i386_undo_prelink_rel, + .layout_libs_init = i386_layout_libs_init, + .layout_libs_pre = i386_layout_libs_pre, + .layout_libs_post = i386_layout_libs_post, + /* Although TASK_UNMAPPED_BASE is 0x40000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = REG2S, + .mmap_end = REG2E, + .max_page_size = 0x1000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-ia64.c b/trunk/src/arch-ia64.c new file mode 100644 index 0000000..0be672c --- /dev/null +++ b/trunk/src/arch-ia64.c @@ -0,0 +1,525 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" +#include "fptr.h" + +static int +ia64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_IA_64_PLT_RESERVE) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf64_Addr data; + + if (sec != -1) + { + data = read_ule64 (dso, dyn->d_un.d_ptr + 8); + + /* If .got[1] points to .plt + 0x30, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 0x30 + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_le64 (dso, dyn->d_un.d_ptr + 8, data + adjust); + break; + } + } + } + + if (dyn->d_un.d_ptr >= start) + dyn->d_un.d_ptr += adjust; + return 1; + } + + return 0; +} + +static int +ia64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: IA-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ia64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_REL32MSB + && rela->r_addend >= start) + { + rela->r_addend += adjust; + switch (GELF_R_TYPE (rela->r_info) & 3) + { + case 0: write_be32 (dso, rela->r_offset, rela->r_addend); break; + case 1: write_le32 (dso, rela->r_offset, rela->r_addend); break; + case 2: write_be64 (dso, rela->r_offset, rela->r_addend); break; + case 3: write_le64 (dso, rela->r_offset, rela->r_addend); break; + } + } + else if ((GELF_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + { + GElf_Addr val, gp; + + if (GELF_R_TYPE (rela->r_info) & 1) + { + val = read_ule64 (dso, rela->r_offset); + gp = read_ule64 (dso, rela->r_offset + 8); + } + else + { + val = read_ube64 (dso, rela->r_offset); + gp = read_ube64 (dso, rela->r_offset + 8); + } + if (gp == dso->info[DT_PLTGOT]) + { + if (val >= start) + val += adjust; + if (gp >= start) + gp += adjust; + } + if (GELF_R_TYPE (rela->r_info) & 1) + { + write_le64 (dso, rela->r_offset, val); + write_le64 (dso, rela->r_offset + 8, gp); + } + else + { + write_le64 (dso, rela->r_offset, val); + write_le64 (dso, rela->r_offset + 8, gp); + } + } + return 0; +} + +static int +ia64_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: IA-64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +ia64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_REL32MSB + || GELF_R_TYPE (rela->r_info) == R_IA64_NONE) + /* Fast path: nothing to do. */ + return 0; + dso = info->dso; + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_DIR32MSB) + { + /* Nothing to do. */ + } + else if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_PCREL32MSB) + { + value -= rela->r_offset & -16; + } + else if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_FPTR32MSB) + { + /* FIXME */ + } + else if ((GELF_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + { + GElf_Addr gp = info->resolveent->pltgot; + + if (GELF_R_TYPE (rela->r_info) & 1) + { + write_le64 (dso, rela->r_offset, value); + write_le64 (dso, rela->r_offset + 8, gp); + } + else + { + write_be64 (dso, rela->r_offset, value); + write_be64 (dso, rela->r_offset + 8, gp); + } + + return 0; + } + else + { + error (0, 0, "%s: Unknown ia64 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + + switch (GELF_R_TYPE (rela->r_info) & 3) + { + case 0: write_be32 (dso, rela->r_offset, value); break; + case 1: write_le32 (dso, rela->r_offset, value); break; + case 2: write_be64 (dso, rela->r_offset, value); break; + case 3: write_le64 (dso, rela->r_offset, value); break; + } + return 0; +} + +static int +ia64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + if ((GELF_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + { + GElf_Addr gp = 0; + int i; + + for (i = 0; i < info->ent->ndepends; ++i) + if (info->ent->depends[i]->base <= rela->r_addend + && info->ent->depends[i]->end > rela->r_addend) + { + gp = info->ent->depends[i]->pltgot; + break; + } + + if (i == info->ent->ndepends) + abort (); + + if (GELF_R_TYPE (rela->r_info) & 1) + { + buf_write_le64 (buf, rela->r_addend); + buf_write_le64 (buf + 8, gp); + } + else + { + buf_write_be64 (buf, rela->r_addend); + buf_write_be64 (buf + 8, gp); + } + return 0; + } + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_IA64_DIR32MSB: buf_write_be32 (buf, rela->r_addend); break; + case R_IA64_DIR32LSB: buf_write_le32 (buf, rela->r_addend); break; + case R_IA64_DIR64MSB: buf_write_be64 (buf, rela->r_addend); break; + case R_IA64_DIR64LSB: buf_write_le64 (buf, rela->r_addend); break; + default: + abort (); + } + return 0; +} + +static int +ia64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: IA-64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +ia64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_DIR32MSB) + { + /* Nothing to do. */ + } + else if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_PCREL32MSB) + { + value -= rela->r_offset & -16; + } + else if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_FPTR32MSB) + { + /* FIXME */ + } + else if ((GELF_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + { + GElf_Addr gp = info->resolveent->pltgot; + + if (GELF_R_TYPE (rela->r_info) & 1) + { + buf_write_le64 (buf, value); + buf_write_le64 (buf + 8, gp); + } + else + { + buf_write_be64 (buf, value); + buf_write_be64 (buf + 8, gp); + } + return 0; + } + else + return 1; + + switch (GELF_R_TYPE (rela->r_info) & 3) + { + case 0: buf_write_be32 (buf, value); break; + case 1: buf_write_le32 (buf, value); break; + case 2: buf_write_be64 (buf, value); break; + case 3: buf_write_le64 (buf, value); break; + } + return 0; +} + +static int +ia64_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: IA-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ia64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *ret; + + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_REL32MSB + || GELF_R_TYPE (rela->r_info) == R_IA64_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + return 0; + value = conflict_lookup_value (conflict); + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_DIR32MSB + || (GELF_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + { + ret->r_addend = value + rela->r_addend; + return 0; + } + else if ((GELF_R_TYPE (rela->r_info) & ~3) == R_IA64_PCREL32MSB) + { + ret->r_addend = value + rela->r_addend - (rela->r_offset & -16); + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info) + + R_IA64_DIR32MSB - R_IA64_PCREL32MSB); + return 0; + } + else if (GELF_R_TYPE (rela->r_info) == R_IA64_COPY) + { + error (0, 0, "R_IA64_COPY should not be present in shared libraries"); + return 1; + } + error (0, 0, "%s: Unknown ia64 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; +} + +static int +ia64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: IA-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ia64_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static GElf_Addr +ia64_create_opd (struct prelink_info *info, int first, int last, int plt) +{ + Elf_Data *d; + Elf_Scn *scn; + Elf64_Rela *rela, *relaend; + DSO *dso = info->dso; + int sec; + + if (opd_init (info)) + return -1; + + if (plt) + info->ent->opd->plt_start = dso->shdr[dso->shdr[plt].sh_info].sh_addr; + else + info->ent->opd->plt_start = dso->shdr[dso->dynamic].sh_addr; + sec = first; + while (sec <= last) + { + d = NULL; + scn = dso->scn[sec++]; + while ((d = elf_getdata (scn, d)) != NULL) + { + rela = (Elf64_Rela *) d->d_buf; + relaend = rela + d->d_size / sizeof (Elf64_Rela); + for (; rela < relaend; rela++) + if ((ELF64_R_TYPE (rela->r_info) & ~3) == R_IA64_FPTR32MSB + && opd_add (info, ELF64_R_SYM (rela->r_info), + R_IA64_FPTR64LSB)) + return -1; + } + } + + sec = first; + while (sec) + { + d = NULL; + if (sec == plt) + break; + scn = dso->scn[sec++]; + if (sec == last + 1) + sec = plt; + while ((d = elf_getdata (scn, d)) != NULL) + { + rela = (Elf64_Rela *) d->d_buf; + relaend = rela + d->d_size / sizeof (Elf64_Rela); + for (; rela < relaend; rela++) + if ((ELF64_R_TYPE (rela->r_info) & ~1) == R_IA64_IPLTMSB) + opd_note_plt (info, ELF64_R_SYM (rela->r_info), R_IA64_IPLTLSB, + rela->r_offset); + } + } + + return opd_size (info, 16); +} + +static int +ia64_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int plt = -1, got = -1, i; + const char *name; + + /* Write address of .plt + 0x30 into .got[1]. + .plt + 0x30 is what .IA_64.pltoff[0] contains unless prelinking. */ + + dso = info->dso; + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS) + { + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".got")) + { + if (got != -1) + { + error (0, 0, "%s: More than one .got section", dso->filename); + return 1; + } + got = i; + } + else if (! strcmp (name, ".plt")) + { + if (plt != -1) + { + error (0, 0, "%s: More than one .plt section", dso->filename); + return 1; + } + plt = i; + } + } + + if (plt == -1) + return 0; + + if (got == -1) + { + error (0, 0, "%s: Has .plt section but not .got section", dso->filename); + return 1; + } + + write_le64 (dso, dso->shdr[got].sh_addr + 8, dso->shdr[plt].sh_addr + 0x30); + return 0; +} + +static int +ia64_reloc_size (int reloc_type) +{ + if ((reloc_type & ~1) == R_IA64_IPLTMSB) + return 16; + return (reloc_type & 2) ? 8 : 4; +} + +static int +ia64_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_IA64_IPLTLSB: + case R_IA64_IPLTMSB: + return RTYPE_CLASS_PLT; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "IA-64", + .class = ELFCLASS64, + .machine = EM_IA_64, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_IA64_IPLTLSB, + .R_COPY = -1, + .R_RELATIVE = R_IA64_REL64LSB, + .dynamic_linker = "/lib/ld-linux-ia64.so.2", + .adjust_dyn = ia64_adjust_dyn, + .adjust_rel = ia64_adjust_rel, + .adjust_rela = ia64_adjust_rela, + .prelink_rel = ia64_prelink_rel, + .prelink_rela = ia64_prelink_rela, + .prelink_conflict_rel = ia64_prelink_conflict_rel, + .prelink_conflict_rela = ia64_prelink_conflict_rela, + .apply_conflict_rela = ia64_apply_conflict_rela, + .apply_rel = ia64_apply_rel, + .apply_rela = ia64_apply_rela, + .rel_to_rela = ia64_rel_to_rela, + .need_rel_to_rela = ia64_need_rel_to_rela, + .create_opd = ia64_create_opd, + .reloc_size = ia64_reloc_size, + .reloc_class = ia64_reloc_class, + .max_reloc_size = 16, + .arch_prelink = ia64_arch_prelink, + /* Although TASK_UNMAPPED_BASE is 0x2000000000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x2000000010000000LL, + .mmap_end = 0x4000000000000000LL, + .max_page_size = 0x10000, + /* The kernel can be configured for 4K, 8K, 16K and 64K, + but most kernels have at least 8K. */ + .page_size = 0x02000 +}; diff --git a/trunk/src/arch-mips.c b/trunk/src/arch-mips.c new file mode 100644 index 0000000..f5a2361 --- /dev/null +++ b/trunk/src/arch-mips.c @@ -0,0 +1,1031 @@ +/* Copyright (C) 2006 CodeSourcery + Written by Richard Sandiford <richard@codesourcery.com>, 2006 + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* GENERAL NOTES + + The psABI defines R_MIPS_REL32 as A - EA + S, where the value of EA + depends on the symbol index. If the index is less than DT_MIPS_GOTSYM, + EA is the symbol's st_value "plus displacement". If the index is greater + than or equal to DT_MIPS_GOTSYM, EA is the original value of the + associated GOT entry. + + However, glibc's dynamic linker implements a different definition. + If the index is less than DT_MIPS_GOTSYM, the dynamic linker adds the + symbol's st_value and the base address to the addend. If the index + is greater than or equal to DT_MIPS_GOTSYM, the dynamic linker adds + the final symbol value to the addend. + + MIPS GOTs are divided into three parts: + + - Reserved entries (of which GNU objects have 2) + - Local entries + - Global entries + + DT_MIPS_LOCAL_GOTNO gives the total number of reserved and local + entries. The local entries all hold virtual addresses and the + dynamic linker will add the base address to each one. + + Unlike most other architectures, the MIPS ABI does not use + relocations to initialize the global GOT entries. Instead, global + GOT entry X is mapped to dynamic symbol DT_MIPS_GOTSYM + X, and there + are a total of DT_MIPS_SYMTABNO - DT_MIPS_GOTSYM global GOT entries. + + The interpretation of a global GOT entry depends on the symbol entry + and the initial GOT contents. The psABI lists the following cases: + + st_shndx st_type st_value initial GOT value + -------- ------- -------- ----------------- + A: SHN_UNDEF STT_FUNC 0 st_value (== 0) / QS + B: SHN_UNDEF STT_FUNC stub address st_value / QS + C: SHN_UNDEF all others 0 st_value (== 0) / QS + D: SHN_COMMON any alignment 0 / QS + E: all others STT_FUNC value st_value / stub address + F: all others all others value st_value + + (wording slightly modified from the psABI table). Here, QS denotes + Quickstart values. + + The dynamic linker treats each case as follows: + + - [A, B when not binding lazily, C, D, E when not binding lazily, F] + Resolve the symbol and store its value in the GOT. + + - [B when binding lazily] Set the GOT entry to the st_value plus + the base address. + + - [E when binding lazily] If the GOT entry is different from the st_value, + add the base addreess to the GOT entry. Otherwise resolve the symbol + and store its value in the GOT (as for A, C, etc). + + As the table shows, we can install Quickstart values for types A-D. + Installing Quickstart values for type F should be a no-op, because the + GOT should already hold the desired value. Installing Quickstart values + for type E would either be a no-op (if the GOT entry already contains + st_value) or would lose the address of the lazy binding stub. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" +#include "layout.h" + +/* The thread pointer points 0x7000 past the first static TLS block. */ +#define TLS_TP_OFFSET 0x7000 + +/* Dynamic thread vector pointers point 0x8000 past the start of each + TLS block. */ +#define TLS_DTV_OFFSET 0x8000 + +/* The number of reserved entries at the beginning of the GOT. + The dynamic linker points entry 0 to the resolver function + and entry 1 to the link_map. */ +#define RESERVED_GOTNO 2 + +/* A structure for iterating over local GOT entries. */ +struct mips_local_got_iterator { + /* The DSO containing the GOT. */ + DSO *dso; + + /* The size of a GOT entry. */ + GElf_Word entry_size; + + /* The index of the current GOT entry. */ + GElf_Word got_index; + + /* A pointer to the current GOT entry. */ + unsigned char *got_entry; + + /* True if we failed to read an entry correctly. */ + int failed; + + /* Used internally to obtain GOT_ENTRY. */ + struct data_iterator got_iterator; +}; + +/* Set up LGI to iterate over DSO's local GOT. The caller should use + mips_get_local_got_entry to read the first entry. */ + +static inline void +mips_init_local_got_iterator (struct mips_local_got_iterator *lgi, DSO *dso) +{ + lgi->dso = dso; + lgi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT); + lgi->got_index = RESERVED_GOTNO - 1; + lgi->failed = 0; + init_data_iterator (&lgi->got_iterator, dso, + dso->info[DT_PLTGOT] + + (lgi->got_index + 1) * lgi->entry_size); +} + +/* Return true if LGI has not reached the end of the GOT and if the next + entry can be accessed. When returning true, use LGI's fields to + describe the next entry. */ + +static inline int +mips_get_local_got_entry (struct mips_local_got_iterator *lgi) +{ + lgi->got_index++; + if (lgi->got_index >= lgi->dso->info_DT_MIPS_LOCAL_GOTNO) + return 0; + + lgi->got_entry = get_data_from_iterator (&lgi->got_iterator, + lgi->entry_size); + if (lgi->got_entry == NULL) + { + error (0, 0, "%s: Malformed local GOT\n", lgi->dso->filename); + lgi->failed = 1; + return 0; + } + + return 1; +} + +/* A structure for iterating over global GOT entries. */ +struct mips_global_got_iterator { + /* The DSO containing the GOT. */ + DSO *dso; + + /* The size of a GOT entry. */ + GElf_Word entry_size; + + /* The virtual address of the current GOT entry. */ + GElf_Addr got_addr; + + /* The index of the associated entry in the dynamic symbol table. */ + GElf_Word sym_index; + + /* A pointer to the current GOT entry. */ + unsigned char *got_entry; + + /* The symbol associated with the current GOT entry. */ + GElf_Sym sym; + + /* True if we failed to read an entry correctly. */ + int failed; + + /* Used internally to obtain GOT_ENTRY and SYM. */ + struct data_iterator got_iterator; + struct data_iterator sym_iterator; +}; + +/* Set up GGI to iterate over DSO's global GOT. The caller should use + mips_get_global_got_entry to read the first entry. */ + +static inline void +mips_init_global_got_iterator (struct mips_global_got_iterator *ggi, DSO *dso) +{ + GElf_Word sym_size; + + ggi->dso = dso; + ggi->entry_size = gelf_fsize (dso->elf, ELF_T_WORD, 1, EV_CURRENT); + ggi->got_addr = (dso->info[DT_PLTGOT] + + (dso->info_DT_MIPS_LOCAL_GOTNO - 1) * ggi->entry_size); + ggi->sym_index = dso->info_DT_MIPS_GOTSYM - 1; + ggi->failed = 0; + + sym_size = gelf_fsize (dso->elf, ELF_T_SYM, 1, EV_CURRENT); + init_data_iterator (&ggi->got_iterator, dso, + ggi->got_addr + ggi->entry_size); + init_data_iterator (&ggi->sym_iterator, dso, + dso->info[DT_SYMTAB] + (ggi->sym_index + 1) * sym_size); +} + +/* Return true if GGI has not reached the end of the GOT and if the next + entry can be accessed. When returning true, use GGI's fields to + describe the next entry. */ + +static inline int +mips_get_global_got_entry (struct mips_global_got_iterator *ggi) +{ + ggi->sym_index++; + ggi->got_addr += ggi->entry_size; + if (ggi->sym_index >= ggi->dso->info_DT_MIPS_SYMTABNO) + return 0; + + ggi->got_entry = get_data_from_iterator (&ggi->got_iterator, + ggi->entry_size); + if (ggi->got_entry == NULL + || !get_sym_from_iterator (&ggi->sym_iterator, &ggi->sym)) + { + error (0, 0, "%s: Malformed global GOT\n", ggi->dso->filename); + ggi->failed = 1; + return 0; + } + + return 1; +} + +static int +mips_arch_adjust (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + struct mips_local_got_iterator lgi; + struct mips_global_got_iterator ggi; + GElf_Addr value; + + if (dso->info[DT_PLTGOT] == 0) + return 0; + + /* Adjust every local GOT entry by ADJUST. Every adjustment moves + the code and data, so we do not need to check START here. */ + mips_init_local_got_iterator (&lgi, dso); + while (mips_get_local_got_entry (&lgi)) + { + value = buf_read_une32 (dso, lgi.got_entry); + buf_write_ne32 (dso, lgi.got_entry, value + adjust); + } + + /* Adjust every global GOT entry. Referring to the table above: + + For [A, B, C]: Adjust the GOT entry if it contains st_value + and if the symbol's value will be adjusted. + + For [D]: Do nothing. SHN_COMMON entries never need adjusting. + + For [E, F]: Adjust the GOT entry if it does not contain st_value + -- in other words, if it is a type E entry that points to a lazy + binding stub -- or if the symbol's value will also be adjusted. */ + mips_init_global_got_iterator (&ggi, dso); + while (mips_get_global_got_entry (&ggi)) + { + value = buf_read_une32 (dso, ggi.got_entry); + if (ggi.sym.st_shndx != SHN_COMMON + && value >= start + && (value == ggi.sym.st_value + ? adjust_symbol_p (dso, &ggi.sym) + : ggi.sym.st_shndx != SHN_UNDEF)) + buf_write_ne32 (dso, ggi.got_entry, value + adjust); + } + + return lgi.failed || ggi.failed; +} + +static int +mips_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + switch (dyn->d_tag) + { + case DT_MIPS_TIME_STAMP: + case DT_MIPS_ICHECKSUM: + case DT_MIPS_IVERSION: + case DT_MIPS_CONFLICT: + case DT_MIPS_CONFLICTNO: + case DT_MIPS_LIBLIST: + case DT_MIPS_LIBLISTNO: + error (0, 0, "%s: File contains QuickStart information", dso->filename); + return 1; + + case DT_MIPS_BASE_ADDRESS: + case DT_MIPS_RLD_MAP: + case DT_MIPS_OPTIONS: + if (dyn->d_un.d_ptr >= start) + dyn->d_un.d_ptr += adjust; + return 1; + + case DT_MIPS_LOCAL_GOTNO: + case DT_MIPS_UNREFEXTNO: + case DT_MIPS_SYMTABNO: + case DT_MIPS_HIPAGENO: + case DT_MIPS_GOTSYM: + /* We don't change the layout of the GOT or symbol table. */ + return 1; + + case DT_MIPS_RLD_VERSION: + case DT_MIPS_FLAGS: + /* We don't change these properties. */ + return 1; + } + return 0; +} + +/* Read the addend for a relocation in DSO. If RELA is nonnull, + use its r_addend, otherwise read a 32-bit in-place addend from + address R_OFFSET. */ + +static inline uint32_t +mips_read_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela) +{ + return rela ? rela->r_addend : read_une32 (dso, r_offset); +} + +/* Like mips_read_addend, but change the addend to VALUE. */ + +static inline void +mips_write_addend (DSO *dso, GElf_Addr r_offset, GElf_Rela *rela, + uint32_t value) +{ + if (rela) + rela->r_addend = (int32_t) value; + else + write_ne32 (dso, r_offset, value); +} + +/* There is a relocation of type R_INFO against address R_OFFSET in DSO. + Adjust it so that virtual addresses >= START are increased by ADJUST + If the relocation is in a RELA section, RELA points to the relocation, + otherwise it is null. */ + +static int +mips_adjust_reloc (DSO *dso, GElf_Addr r_offset, GElf_Xword r_info, + GElf_Addr start, GElf_Addr adjust, GElf_Rela *rela) +{ + GElf_Addr value; + GElf_Word r_sym; + + if (GELF_R_TYPE (r_info) == R_MIPS_REL32) + { + r_sym = GELF_R_SYM (r_info); + if (r_sym < dso->info_DT_MIPS_GOTSYM) + { + /* glibc's dynamic linker adds the symbol's st_value and the + base address to the addend. It therefore treats all symbols + as being relative, even if they would normally be considered + absolute. For example, the special null symbol should always + have the value zero, even when the base address is nonzero, + but R_MIPS_REL32 relocations against the null symbol must + nevertheles be adjusted as if that symbol were relative. + The same would apply to SHN_ABS symbols too. + + Thus the result of the relocation calculation must always + be adjusted by ADJUST. (We do not need to check START because + every adjustment requested by the caller will affect all + legitimate local relocation values.) This means that we + should add ADJUST to the addend if and only if the symbol's + value is not being adjusted. + + In general, we can only check whether a symbol's value is + being adjusted by reading its entry in the dynamic symbol + table and then querying adjust_symbol_p. However, this + generality is fortunately not needed. Modern versions + of binutils will never generate R_MIPS_REL32 relocations + against symbols in the range [1, DT_MIPS_GOTSYM), so we + only need to handle relocations against the null symbol. */ + if (r_sym != 0) + { + error (0, 0, "%s: The prelinker does not support R_MIPS_REL32" + " relocs against local symbols", dso->filename); + return 1; + } + value = mips_read_addend (dso, r_offset, rela); + mips_write_addend (dso, r_offset, rela, value + adjust); + } + } + return 0; +} + +static int +mips_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, GElf_Addr adjust) +{ + return mips_adjust_reloc (dso, rel->r_offset, rel->r_info, + start, adjust, NULL); +} + +static int +mips_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, GElf_Addr adjust) +{ + return mips_adjust_reloc (dso, rela->r_offset, rela->r_info, + start, adjust, rela); +} + +/* Calculate relocation RELA as A + VALUE and store the result in DSO. */ + +static void +mips_prelink_32bit_reloc (DSO *dso, GElf_Rela *rela, GElf_Addr value) +{ + assert (rela != NULL); + write_ne32 (dso, rela->r_offset, value + rela->r_addend); +} + +/* There is a relocation of type R_INFO against address R_OFFSET in DSO. + Prelink the relocation field, using INFO to look up symbol values. + If the relocation is in a RELA section, RELA points to the relocation, + otherwise it is null. */ + +static int +mips_prelink_reloc (struct prelink_info *info, GElf_Addr r_offset, + GElf_Xword r_info, GElf_Rela *rela) +{ + DSO *dso; + GElf_Addr value; + GElf_Word r_sym; + int r_type; + + dso = info->dso; + r_sym = GELF_R_SYM (r_info); + r_type = GELF_R_TYPE (r_info); + switch (r_type) + { + case R_MIPS_NONE: + break; + + case R_MIPS_REL32: + /* An in-place R_MIPS_REL32 relocation against symbol 0 needs no + adjustment. */ + if (rela != NULL || GELF_R_SYM (r_info) != 0) + { + value = info->resolve (info, r_sym, r_type); + mips_prelink_32bit_reloc (dso, rela, value); + } + break; + + case R_MIPS_GLOB_DAT: + write_ne32 (dso, r_offset, info->resolve (info, r_sym, r_type)); + break; + + case R_MIPS_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_MIPS_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + /* These relocations will be resolved using a conflict. We need + not change the field value here. */ + break; + + case R_MIPS_TLS_DTPREL32: + value = info->resolve (info, r_sym, r_type); + mips_prelink_32bit_reloc (dso, rela, value - TLS_DTV_OFFSET); + break; + + case R_MIPS_TLS_TPREL32: + /* Relocations in a shared library will be resolved using a conflict. + We need not change the relocation field here. */ + if (dso->ehdr.e_type == ET_EXEC) + { + value = info->resolve (info, r_sym, r_type); + value += info->resolvetls->offset - TLS_TP_OFFSET; + mips_prelink_32bit_reloc (dso, rela, value); + } + break; + + default: + error (0, 0, "%s: Unknown MIPS relocation type %d", + dso->filename, (int) GELF_R_TYPE (r_info)); + return 1; + } + return 0; +} + +static int +mips_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + DSO *dso; + + /* Convert R_MIPS_REL32 relocations against global symbols into + R_MIPS_GLOB_DAT if the addend is zero. */ + dso = info->dso; + if (GELF_R_TYPE (rel->r_info) == R_MIPS_REL32 + && GELF_R_SYM (rel->r_info) >= dso->info_DT_MIPS_GOTSYM + && read_une32 (dso, rel->r_offset) == 0) + { + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_GLOB_DAT); + write_ne32 (dso, rel->r_offset, + info->resolve (info, GELF_R_SYM (rel->r_info), + GELF_R_TYPE (rel->r_info))); + return 2; + } + return mips_prelink_reloc (info, rel->r_offset, rel->r_info, NULL); +} + +static int +mips_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + return mips_prelink_reloc (info, rela->r_offset, rela->r_info, rela); +} + +/* CONFLICT is a conflict returned by prelink_conflict for a symbol + belonging to DSO. Set *TLS_OUT to the associated TLS information. + Return 1 on failure. */ + +static int +mips_get_tls (DSO *dso, struct prelink_conflict *conflict, + struct prelink_tls **tls_out) +{ + if (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL) + { + error (0, 0, "%s: R_MIPS_TLS not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + + *tls_out = conflict->lookup.tls; + return 0; +} + +/* There is a relocation of type R_INFO against address R_OFFSET in DSO. + See if the relocation field must be adjusted by a conflict when DSO + is used in the context described by INFO. Add a conflict entry if so. + If the relocation is in a RELA section, RELA points to the relocation, + otherwise it is null. */ + +static int +mips_prelink_conflict_reloc (DSO *dso, struct prelink_info *info, + GElf_Addr r_offset, GElf_Xword r_info, + GElf_Rela *rela) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *entry; + + conflict = prelink_conflict (info, GELF_R_SYM (r_info), + GELF_R_TYPE (r_info)); + if (conflict == NULL) + { + switch (GELF_R_TYPE (r_info)) + { + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_TPREL32: + tls = info->curtls; + if (tls == NULL) + return 0; + /* A relocation against symbol 0. A shared library cannot + know what the final module IDs or TP-relative offsets are, + so the executable must always have a conflict for them. */ + value = 0; + break; + default: + return 0; + } + } + else + { + /* DTPREL32 relocations just involve the symbol value; no other + TLS information is needed. Ignore conflicts created from a + lookup of type RTYPE_CLASS_TLS if no real conflict exists. */ + if (GELF_R_TYPE (r_info) == R_MIPS_TLS_DTPREL32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + /* VALUE now contains the final symbol value. Change it to the + value we want to store at R_OFFSET. */ + switch (GELF_R_TYPE (r_info)) + { + case R_MIPS_REL32: + value += mips_read_addend (dso, r_offset, rela); + break; + + case R_MIPS_GLOB_DAT: + break; + + case R_MIPS_TLS_DTPMOD32: + if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1) + return 1; + value = tls->modid; + break; + + case R_MIPS_TLS_DTPREL32: + value += mips_read_addend (dso, r_offset, rela) - TLS_DTV_OFFSET; + break; + + case R_MIPS_TLS_TPREL32: + if (conflict != NULL && mips_get_tls (dso, conflict, &tls) == 1) + return 1; + value += (mips_read_addend (dso, r_offset, rela) + + tls->offset - TLS_TP_OFFSET); + break; + + default: + error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename, + (int) GELF_R_TYPE (r_info)); + return 1; + } + /* Create and initialize a conflict entry. */ + entry = prelink_conflict_add_rela (info); + if (entry == NULL) + return 1; + entry->r_addend = (int32_t) value; + entry->r_offset = r_offset; + entry->r_info = GELF_R_INFO (0, R_MIPS_REL32); + return 0; +} + +static int +mips_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + return mips_prelink_conflict_reloc (dso, info, rel->r_offset, + rel->r_info, NULL); +} + +static int +mips_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + return mips_prelink_conflict_reloc (dso, info, rela->r_offset, + rela->r_info, rela); +} + +static int +mips_arch_prelink_conflict (DSO *dso, struct prelink_info *info) +{ + struct mips_global_got_iterator ggi; + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *entry; + + if (dso->info[DT_PLTGOT] == 0) + return 0; + + /* Add a conflict for every global GOT entry that does not hold the + right value, either because of a conflict, or because the DSO has + a lazy binding stub for a symbol that it also defines. */ + mips_init_global_got_iterator (&ggi, dso); + while (mips_get_global_got_entry (&ggi)) + { + conflict = prelink_conflict (info, ggi.sym_index, R_MIPS_REL32); + if (conflict != NULL) + value = conflict_lookup_value (conflict); + else if (ggi.sym.st_shndx != SHN_UNDEF + && ggi.sym.st_shndx != SHN_COMMON) + value = ggi.sym.st_value; + else + continue; + if (buf_read_une32 (dso, ggi.got_entry) != value) + { + entry = prelink_conflict_add_rela (info); + if (entry == NULL) + return 1; + entry->r_addend = (int32_t) value; + entry->r_offset = ggi.got_addr; + entry->r_info = GELF_R_INFO (0, R_MIPS_REL32); + } + } + + return ggi.failed; +} + +static int +mips_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_MIPS_REL32: + buf_write_ne32 (info->dso, buf, rela->r_addend); + break; + + default: + abort (); + } + return 0; +} + +/* BUF points to a 32-bit field in DSO that is subject to relocation. + If the relocation is in a RELA section, RELA points to the relocation, + otherwise it is null. Add the addend to ADJUSTMENT and install the + result. */ + +static inline void +mips_apply_adjustment (DSO *dso, GElf_Rela *rela, char *buf, + GElf_Addr adjustment) +{ + if (rela) + adjustment += rela->r_addend; + else + adjustment += buf_read_une32 (dso, buf); + buf_write_ne32 (dso, buf, adjustment); +} + +static int +mips_apply_reloc (struct prelink_info *info, GElf_Xword r_info, + GElf_Rela *rela, char *buf) +{ + DSO *dso; + + dso = info->dso; + switch (GELF_R_TYPE (r_info)) + { + case R_MIPS_NONE: + break; + + case R_MIPS_REL32: + mips_apply_adjustment (dso, rela, buf, + info->resolve (info, GELF_R_SYM (r_info), + GELF_R_TYPE (r_info))); + break; + + default: + return 1; + } + return 0; +} + +static int +mips_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + return mips_apply_reloc (info, rel->r_info, NULL, buf); +} + +static int +mips_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + return mips_apply_reloc (info, rela->r_info, rela, buf); +} + +static int +mips_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + rela->r_offset = rel->r_offset; + rela->r_info = rel->r_info; + switch (GELF_R_TYPE (rel->r_info)) + { + case R_MIPS_REL32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + /* These relocations have an in-place addend. */ + rela->r_addend = (int32_t) read_une32 (dso, rel->r_offset); + break; + + case R_MIPS_NONE: + case R_MIPS_GLOB_DAT: + case R_MIPS_TLS_DTPMOD32: + /* These relocations have no addend. */ + rela->r_addend = 0; + break; + + default: + error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename, + (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + return 0; +} + +static int +mips_rela_to_rel (DSO *dso, GElf_Rela *rela, GElf_Rel *rel) +{ + rel->r_offset = rela->r_offset; + rel->r_info = rela->r_info; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_MIPS_NONE: + break; + + case R_MIPS_REL32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + /* These relocations have an in-place addend. */ + write_ne32 (dso, rela->r_offset, rela->r_addend); + break; + + case R_MIPS_GLOB_DAT: + case R_MIPS_TLS_DTPMOD32: + /* These relocations have no addend. */ + write_ne32 (dso, rela->r_offset, 0); + break; + + default: + error (0, 0, "%s: Unknown MIPS relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +mips_need_rel_to_rela (DSO *dso, int first, int last) +{ + Elf_Data *data; + Elf_Scn *scn; + Elf32_Rel *rel, *relend; + int n; + + for (n = first; n <= last; n++) + { + data = NULL; + scn = dso->scn[n]; + while ((data = elf_getdata (scn, data)) != NULL) + { + rel = (Elf32_Rel *) data->d_buf; + relend = rel + data->d_size / sizeof (Elf32_Rel); + for (; rel < relend; rel++) + switch (ELF32_R_TYPE (rel->r_info)) + { + case R_MIPS_NONE: + break; + + case R_MIPS_REL32: + /* The SVR4 definition was designed to allow exactly the + sort of prelinking we want to do here, in combination + with Quickstart. Unfortunately, glibc's definition + makes it impossible for relocations against anything + other than the null symbol. We get around this for + zero addends by using a R_MIPS_GLOB_DAT relocation + instead, where R_MIPS_GLOB_DAT is a GNU extension + added specifically for this purpose. */ + if (ELF32_R_SYM (rel->r_info) != 0 + && (ELF32_R_SYM (rel->r_info) < dso->info_DT_MIPS_GOTSYM + || read_une32 (dso, rel->r_offset) != 0)) + return 1; + break; + + case R_MIPS_GLOB_DAT: + /* This relocation has no addend. */ + break; + + case R_MIPS_TLS_DTPMOD32: + /* The relocation will be resolved using a conflict. */ + break; + + case R_MIPS_TLS_DTPREL32: + /* We can prelink these fields, and the addend is relative + to the symbol value. A RELA entry is needed. */ + return 1; + + case R_MIPS_TLS_TPREL32: + /* Relocations in shared libraries will be resolved by a + conflict. Relocations in executables will not, and the + addend is relative to the symbol value. */ + if (dso->ehdr.e_type == ET_EXEC) + return 1; + break; + + default: + error (0, 0, "%s: Unknown MIPS relocation type %d", + dso->filename, (int) GELF_R_TYPE (rel->r_info)); + return 1; + } + } + } + return 0; +} + +static int +mips_reloc_size (int reloc_type) +{ + return 4; +} + +static int +mips_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_MIPS_TLS_DTPMOD32: + case R_MIPS_TLS_DTPREL32: + case R_MIPS_TLS_TPREL32: + return RTYPE_CLASS_TLS; + default: + /* MIPS lazy resolution stubs are local to the containing object, + so SHN_UNDEF symbols never participate in symbol lookup. */ + return RTYPE_CLASS_PLT; + } +} + +static int +mips_arch_prelink (struct prelink_info *info) +{ + struct mips_global_got_iterator ggi; + DSO *dso; + GElf_Addr value; + + dso = info->dso; + if (dso->info[DT_PLTGOT] == 0) + return 0; + + /* Install Quickstart values for all global GOT entries of type A-D + in the table above. */ + mips_init_global_got_iterator (&ggi, dso); + while (mips_get_global_got_entry (&ggi)) + { + value = info->resolve (info, ggi.sym_index, R_MIPS_REL32); + if (ggi.sym.st_shndx == SHN_UNDEF + || ggi.sym.st_shndx == SHN_COMMON) + buf_write_ne32 (dso, ggi.got_entry, value); + else + { + /* Type E and F in the table above. We cannot install Quickstart + values for type E, but we should never need to in executables, + because an executable should not use lazy binding stubs for + symbols it defines itself. Although we could in theory just + discard any such stub address, it goes against the principle + that prelinking should be reversible. + + When type E entries occur in shared libraries, we can fix + them up using conflicts. + + Type F entries should never need a Quickstart value -- the + current value should already be correct. However, the conflict + code will cope correctly with malformed type F entries in + shared libraries, so we only complain about executables here. */ + if (dso->ehdr.e_type == ET_EXEC + && value != buf_read_une32 (dso, ggi.got_entry)) + { + error (0, 0, "%s: The global GOT entries for defined symbols" + " do not match their st_values\n", dso->filename); + return 1; + } + } + } + return ggi.failed; +} + +static int +mips_arch_undo_prelink (DSO *dso) +{ + struct mips_global_got_iterator ggi; + + if (dso->info[DT_PLTGOT] == 0) + return 0; + + mips_init_global_got_iterator (&ggi, dso); + while (mips_get_global_got_entry (&ggi)) + if (ggi.sym.st_shndx == SHN_UNDEF) + /* Types A-C in the table above. */ + buf_write_ne32 (dso, ggi.got_entry, ggi.sym.st_value); + else if (ggi.sym.st_shndx == SHN_COMMON) + /* Type D in the table above. */ + buf_write_ne32 (dso, ggi.got_entry, 0); + return ggi.failed; +} + +static int +mips_undo_prelink_rel (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr) +{ + /* Convert R_MIPS_GLOB_DAT relocations back into R_MIPS_REL32 + relocations. Ideally we'd have some mechanism for recording + these changes in the undo section, but in the absence of that, + it's better to assume that the original relocation was + R_MIPS_REL32; R_MIPS_GLOB_DAT was added specifically for the + prelinker and shouldn't be used in non-prelinked binaries. */ + if (GELF_R_TYPE (rel->r_info) == R_MIPS_GLOB_DAT) + { + write_ne32 (dso, rel->r_offset, 0); + rel->r_info = GELF_R_INFO (GELF_R_SYM (rel->r_info), R_MIPS_REL32); + return 2; + } + return 0; +} + +PL_ARCH = { + .name = "MIPS", + .class = ELFCLASS32, + .machine = EM_MIPS, + .max_reloc_size = 4, + .dynamic_linker = "/lib/ld.so.1", + /* MIPS does not use COPY relocs or jump slots. Pick a value outside + the ELF32_R_TYPE range. */ + .R_COPY = ~0U, + .R_JMP_SLOT = ~0U, + /* R_MIPS_REL32 relocations against symbol 0 do act as relative relocs, + but those against other symbols don't. */ + .R_RELATIVE = ~0U, + .arch_adjust = mips_arch_adjust, + .adjust_dyn = mips_adjust_dyn, + .adjust_rel = mips_adjust_rel, + .adjust_rela = mips_adjust_rela, + .prelink_rel = mips_prelink_rel, + .prelink_rela = mips_prelink_rela, + .prelink_conflict_rel = mips_prelink_conflict_rel, + .prelink_conflict_rela = mips_prelink_conflict_rela, + .arch_prelink_conflict = mips_arch_prelink_conflict, + .apply_conflict_rela = mips_apply_conflict_rela, + .apply_rel = mips_apply_rel, + .apply_rela = mips_apply_rela, + .rel_to_rela = mips_rel_to_rela, + .rela_to_rel = mips_rela_to_rel, + .need_rel_to_rela = mips_need_rel_to_rela, + .reloc_size = mips_reloc_size, + .reloc_class = mips_reloc_class, + .arch_prelink = mips_arch_prelink, + .arch_undo_prelink = mips_arch_undo_prelink, + .undo_prelink_rel = mips_undo_prelink_rel, + /* Although TASK_UNMAPPED_BASE is 0x2aaa8000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x2c000000, + .mmap_end = 0x3c000000, + .max_page_size = 0x10000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-ppc.c b/trunk/src/arch-ppc.c new file mode 100644 index 0000000..5608750 --- /dev/null +++ b/trunk/src/arch-ppc.c @@ -0,0 +1,1154 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" +#include "layout.h" + +#ifndef DT_PPC_GOT +# define DT_PPC_GOT (DT_LOPROC + 0) +#endif + +#define DT_PPC_GOT_BIT DT_LOPROC_BIT + +static int +ppc_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PPC_GOT) + { + Elf32_Addr data; + + data = read_ube32 (dso, dyn->d_un.d_ptr); + /* DT_PPC_GOT[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ube32 (dso, dyn->d_un.d_ptr + 4); + /* DT_PPC_GOT[1] points to .glink in prelinked libs. */ + if (data && data >= start) + write_be32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + + if (dyn->d_un.d_ptr >= start) + { + dyn->d_un.d_ptr += adjust; + return 1; + } + } + else if (dyn->d_tag == DT_PLTGOT + && !dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".got") + && dso->shdr[i].sh_size >= 16) + { + Elf32_Addr data, addr; + int step; + + /* If .got[1] points to _DYNAMIC, it needs to be adjusted. + Other possible locations of the .got header are at the + end of .got or around offset 32768 in it. */ + for (addr = dso->shdr[i].sh_addr, step = 0; step < 18; step++) + { + if (read_ube32 (dso, addr) == 0x4e800021 + && (data = read_ube32 (dso, addr + 4)) + == dso->shdr[n].sh_addr + && data >= start + && read_ube32 (dso, addr + 8) == 0 + && read_ube32 (dso, addr + 12) == 0) + { + /* Probably should use here a check that neither of + the 4 addresses contains a dynamic relocation against + it. */ + write_be32 (dso, addr + 4, data + adjust); + break; + } + if (step == 0) + addr = dso->shdr[i].sh_addr + dso->shdr[i].sh_size - 16; + else if (step == 1) + { + if (dso->shdr[i].sh_size >= 32768 - 32) + addr = dso->shdr[i].sh_addr + 32768 - 32 - 16; + else + break; + } + else + { + addr += 4; + if (addr + 16 + > dso->shdr[i].sh_addr + dso->shdr[i].sh_size) + break; + } + } + break; + } + } + + return 0; +} + +static int +ppc_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: PowerPC doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE) + { + if ((Elf32_Word) rela->r_addend >= start) + rela->r_addend += (Elf32_Sword) adjust; + } + if (GELF_R_TYPE (rela->r_info) == R_PPC_JMP_SLOT + && dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + { + Elf32_Addr data = read_ube32 (dso, rela->r_offset); + if (data >= start) + write_be32 (dso, rela->r_offset, data + adjust); + } + return 0; +} + +static int +ppc_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: PowerPC doesn't support REL relocs", info->dso->filename); + return 1; +} + +static void +ppc_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr value) +{ + Elf32_Sword disp = value - rela->r_offset; + + if (disp >= -0x2000000 && disp < 0x2000000) + { + /* b value */ + write_be32 (dso, rela->r_offset, 0x48000000 | (disp & 0x3fffffc)); + } + else if ((Elf32_Addr) value >= -0x2000000 || value < 0x2000000) + { + /* ba value */ + write_be32 (dso, rela->r_offset, 0x48000002 | (value & 0x3fffffc)); + } + else + { + Elf32_Addr plt = dso->info[DT_PLTGOT]; + + if (rela->r_offset - plt < (8192 * 2 + 18) * 4) + { + Elf32_Word index = (rela->r_offset - plt - 18 * 4) / (4 * 2); + Elf32_Word count = dso->info[DT_PLTRELSZ] / sizeof (Elf32_Rela); + Elf32_Addr data; + + data = plt + (18 + 2 * count + + (count > 8192 ? (count - 8192) * 2 : 0)) * 4; + write_be32 (dso, data + 4 * index, value); + /* li %r11, 4*index + b .plt+0 */ + write_be32 (dso, rela->r_offset, + 0x39600000 | ((index * 4) & 0xffff)); + write_be32 (dso, rela->r_offset + 4, + 0x48000000 | ((plt - rela->r_offset - 4) & 0x3fffffc)); + } + else + { + /* lis %r12, %hi(finaladdr) + addi %r12, %r12, %lo(finaladdr) + mtctr %r12 + bctr */ + write_be32 (dso, rela->r_offset, + 0x39800000 | (((value + 0x8000) >> 16) & 0xffff)); + write_be32 (dso, rela->r_offset + 4, 0x398c0000 | (value & 0xffff)); + write_be32 (dso, rela->r_offset + 8, 0x7d8903a6); + write_be32 (dso, rela->r_offset + 12, 0x4e800420); + } + } +} + +static int +ppc_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_PPC_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE) + { + write_be32 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_GLOB_DAT: + case R_PPC_ADDR32: + case R_PPC_UADDR32: + write_be32 (dso, rela->r_offset, value); + break; + case R_PPC_DTPREL32: + write_be32 (dso, rela->r_offset, value - 0x8000); + break; + case R_PPC_JMP_SLOT: + if (dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + write_be32 (dso, rela->r_offset, value); + else + ppc_fixup_plt (dso, rela, value); + break; + case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_ADDR16_LO: + write_be16 (dso, rela->r_offset, value); + break; + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + write_be16 (dso, rela->r_offset, value - 0x8000); + break; + case R_PPC_ADDR16_HI: + case R_PPC_DTPREL16_HA: + write_be16 (dso, rela->r_offset, value >> 16); + break; + case R_PPC_DTPREL16_HI: + write_be16 (dso, rela->r_offset, (value - 0x8000) >> 16); + break; + case R_PPC_ADDR16_HA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16); + break; + case R_PPC_ADDR24: + write_be32 (dso, rela->r_offset, + (value & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003)); + break; + case R_PPC_ADDR14: + write_be32 (dso, rela->r_offset, + (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffff0003)); + break; + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + write_be32 (dso, rela->r_offset, + (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffdf0003) + | ((((GELF_R_TYPE (rela->r_info) == R_PPC_ADDR14_BRTAKEN) + << 21) + ^ (value >> 10)) & 0x00200000)); + break; + case R_PPC_REL24: + write_be32 (dso, rela->r_offset, + ((value - rela->r_offset) & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003)); + break; + case R_PPC_REL32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + /* DTPMOD32 and TPREL* is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_PPC_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_PPC_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_PPC_TPREL32: + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + { + value += info->resolvetls->offset - 0x7000; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_TPREL32: + write_be32 (dso, rela->r_offset, value); + break; + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + write_be16 (dso, rela->r_offset, value); + break; + case R_PPC_TPREL16_HI: + write_be16 (dso, rela->r_offset, value >> 16); + break; + case R_PPC_TPREL16_HA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16); + break; + } + } + break; + case R_PPC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_PPC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +ppc_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_ADDR32: + case R_PPC_UADDR32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_PPC_ADDR16: + case R_PPC_UADDR16: + buf_write_be16 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +ppc_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: PowerPC doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +ppc_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_NONE: + break; + case R_PPC_GLOB_DAT: + case R_PPC_ADDR32: + case R_PPC_UADDR32: + buf_write_be32 (buf, value); + break; + case R_PPC_ADDR16_HA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC_ADDR16_HI: + value = value >> 16; + /* FALLTHROUGH */ + case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_ADDR16_LO: + buf_write_be16 (buf, value); + break; + case R_PPC_ADDR24: + buf_write_be32 (buf, (value & 0x03fffffc) + | (buf_read_ube32 (buf) & 0xfc000003)); + break; + case R_PPC_ADDR14: + buf_write_be32 (buf, (value & 0xfffc) + | (buf_read_ube32 (buf) & 0xffff0003)); + break; + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + buf_write_be32 (buf, (value & 0xfffc) + | (buf_read_ube32 (buf) & 0xffdf0003) + | ((((GELF_R_TYPE (rela->r_info) + == R_PPC_ADDR14_BRTAKEN) << 21) + ^ (value >> 10)) & 0x00200000)); + break; + case R_PPC_REL24: + buf_write_be32 (buf, ((value - rela->r_offset) & 0x03fffffc) + | (buf_read_ube32 (buf) & 0xfc000003)); + break; + case R_PPC_REL32: + buf_write_be32 (buf, value - rela->r_offset); + break; + case R_PPC_RELATIVE: + error (0, 0, "%s: R_PPC_RELATIVE in ET_EXEC object?", + info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +ppc_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: PowerPC doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + int r_type; + + if (GELF_R_TYPE (rela->r_info) == R_PPC_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_PPC_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPREL relocs need conflicts. */ + case R_PPC_DTPMOD32: + case R_PPC_TPREL32: + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPREL wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_DTPREL32: + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_DTPREL16_HA: + return 0; + } + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + value += rela->r_addend; + r_type = GELF_R_TYPE (rela->r_info); + switch (r_type) + { + case R_PPC_GLOB_DAT: + r_type = R_PPC_ADDR32; + break; + case R_PPC_ADDR32: + case R_PPC_UADDR32: + break; + case R_PPC_JMP_SLOT: + if (dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + r_type = R_PPC_ADDR32; + break; + case R_PPC_ADDR16_HA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC_ADDR16_HI: + value = value >> 16; + /* FALLTHROUGH */ + case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_ADDR16_LO: + if (r_type != R_PPC_UADDR16) + r_type = R_PPC_ADDR16; + value = ((value & 0xffff) ^ 0x8000) - 0x8000; + break; + case R_PPC_ADDR24: + r_type = R_PPC_ADDR32; + value = (value & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003); + break; + case R_PPC_ADDR14: + r_type = R_PPC_ADDR32; + value = (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffff0003); + break; + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + r_type = R_PPC_ADDR32; + value = (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffdf0003) + | ((((r_type == R_PPC_ADDR14_BRTAKEN) << 21) + ^ (value >> 10)) & 0x00200000); + break; + case R_PPC_REL24: + r_type = R_PPC_ADDR32; + value = ((value - rela->r_offset) & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003); + break; + case R_PPC_REL32: + r_type = R_PPC_ADDR32; + value -= rela->r_offset; + break; + case R_PPC_DTPMOD32: + case R_PPC_DTPREL32: + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_DTPREL16_HA: + case R_PPC_TPREL32: + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + r_type = R_PPC_ADDR16; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_DTPMOD32: + r_type = R_PPC_ADDR32; + value = tls->modid; + break; + case R_PPC_DTPREL32: + r_type = R_PPC_ADDR32; + value -= 0x8000; + break; + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + value -= 0x8000; + break; + case R_PPC_DTPREL16_HI: + value = (value - 0x8000) >> 16; + break; + case R_PPC_DTPREL16_HA: + value >>= 16; + break; + case R_PPC_TPREL32: + r_type = R_PPC_ADDR32; + value += tls->offset - 0x7000; + break; + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + value += tls->offset - 0x7000; + break; + case R_PPC_TPREL16_HI: + value = (value + tls->offset - 0x7000) >> 16; + break; + case R_PPC_TPREL16_HA: + value = (value + tls->offset - 0x7000 + 0x8000) >> 16; + break; + } + if (r_type == R_PPC_ADDR16) + value = ((value & 0xffff) ^ 0x8000) - 0x8000; + break; + default: + error (0, 0, "%s: Unknown PowerPC relocation type %d", dso->filename, + r_type); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + ret->r_addend = (Elf32_Sword) value; + return 0; +} + +static int +ppc_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: PowerPC doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +ppc_arch_pre_prelink (DSO *dso) +{ + Elf_Data *data = NULL; + Elf_Scn *scn; + GElf_Dyn dyn; + Elf32_Addr val; + int i; + + if (!dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + return 0; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + + scn = dso->scn[dso->dynamic]; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + assert (dyn.d_tag != DT_NULL); + if (dyn.d_tag == DT_PPC_GOT) + break; + } + if (ndx < maxndx) + break; + } + + /* DT_PPC_GOT[1] should point to .glink in prelinked libs. */ + val = read_ube32 (dso, dyn.d_un.d_ptr + 4); + if (val) + return 0; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + + val = read_ube32 (dso, dso->shdr[i].sh_addr); + write_be32 (dso, dyn.d_un.d_ptr + 4, val); + + return 0; +} + +static int +ppc_arch_prelink (struct prelink_info *info) +{ + DSO *dso = info->dso; + Elf32_Addr plt = dso->info[DT_PLTGOT]; + + if (plt && !dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + { + Elf32_Word count = dso->info[DT_PLTRELSZ] / sizeof (Elf32_Rela); + Elf32_Addr data; + + data = plt + (18 + 2 * count + + (count > 8192 ? (count - 8192) * 2 : 0)) * 4; + + /* addis %r11, %r11, %hi(data) + lwz %r11, %r11, %lo(data) + mtctr %r11 + bctr */ + write_be32 (dso, plt, 0x3d6b0000 | (((data + 0x8000) >> 16) & 0xffff)); + write_be32 (dso, plt + 4, 0x816b0000 | (data & 0xffff)); + write_be32 (dso, plt + 8, 0x7d6903a6); + write_be32 (dso, plt + 12, 0x4e800420); + } + return 0; +} + +static int +ppc_arch_undo_prelink (DSO *dso) +{ + Elf_Data *data = NULL; + Elf_Scn *scn; + GElf_Dyn dyn; + Elf32_Addr val, addr, endaddr; + int i; + + if (!dynamic_info_is_set (dso, DT_PPC_GOT_BIT)) + return 0; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + + scn = dso->scn[dso->dynamic]; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + assert (dyn.d_tag != DT_NULL); + if (dyn.d_tag == DT_PPC_GOT) + break; + } + if (ndx < maxndx) + break; + } + + /* DT_PPC_GOT[1] should point to .glink in prelinked libs. */ + val = read_ube32 (dso, dyn.d_un.d_ptr + 4); + if (!val) + return 0; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt")) + break; + + if (i == dso->ehdr.e_shnum || (dso->shdr[i].sh_size & 3)) + return 0; + + addr = dso->shdr[i].sh_addr; + endaddr = addr + dso->shdr[i].sh_size; + for (; addr < endaddr; addr += 4, val += 4) + write_be32 (dso, addr, val); + + write_be32 (dso, dyn.d_un.d_ptr + 4, 0); + + return 0; +} + + +static int +ppc_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC_NONE: + return 0; + case R_PPC_RELATIVE: + case R_PPC_GLOB_DAT: + case R_PPC_ADDR32: + case R_PPC_UADDR32: + case R_PPC_REL32: + case R_PPC_DTPMOD32: + case R_PPC_DTPREL32: + case R_PPC_TPREL32: + write_be32 (dso, rela->r_offset, 0); + break; + case R_PPC_JMP_SLOT: + /* .plt section will become SHT_NOBITS if DT_PPC_GOT is not present, + otherwise .plt section will be unprelinked in + ppc_arch_undo_prelink. */ + return 0; + case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_DTPREL16: + case R_PPC_TPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_TPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_TPREL16_HI: + case R_PPC_DTPREL16_HA: + case R_PPC_TPREL16_HA: + write_be16 (dso, rela->r_offset, 0); + break; + case R_PPC_ADDR24: + case R_PPC_REL24: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xfc000003); + break; + case R_PPC_ADDR14: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffff0003); + break; + case R_PPC_ADDR14_BRTAKEN: + case R_PPC_ADDR14_BRNTAKEN: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffdf0003); + break; + case R_PPC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_PPC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +ppc_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_PPC_ADDR16: + case R_PPC_UADDR16: + case R_PPC_ADDR16_LO: + case R_PPC_ADDR16_HI: + case R_PPC_ADDR16_HA: + case R_PPC_DTPREL16: + case R_PPC_DTPREL16_LO: + case R_PPC_DTPREL16_HI: + case R_PPC_DTPREL16_HA: + case R_PPC_TPREL16: + case R_PPC_TPREL16_LO: + case R_PPC_TPREL16_HI: + case R_PPC_TPREL16_HA: + return 2; + default: + break; + } + return 4; +} + +static int +ppc_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_PPC_COPY: return RTYPE_CLASS_COPY; + case R_PPC_JMP_SLOT: return RTYPE_CLASS_PLT; + default: + if (reloc_type >= R_PPC_DTPMOD32 && reloc_type <= R_PPC_DTPREL32) + return RTYPE_CLASS_TLS; + return RTYPE_CLASS_VALID; + } +} + +/* Library memory regions in order of precedence: + 0xe800000 .. 0x10000000 top to bottom + 0x40000 .. 0xe800000 bottom to top + 0x18000000 .. 0x30000000 bottom to top */ + +#define REG0S 0x0e800000 +#define REG0E 0x10000000 +#define REG1S 0x00040000 +#define REG1E REG0S +#define REG2S 0x18000000 +#define REG2E 0x30000000 + +struct ppc_layout_data +{ + int cnt; + struct prelink_entry e[3]; + Elf32_Addr mmap_start, first_start, last_start; + struct + { + struct prelink_entry *e; + Elf32_Addr base, end, layend; + } ents[0]; +}; + +static inline void +list_append (struct prelink_entry *x, struct prelink_entry *e) +{ + x->prev->next = e; + e->prev = x->prev; + e->next = NULL; + x->prev = e; +} + +static int +addr_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + + if (a->base < b->base) + return -1; + else if (a->base > b->base) + return 1; + if (a->layend < b->layend) + return -1; + else if (a->layend > b->layend) + return 1; + return 0; +} + +static void +list_sort (struct prelink_entry *x) +{ + int cnt, i; + struct prelink_entry *e; + struct prelink_entry **a; + + if (x->next == NULL) + return; + for (cnt = 0, e = x->next; e != NULL; e = e->next) + ++cnt; + a = alloca (cnt * sizeof (*a)); + for (i = 0, e = x->next; e != NULL; e = e->next) + a[i++] = e; + qsort (a, cnt, sizeof (*a), addr_cmp); + x->next = NULL; + x->prev = x; + for (i = 0; i < cnt; ++i) + list_append (x, a[i]); +} + +static int +ppc_layout_libs_pre (struct layout_libs *l) +{ + Elf32_Addr mmap_start = l->mmap_start - REG1S; + Elf32_Addr first_start = REG0S, last_start = REG2S; + struct prelink_entry *e, e0, *next = NULL; + struct ppc_layout_data *pld; + int cnt; + + mmap_start = REG0E - (mmap_start & 0xff0000); + for (cnt = 0, e = l->list; e != NULL; e = e->next, ++cnt) + { + if (e->base < mmap_start && e->layend > mmap_start) + mmap_start = (e->layend + 0xffff) & ~0xffff; + if (e->base < REG0S && e->layend > REG0S && first_start > e->base) + first_start = e->base; + if (e->base < REG0E && e->layend > REG2S && last_start < e->layend) + last_start = e->layend; + } + if (mmap_start > REG0E) + mmap_start = REG0E; + + pld = calloc (sizeof (*pld) + cnt * sizeof (pld->ents[0]), 1); + if (pld == NULL) + error (EXIT_FAILURE, ENOMEM, "Cannot lay libraries out"); + + l->arch_data = pld; + memset (&e0, 0, sizeof (e0)); + e0.prev = &e0; + pld->cnt = cnt; + pld->e[0].u.tmp = -1; + pld->e[0].base = REG1S + REG0E - mmap_start; + pld->e[0].end = pld->e[0].base; + pld->e[0].layend = pld->e[0].end; + pld->e[0].prev = &pld->e[0]; + pld->e[1].u.tmp = -1; + pld->e[1].base = pld->e[0].end + mmap_start - REG0S; + pld->e[1].end = pld->e[1].base; + pld->e[1].layend = pld->e[1].end; + pld->e[1].prev = &pld->e[1]; + pld->e[2].u.tmp = -1; + pld->e[2].base = pld->e[1].end + first_start - REG1S; + pld->e[2].end = pld->e[1].base; + pld->e[2].layend = pld->e[2].end; + pld->e[2].prev = &pld->e[2]; + for (cnt = 0, e = l->list; e != NULL; e = next, ++cnt) + { + next = e->next; + pld->ents[cnt].e = e; + pld->ents[cnt].base = e->base; + pld->ents[cnt].end = e->end; + pld->ents[cnt].layend = e->layend; + if (e->layend <= REG0S) + { + if (e->base < REG1S) + e->base = REG1S; + else if (e->base > first_start) + e->base = first_start; + if (e->layend < REG1S) + e->layend = REG1S; + else if (e->layend > first_start) + e->layend = first_start; + e->base += pld->e[1].end - REG1S; + e->layend += pld->e[1].end - REG1S; + list_append (&pld->e[1], e); + } + else if (e->base < mmap_start) + { + if (e->base < REG0S) + e->base = REG0S; + if (e->layend > mmap_start) + e->layend = mmap_start; + e->base = pld->e[0].end + mmap_start - e->layend; + e->layend = pld->e[0].layend + mmap_start - pld->ents[cnt].base; + list_append (&pld->e[0], e); + } + else if (e->base < REG0E) + { + if (e->layend > REG0E) + e->layend = REG0E; + e->base = REG1S + REG0E - e->layend; + e->layend = REG1S + REG0E - pld->ents[cnt].base; + list_append (&e0, e); + } + else if (e->layend >= last_start) + { + if (e->base < last_start) + e->base = last_start; + e->base += pld->e[2].end - last_start; + e->layend += pld->e[2].end - last_start; + list_append (&pld->e[2], e); + } + e->end = e->layend; + } + + list_sort (&pld->e[0]); + if (e0.next == NULL) + l->list = &pld->e[0]; + else + { + list_sort (&e0); + l->list = e0.next; + l->list->prev = pld->e[0].prev; + e0.prev->next = &pld->e[0]; + pld->e[0].prev = e0.prev; + } + + e0.prev = l->list->prev; + l->list->prev = pld->e[1].prev; + e0.prev->next = &pld->e[1]; + pld->e[1].prev = e0.prev; + + e0.prev = l->list->prev; + l->list->prev = pld->e[2].prev; + e0.prev->next = &pld->e[2]; + pld->e[2].prev = e0.prev; + + pld->mmap_start = mmap_start; + pld->first_start = first_start; + pld->last_start = last_start; + + l->mmap_start = REG1S; + l->mmap_fin = pld->e[2].end + REG2E - last_start; + l->mmap_end = l->mmap_fin; + l->fakecnt = 3; + l->fake = pld->e; + + return 0; +} + +static int +ppc_layout_libs_post (struct layout_libs *l) +{ + struct prelink_entry *e; + struct ppc_layout_data *pld = (struct ppc_layout_data *) l->arch_data; + Elf32_Addr base, end; + int i; + + /* First fix up base and end fields we saved. */ + for (i = 0; i < pld->cnt; ++i) + { + pld->ents[i].e->base = pld->ents[i].base; + pld->ents[i].e->layend = pld->ents[i].layend; + pld->ents[i].e->end = pld->ents[i].end; + pld->ents[i].e->done |= 0x40; + } + pld->e[0].done |= 0x40; + pld->e[1].done |= 0x40; + pld->e[2].done |= 0x40; + + /* Now fix up the newly created items. */ + for (e = l->list; e != NULL; e = e->next) + if (e->done & 0x40) + e->done &= ~0x40; + else + { + base = e->base; + end = e->layend; + if (e->base < pld->e[0].base) + { + e->base = REG1S + REG0E - end; + e->end += e->base - base; + e->layend = REG1S + REG0E - base; + } + else if (e->base < pld->e[1].base) + { + e->base = pld->e[0].end + pld->mmap_start - end; + e->end += e->base - base; + e->layend = pld->e[0].end + pld->mmap_start - base; + } + else if (e->base < pld->e[2].base) + { + e->base -= pld->e[1].end - REG1S; + e->end -= pld->e[1].end - REG1S; + e->layend -= pld->e[1].end - REG1S; + } + else + { + e->base -= pld->e[2].end - pld->last_start; + e->end -= pld->e[2].end - pld->last_start; + e->layend -= pld->e[2].end - pld->last_start; + } + } + + for (i = 0; i < pld->cnt; ++i) + pld->ents[i].e->done &= ~0x40; + + free (l->arch_data); + return 0; +} + +PL_ARCH = { + .name = "PowerPC", + .class = ELFCLASS32, + .machine = EM_PPC, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_PPC_JMP_SLOT, + .R_COPY = R_PPC_COPY, + .R_RELATIVE = R_PPC_RELATIVE, + .dynamic_linker = "/lib/ld.so.1", + .adjust_dyn = ppc_adjust_dyn, + .adjust_rel = ppc_adjust_rel, + .adjust_rela = ppc_adjust_rela, + .prelink_rel = ppc_prelink_rel, + .prelink_rela = ppc_prelink_rela, + .prelink_conflict_rel = ppc_prelink_conflict_rel, + .prelink_conflict_rela = ppc_prelink_conflict_rela, + .apply_conflict_rela = ppc_apply_conflict_rela, + .apply_rel = ppc_apply_rel, + .apply_rela = ppc_apply_rela, + .rel_to_rela = ppc_rel_to_rela, + .need_rel_to_rela = ppc_need_rel_to_rela, + .reloc_size = ppc_reloc_size, + .reloc_class = ppc_reloc_class, + .max_reloc_size = 4, + .arch_pre_prelink = ppc_arch_pre_prelink, + .arch_prelink = ppc_arch_prelink, + .arch_undo_prelink = ppc_arch_undo_prelink, + .undo_prelink_rela = ppc_undo_prelink_rela, + .layout_libs_pre = ppc_layout_libs_pre, + .layout_libs_post = ppc_layout_libs_post, + /* This will need some changes in layout.c. + PowerPC prefers addresses right below REG0E + and can use the region above REG2S if libs don't fit. */ + .mmap_base = REG1S, + .mmap_end = REG2E, + .max_page_size = 0x10000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-ppc64.c b/trunk/src/arch-ppc64.c new file mode 100644 index 0000000..3b12dbe --- /dev/null +++ b/trunk/src/arch-ppc64.c @@ -0,0 +1,856 @@ +/* Copyright (C) 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" +#include "layout.h" + +struct opd_rec +{ + GElf_Addr fn, toc, chain; +}; + +struct opd_lib +{ + GElf_Addr start, size; + GElf_Addr table[1]; +}; + +static int +ppc64_adjust_section (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + if (dso->shdr[n].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[n].sh_name), ".got")) + { + Elf64_Addr data; + + /* .got[0]-0x8000 points to .got, it needs to be adjusted. */ + data = read_ube64 (dso, dso->shdr[n].sh_addr); + if (addr_to_sec (dso, data - 0x8000) == n + && data - 0x8000 == dso->shdr[n].sh_addr) + write_be64 (dso, dso->shdr[n].sh_addr, data + adjust); + } + return 0; +} + +static int +ppc64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PPC64_GLINK && dyn->d_un.d_ptr >= start) + { + dyn->d_un.d_ptr += adjust; + return 1; + } + + return 0; +} + +static int +ppc64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE) + { + GElf_Addr val = read_ube64 (dso, rela->r_offset); + + if (val == rela->r_addend && val >= start) + write_be64 (dso, rela->r_offset, val + adjust); + if (rela->r_addend >= start) + rela->r_addend += adjust; + } + return 0; +} + +static int +ppc64_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: PowerPC64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +ppc64_fixup_plt (struct prelink_info *info, GElf_Rela *rela, GElf_Addr value) +{ + DSO *dso = info->dso; + int sec, i; + size_t n; + struct opd_rec rec; + + if (value == 0) + { + rec.fn = 0; + rec.toc = 0; + rec.chain = 0; + } + else if ((sec = addr_to_sec (dso, value)) != -1) + { + rec.fn = read_ube64 (dso, value); + rec.toc = read_ube64 (dso, value + 8); + rec.chain = read_ube64 (dso, value + 16); + } + else + { + for (i = 0; i < info->ent->ndepends; ++i) + if (info->ent->depends[i]->opd + && info->ent->depends[i]->opd->start <= value + && (info->ent->depends[i]->opd->start + + info->ent->depends[i]->opd->size) > value) + break; + + if (i == info->ent->ndepends) + { + error (0, 0, "%s: R_PPC64_JMP_SLOT doesn't resolve to an .opd address", + dso->filename); + return 1; + } + if ((value - info->ent->depends[i]->opd->start) % 8) + { + error (0, 0, "%s: R_PPC64_JMP_SLOT doesn't resolve to valid .opd section location", + dso->filename); + return 1; + } + n = (value - info->ent->depends[i]->opd->start) / 8; + rec.fn = info->ent->depends[i]->opd->table[n]; + rec.toc = info->ent->depends[i]->opd->table[n + 1]; + rec.chain = info->ent->depends[i]->opd->table[n + 2]; + } + write_be64 (dso, rela->r_offset, rec.fn); + write_be64 (dso, rela->r_offset + 8, rec.toc); + write_be64 (dso, rela->r_offset + 16, rec.chain); + return 0; +} + +static int +ppc64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_PPC64_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE) + { + write_be64 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_GLOB_DAT: + case R_PPC64_ADDR64: + case R_PPC64_UADDR64: + write_be64 (dso, rela->r_offset, value); + break; + case R_PPC64_DTPREL64: + write_be64 (dso, rela->r_offset, value - 0x8000); + break; + case R_PPC64_ADDR32: + case R_PPC64_UADDR32: + write_be32 (dso, rela->r_offset, value); + break; + case R_PPC64_JMP_SLOT: + return ppc64_fixup_plt (info, rela, value); + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + case R_PPC64_ADDR16_LO: + write_be16 (dso, rela->r_offset, value); + break; + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + write_be16 (dso, rela->r_offset, value - 0x8000); + break; + case R_PPC64_ADDR16_HI: + case R_PPC64_DTPREL16_HA: + write_be16 (dso, rela->r_offset, value >> 16); + break; + case R_PPC64_DTPREL16_HI: + write_be16 (dso, rela->r_offset, (value - 0x8000) >> 16); + break; + case R_PPC64_ADDR16_HA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16); + break; + case R_PPC64_ADDR16_HIGHER: + write_be16 (dso, rela->r_offset, value >> 32); + break; + case R_PPC64_ADDR16_HIGHERA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 32); + break; + case R_PPC64_ADDR16_HIGHEST: + write_be16 (dso, rela->r_offset, value >> 48); + break; + case R_PPC64_ADDR16_HIGHESTA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 48); + break; + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR16_DS: + write_be16 (dso, rela->r_offset, + (value & 0xfffc) | read_ube16 (dso, rela->r_offset & 3)); + break; + case R_PPC64_ADDR24: + write_be32 (dso, rela->r_offset, + (value & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003)); + break; + case R_PPC64_ADDR14: + write_be32 (dso, rela->r_offset, + (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffff0003)); + break; + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR14_BRNTAKEN: + write_be32 (dso, rela->r_offset, + (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffdf0003) + | ((((GELF_R_TYPE (rela->r_info) == R_PPC64_ADDR14_BRTAKEN) + << 21) + ^ (value >> 42)) & 0x00200000)); + break; + case R_PPC64_REL24: + write_be32 (dso, rela->r_offset, + ((value - rela->r_offset) & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003)); + break; + case R_PPC64_REL32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_PPC64_REL64: + write_be64 (dso, rela->r_offset, value - rela->r_offset); + break; + /* DTPMOD64 and TPREL* is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_PPC64_DTPMOD64: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_PPC64_DTPMOD64 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_PPC64_TPREL64: + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + { + value += info->resolvetls->offset - 0x7000; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_TPREL64: + write_be64 (dso, rela->r_offset, value); + break; + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + write_be16 (dso, rela->r_offset, value); + break; + case R_PPC64_TPREL16_HI: + write_be16 (dso, rela->r_offset, value >> 16); + break; + case R_PPC64_TPREL16_HA: + write_be16 (dso, rela->r_offset, (value + 0x8000) >> 16); + break; + } + } + break; + case R_PPC64_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_PPC64_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +ppc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_ADDR64: + case R_PPC64_UADDR64: + buf_write_be64 (buf, rela->r_addend); + break; + case R_PPC64_ADDR32: + case R_PPC64_UADDR32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + buf_write_be16 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +ppc64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: PowerPC64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +ppc64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_NONE: + break; + case R_PPC64_GLOB_DAT: + case R_PPC64_ADDR64: + case R_PPC64_UADDR64: + buf_write_be64 (buf, value); + break; + case R_PPC64_ADDR32: + case R_PPC64_UADDR32: + buf_write_be32 (buf, value); + break; + case R_PPC64_ADDR16_HA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HI: + value = value >> 16; + /* FALLTHROUGH */ + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + case R_PPC64_ADDR16_LO: + buf_write_be16 (buf, value); + break; + case R_PPC64_ADDR16_HIGHERA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HIGHER: + buf_write_be16 (buf, value >> 32); + break; + case R_PPC64_ADDR16_HIGHESTA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HIGHEST: + buf_write_be16 (buf, value >> 48); + break; + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR16_DS: + buf_write_be16 (buf, (value & 0xfffc) + | (buf_read_ube16 (buf) & 3)); + break; + case R_PPC64_ADDR24: + buf_write_be32 (buf, (value & 0x03fffffc) + | (buf_read_ube32 (buf) & 0xfc000003)); + break; + case R_PPC64_ADDR14: + buf_write_be32 (buf, (value & 0xfffc) + | (buf_read_ube32 (buf) & 0xffff0003)); + break; + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR14_BRNTAKEN: + buf_write_be32 (buf, (value & 0xfffc) + | (buf_read_ube32 (buf) & 0xffdf0003) + | ((((GELF_R_TYPE (rela->r_info) + == R_PPC64_ADDR14_BRTAKEN) << 21) + ^ (value >> 42)) & 0x00200000)); + break; + case R_PPC64_REL24: + buf_write_be32 (buf, ((value - rela->r_offset) & 0x03fffffc) + | (buf_read_ube32 (buf) & 0xfc000003)); + break; + case R_PPC64_REL32: + buf_write_be32 (buf, value - rela->r_offset); + break; + case R_PPC64_REL64: + buf_write_be64 (buf, value - rela->r_offset); + break; + case R_PPC64_RELATIVE: + error (0, 0, "%s: R_PPC64_RELATIVE in ET_EXEC object?", + info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +ppc64_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + int r_type; + + if (GELF_R_TYPE (rela->r_info) == R_PPC64_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_PPC64_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPREL relocs need conflicts. */ + case R_PPC64_DTPMOD64: + case R_PPC64_TPREL64: + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPREL wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_DTPREL64: + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_HI: + case R_PPC64_DTPREL16_HA: + return 0; + } + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + value += rela->r_addend; + r_type = GELF_R_TYPE (rela->r_info); + switch (r_type) + { + case R_PPC64_GLOB_DAT: + r_type = R_PPC64_ADDR64; + break; + case R_PPC64_ADDR64: + case R_PPC64_UADDR64: + case R_PPC64_JMP_SLOT: + break; + case R_PPC64_ADDR32: + case R_PPC64_UADDR32: + value = (Elf32_Sword) value; + break; + case R_PPC64_ADDR16_HA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HI: + value = value >> 16; + /* FALLTHROUGH */ + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + case R_PPC64_ADDR16_LO: + if (r_type != R_PPC64_UADDR16) + r_type = R_PPC64_ADDR16; + value = ((value & 0xffff) ^ 0x8000) - 0x8000; + break; + case R_PPC64_ADDR16_HIGHERA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HIGHER: + r_type = R_PPC64_ADDR16; + value = (((value >> 32) & 0xffff) ^ 0x8000) - 0x8000; + break; + case R_PPC64_ADDR16_HIGHESTA: + value += 0x8000; + /* FALLTHROUGH */ + case R_PPC64_ADDR16_HIGHEST: + r_type = R_PPC64_ADDR16; + value = ((Elf64_Sxword) value) >> 48; + break; + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR16_DS: + r_type = R_PPC64_ADDR16; + value = ((value & 0xffff) ^ 0x8000) - 0x8000; + value |= read_ube16 (dso, rela->r_offset) & 3; + break; + case R_PPC64_ADDR24: + r_type = R_PPC64_ADDR32; + value = (value & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003); + value = (Elf32_Sword) value; + break; + case R_PPC64_ADDR14: + r_type = R_PPC64_ADDR32; + value = (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffff0003); + value = (Elf32_Sword) value; + break; + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR14_BRNTAKEN: + r_type = R_PPC64_ADDR32; + value = (value & 0xfffc) + | (read_ube32 (dso, rela->r_offset) & 0xffdf0003) + | ((((r_type == R_PPC64_ADDR14_BRTAKEN) << 21) + ^ (value >> 42)) & 0x00200000); + value = (Elf32_Sword) value; + break; + case R_PPC64_REL24: + r_type = R_PPC64_ADDR32; + value = ((value - rela->r_offset) & 0x03fffffc) + | (read_ube32 (dso, rela->r_offset) & 0xfc000003); + value = (Elf32_Sword) value; + break; + case R_PPC64_REL32: + r_type = R_PPC64_ADDR32; + value -= rela->r_offset; + value = (Elf32_Sword) value; + break; + case R_PPC64_REL64: + r_type = R_PPC64_ADDR64; + value -= rela->r_offset; + break; + case R_PPC64_DTPMOD64: + case R_PPC64_DTPREL64: + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_HI: + case R_PPC64_DTPREL16_HA: + case R_PPC64_TPREL64: + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + r_type = R_PPC64_ADDR16; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_DTPMOD64: + r_type = R_PPC64_ADDR64; + value = tls->modid; + break; + case R_PPC64_DTPREL64: + r_type = R_PPC64_ADDR64; + value -= 0x8000; + break; + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + value -= 0x8000; + break; + case R_PPC64_DTPREL16_HI: + value = (value - 0x8000) >> 16; + break; + case R_PPC64_DTPREL16_HA: + value >>= 16; + break; + case R_PPC64_TPREL64: + r_type = R_PPC64_ADDR64; + value += tls->offset - 0x7000; + break; + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + value += tls->offset - 0x7000; + break; + case R_PPC64_TPREL16_HI: + value = (value + tls->offset - 0x7000) >> 16; + break; + case R_PPC64_TPREL16_HA: + value = (value + tls->offset - 0x7000 + 0x8000) >> 16; + break; + } + if (r_type == R_PPC64_ADDR16) + value = ((value & 0xffff) ^ 0x8000) - 0x8000; + break; + default: + error (0, 0, "%s: Unknown PowerPC64 relocation type %d", dso->filename, + r_type); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + ret->r_addend = value; + return 0; +} + +static int +ppc64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: PowerPC64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +ppc64_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +ppc64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_PPC64_NONE: + return 0; + case R_PPC64_JMP_SLOT: + /* .plt section will become SHT_NOBITS. */ + return 0; + case R_PPC64_RELATIVE: + case R_PPC64_ADDR64: + write_be64 (dso, rela->r_offset, rela->r_addend); + break; + case R_PPC64_GLOB_DAT: + case R_PPC64_UADDR64: + case R_PPC64_DTPREL64: + case R_PPC64_TPREL64: + case R_PPC64_DTPMOD64: + case R_PPC64_REL64: + write_be64 (dso, rela->r_offset, 0); + break; + case R_PPC64_ADDR32: + case R_PPC64_UADDR32: + case R_PPC64_REL32: + write_be32 (dso, rela->r_offset, 0); + break; + case R_PPC64_ADDR16_HA: + case R_PPC64_DTPREL16_HA: + case R_PPC64_TPREL16_HA: + case R_PPC64_ADDR16_HI: + case R_PPC64_DTPREL16_HI: + case R_PPC64_TPREL16_HI: + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + case R_PPC64_ADDR16_LO: + case R_PPC64_DTPREL16: + case R_PPC64_TPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_TPREL16_LO: + case R_PPC64_ADDR16_HIGHERA: + case R_PPC64_ADDR16_HIGHER: + case R_PPC64_ADDR16_HIGHESTA: + case R_PPC64_ADDR16_HIGHEST: + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR16_DS: + write_be16 (dso, rela->r_offset, 0); + break; + case R_PPC64_ADDR24: + case R_PPC64_REL24: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xfc000003); + break; + case R_PPC64_ADDR14: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffff0003); + break; + case R_PPC64_ADDR14_BRTAKEN: + case R_PPC64_ADDR14_BRNTAKEN: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffdf0003); + break; + case R_PPC64_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_PPC64_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown ppc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +ppc64_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_PPC64_ADDR16: + case R_PPC64_UADDR16: + case R_PPC64_ADDR16_LO: + case R_PPC64_ADDR16_HA: + case R_PPC64_ADDR16_HI: + case R_PPC64_ADDR16_LO_DS: + case R_PPC64_ADDR16_DS: + case R_PPC64_ADDR16_HIGHER: + case R_PPC64_ADDR16_HIGHERA: + case R_PPC64_ADDR16_HIGHEST: + case R_PPC64_ADDR16_HIGHESTA: + case R_PPC64_DTPREL16: + case R_PPC64_DTPREL16_LO: + case R_PPC64_DTPREL16_HI: + case R_PPC64_DTPREL16_HA: + case R_PPC64_TPREL16: + case R_PPC64_TPREL16_LO: + case R_PPC64_TPREL16_HI: + case R_PPC64_TPREL16_HA: + return 2; + case R_PPC64_GLOB_DAT: + case R_PPC64_ADDR64: + case R_PPC64_UADDR64: + case R_PPC64_REL64: + case R_PPC64_DTPMOD64: + case R_PPC64_DTPREL64: + case R_PPC64_TPREL64: + return 8; + default: + break; + } + return 4; +} + +static int +ppc64_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_PPC64_COPY: return RTYPE_CLASS_COPY; + case R_PPC64_ADDR24: return RTYPE_CLASS_PLT; + default: + if (reloc_type >= R_PPC64_DTPMOD64 + && reloc_type <= R_PPC64_TPREL16_HIGHESTA) + return RTYPE_CLASS_TLS; + return RTYPE_CLASS_VALID; + } +} + +static int +ppc64_read_opd (DSO *dso, struct prelink_entry *ent) +{ + int opd; + GElf_Addr n, s; + + free (ent->opd); + ent->opd = NULL; + for (opd = 1; opd < dso->ehdr.e_shnum; ++opd) + if (dso->shdr[opd].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[opd].sh_name), ".opd")) + break; + if (opd == dso->ehdr.e_shnum) + return 0; + ent->opd = malloc (sizeof (struct opd_lib) + dso->shdr[opd].sh_size); + /* The error will happen only when we'll need the opd. */ + if (ent->opd == NULL) + return 0; + s = dso->shdr[opd].sh_addr; + for (n = 0; n < dso->shdr[opd].sh_size / 8; ++n, s += 8) + ent->opd->table[n] = read_ube64 (dso, s); + ent->opd->start = dso->shdr[opd].sh_addr; + ent->opd->size = dso->shdr[opd].sh_size; + return 0; +} + +static int +ppc64_free_opd (struct prelink_entry *ent) +{ + free (ent->opd); + ent->opd = NULL; + return 0; +} + +PL_ARCH = { + .name = "PowerPC", + .class = ELFCLASS64, + .machine = EM_PPC64, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_PPC64_JMP_SLOT, + .R_COPY = R_PPC64_COPY, + .R_RELATIVE = R_PPC64_RELATIVE, + .dynamic_linker = "/lib64/ld64.so.1", + .adjust_section = ppc64_adjust_section, + .adjust_dyn = ppc64_adjust_dyn, + .adjust_rel = ppc64_adjust_rel, + .adjust_rela = ppc64_adjust_rela, + .prelink_rel = ppc64_prelink_rel, + .prelink_rela = ppc64_prelink_rela, + .prelink_conflict_rel = ppc64_prelink_conflict_rel, + .prelink_conflict_rela = ppc64_prelink_conflict_rela, + .apply_conflict_rela = ppc64_apply_conflict_rela, + .apply_rel = ppc64_apply_rel, + .apply_rela = ppc64_apply_rela, + .rel_to_rela = ppc64_rel_to_rela, + .need_rel_to_rela = ppc64_need_rel_to_rela, + .reloc_size = ppc64_reloc_size, + .reloc_class = ppc64_reloc_class, + .read_opd = ppc64_read_opd, + .free_opd = ppc64_free_opd, + .max_reloc_size = 8, + .undo_prelink_rela = ppc64_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x8000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x8001000000LL, + .mmap_end = 0x8100000000LL, + .max_page_size = 0x10000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-s390.c b/trunk/src/arch-s390.c new file mode 100644 index 0000000..4be0dcb --- /dev/null +++ b/trunk/src/arch-s390.c @@ -0,0 +1,513 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +s390_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf64_Addr data; + + if (sec == -1) + return 0; + + data = read_ube32 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ube32 (dso, dyn->d_un.d_ptr + 4); + /* If .got.plt[1] points to .plt + 0x2c, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 0x2c + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_be32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + break; + } + } + } + return 0; +} + +static int +s390_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr addr; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_RELATIVE: + if ((Elf32_Addr) rela->r_addend >= start) + { + addr = read_ube32 (dso, rela->r_offset); + if (addr == rela->r_addend) + write_be32 (dso, rela->r_offset, addr + adjust); + rela->r_addend += (Elf32_Sword) adjust; + } + break; + case R_390_JMP_SLOT: + addr = read_ube32 (dso, rela->r_offset); + if (addr >= start) + write_be32 (dso, rela->r_offset, addr + adjust); + break; + } + return 0; +} + +static int +s390_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +s390_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_390_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_390_RELATIVE) + { + write_be32 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + write_be32 (dso, rela->r_offset, value); + break; + case R_390_32: + write_be32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_390_PC32: + write_be32 (dso, rela->r_offset, value + rela->r_addend - rela->r_offset); + break; + case R_390_TLS_DTPOFF: + write_be32 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD and TPOFF is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_390_TLS_DTPMOD: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_390_TLS_DTPMOD reloc in executable?", + dso->filename); + return 1; + } + break; + case R_390_TLS_TPOFF: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + value + rela->r_addend - info->resolvetls->offset); + break; + case R_390_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_390_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown S390 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +s390_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_32: + buf_write_be32 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +s390_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +s390_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_NONE: + break; + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + buf_write_be32 (buf, value); + break; + case R_390_32: + buf_write_be32 (buf, value + rela->r_addend); + break; + case R_390_PC32: + buf_write_be32 (buf, value + rela->r_addend - rela->r_offset); + break; + case R_390_COPY: + abort (); + case R_390_RELATIVE: + error (0, 0, "%s: R_390_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +s390_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_390_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_390_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_390_TLS_DTPMOD: + case R_390_TLS_TPOFF: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_390_TLS_DTPOFF + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, R_390_32); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + ret->r_addend = (Elf32_Sword) value; + break; + case R_390_32: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + break; + case R_390_PC32: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend - rela->r_offset); + break; + case R_390_COPY: + error (0, 0, "R_390_COPY should not be present in shared libraries"); + return 1; + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_TLS_DTPMOD: + ret->r_addend = tls->modid; + break; + case R_390_TLS_DTPOFF: + ret->r_addend = value + rela->r_addend; + break; + case R_390_TLS_TPOFF: + ret->r_addend = value + rela->r_addend - tls->offset; + break; + } + break; + + default: + error (0, 0, "%s: Unknown S390 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +s390_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +s390_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 0x2c into got[1]. + .plt + 0x2c is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf64_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr + 0x2c; + write_be32 (dso, dso->info[DT_PLTGOT] + 4, data); + } + + return 0; +} + +static int +s390_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt + 0x2c. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_ube32 (dso, dso->info[DT_PLTGOT] + 4); + if (data == dso->shdr[i].sh_addr + 0x2c) + write_be32 (dso, dso->info[DT_PLTGOT] + 4, 0); + } + + return 0; +} + +static int +s390_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_NONE: + case R_390_RELATIVE: + break; + case R_390_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_390_JMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf32_Addr data = read_ube32 (dso, dso->shdr[sec].sh_addr + 4); + + assert (rela->r_offset >= dso->shdr[sec].sh_addr + 12); + assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + write_be32 (dso, rela->r_offset, + 8 * (rela->r_offset - dso->shdr[sec].sh_addr - 12) + + data); + } + break; + case R_390_GLOB_DAT: + case R_390_32: + case R_390_PC32: + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + write_be32 (dso, rela->r_offset, 0); + break; + case R_390_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_390_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown s390 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +s390_reloc_size (int reloc_type) +{ + return 4; +} + +static int +s390_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_390_COPY: return RTYPE_CLASS_COPY; + case R_390_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "S390", + .class = ELFCLASS32, + .machine = EM_S390, + .alternate_machine = { 0xA390 }, + .R_JMP_SLOT = R_390_JMP_SLOT, + .R_COPY = R_390_COPY, + .R_RELATIVE = R_390_RELATIVE, + .dynamic_linker = "/lib/ld.so.1", + .adjust_dyn = s390_adjust_dyn, + .adjust_rel = s390_adjust_rel, + .adjust_rela = s390_adjust_rela, + .prelink_rel = s390_prelink_rel, + .prelink_rela = s390_prelink_rela, + .prelink_conflict_rel = s390_prelink_conflict_rel, + .prelink_conflict_rela = s390_prelink_conflict_rela, + .apply_conflict_rela = s390_apply_conflict_rela, + .apply_rel = s390_apply_rel, + .apply_rela = s390_apply_rela, + .rel_to_rela = s390_rel_to_rela, + .need_rel_to_rela = s390_need_rel_to_rela, + .reloc_size = s390_reloc_size, + .reloc_class = s390_reloc_class, + .max_reloc_size = 4, + .arch_prelink = s390_arch_prelink, + .arch_undo_prelink = s390_arch_undo_prelink, + .undo_prelink_rela = s390_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x40000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x41000000, + .mmap_end = 0x50000000, + .max_page_size = 0x1000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-s390x.c b/trunk/src/arch-s390x.c new file mode 100644 index 0000000..1e381c7 --- /dev/null +++ b/trunk/src/arch-s390x.c @@ -0,0 +1,629 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +s390x_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf64_Addr data; + + if (sec == -1) + return 0; + + data = read_ube64 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be64 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ube64 (dso, dyn->d_un.d_ptr + 8); + /* If .got.plt[1] points to .plt + 0x2e, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 0x2e + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_be64 (dso, dyn->d_un.d_ptr + 8, data + adjust); + break; + } + } + } + return 0; +} + +static int +s390x_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390x_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf64_Addr addr; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_RELATIVE: + if (rela->r_addend >= start) + { + addr = read_ube64 (dso, rela->r_offset); + if (addr == rela->r_addend) + write_be64 (dso, rela->r_offset, addr + adjust); + rela->r_addend += adjust; + } + break; + case R_390_JMP_SLOT: + addr = read_ube64 (dso, rela->r_offset); + if (addr >= start) + write_be64 (dso, rela->r_offset, addr + adjust); + break; + } + return 0; +} + +static int +s390x_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +s390x_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_390_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_390_RELATIVE) + { + write_be64 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + case R_390_64: + write_be64 (dso, rela->r_offset, value); + break; + case R_390_PC64: + write_be64 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_390_32: + write_be32 (dso, rela->r_offset, value); + break; + case R_390_PC32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + write_be32 (dso, rela->r_offset, + ((Elf32_Sword) (value - rela->r_offset)) >> 1); + break; + case R_390_16: + write_be16 (dso, rela->r_offset, value); + break; + case R_390_PC16: + write_be16 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + write_be16 (dso, rela->r_offset, + ((int16_t) (value - rela->r_offset)) >> 1); + break; + case R_390_8: + write_8 (dso, rela->r_offset, value); + break; + case R_390_TLS_DTPOFF: + write_be64 (dso, rela->r_offset, value); + break; + /* DTPMOD and TPOFF is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_390_TLS_DTPMOD: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_390_TLS_DTPMOD reloc in executable?", + dso->filename); + return 1; + } + break; + case R_390_TLS_TPOFF: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be64 (dso, rela->r_offset, value - info->resolvetls->offset); + break; + case R_390_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_390_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown S390 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +s390x_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_64: + buf_write_be64 (buf, rela->r_addend); + break; + case R_390_32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_390_16: + buf_write_be16 (buf, rela->r_addend); + break; + case R_390_8: + buf_write_8 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +s390x_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +s390x_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_NONE: + break; + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + case R_390_64: + buf_write_be64 (buf, value); + break; + case R_390_PC64: + buf_write_be64 (buf, value - rela->r_offset); + break; + case R_390_32: + buf_write_be32 (buf, value); + break; + case R_390_PC32: + buf_write_be32 (buf, value - rela->r_offset); + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + buf_write_be32 (buf, ((Elf32_Sword) (value - rela->r_offset)) >> 1); + break; + case R_390_16: + buf_write_be16 (buf, value); + break; + case R_390_PC16: + buf_write_be16 (buf, value - rela->r_offset); + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + buf_write_be16 (buf, ((int16_t) (value - rela->r_offset)) >> 1); + break; + case R_390_8: + buf_write_8 (buf, value); + break; + case R_390_COPY: + abort (); + case R_390_RELATIVE: + error (0, 0, "%s: R_390_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +s390x_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390x_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + int r_type; + + if (GELF_R_TYPE (rela->r_info) == R_390_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_390_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_390_TLS_DTPMOD: + case R_390_TLS_TPOFF: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_390_TLS_DTPOFF + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + r_type = GELF_R_TYPE (rela->r_info); + value += rela->r_addend; + switch (r_type) + { + case R_390_PC64: + value -= rela->r_offset; + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + case R_390_64: + ret->r_addend = value; + r_type = R_390_64; + break; + case R_390_PC32: + value -= rela->r_offset; + case R_390_32: + ret->r_addend = (Elf32_Addr) value; + r_type = R_390_32; + break; + case R_390_PC32DBL: + case R_390_PLT32DBL: + ret->r_addend + = (Elf32_Addr) (((Elf32_Sword) (value - rela->r_offset)) >> 1); + r_type = R_390_32; + break; + case R_390_PC16: + value -= rela->r_offset; + case R_390_16: + ret->r_addend = (Elf32_Half) value; + r_type = R_390_16; + break; + case R_390_PC16DBL: + case R_390_PLT16DBL: + ret->r_addend = (Elf32_Half) (((int16_t) (value - rela->r_offset)) >> 1); + r_type = R_390_16; + break; + case R_390_8: + ret->r_addend = value & 0xff; + break; + case R_390_COPY: + error (0, 0, "R_390_COPY should not be present in shared libraries"); + return 1; + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + switch (r_type) + { + case R_390_TLS_DTPMOD: + ret->r_addend = tls->modid; + break; + case R_390_TLS_DTPOFF: + ret->r_addend = value; + break; + case R_390_TLS_TPOFF: + ret->r_addend = value - tls->offset; + break; + } + r_type = R_390_64; + break; + default: + error (0, 0, "%s: Unknown S390 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + return 0; +} + +static int +s390x_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: S390 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +s390x_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +s390x_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 0x2e into got[1]. + .plt + 0x2e is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf64_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr + 0x2e; + write_be64 (dso, dso->info[DT_PLTGOT] + 8, data); + } + + return 0; +} + +static int +s390x_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt + 0x2e. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf64_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_ube64 (dso, dso->info[DT_PLTGOT] + 8); + if (data == dso->shdr[i].sh_addr + 0x2e) + write_be64 (dso, dso->info[DT_PLTGOT] + 8, 0); + } + + return 0; +} + +static int +s390x_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_390_NONE: + case R_390_RELATIVE: + break; + case R_390_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_390_JMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf64_Addr data = read_ube64 (dso, dso->shdr[sec].sh_addr + 8); + + assert (rela->r_offset >= dso->shdr[sec].sh_addr + 24); + assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 7) == 0); + write_be64 (dso, rela->r_offset, + 4 * (rela->r_offset - dso->shdr[sec].sh_addr - 24) + + data); + } + break; + case R_390_GLOB_DAT: + case R_390_64: + case R_390_PC64: + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + write_be64 (dso, rela->r_offset, 0); + break; + case R_390_32: + case R_390_PC32: + case R_390_PC32DBL: + case R_390_PLT32DBL: + write_be32 (dso, rela->r_offset, 0); + break; + case R_390_16: + case R_390_PC16: + case R_390_PC16DBL: + case R_390_PLT16DBL: + write_be16 (dso, rela->r_offset, 0); + break; + case R_390_8: + write_8 (dso, rela->r_offset, 0); + break; + case R_390_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_390_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown s390x relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +s390x_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_390_GLOB_DAT: + case R_390_JMP_SLOT: + case R_390_64: + case R_390_PC64: + return 8; + case R_390_32: + case R_390_PC32: + case R_390_PC32DBL: + case R_390_PLT32DBL: + default: + return 4; + case R_390_16: + case R_390_PC16: + case R_390_PC16DBL: + case R_390_PLT16DBL: + return 2; + case R_390_8: + return 1; + } +} + +static int +s390x_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_390_COPY: return RTYPE_CLASS_COPY; + case R_390_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_390_TLS_DTPMOD: + case R_390_TLS_DTPOFF: + case R_390_TLS_TPOFF: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "S390", + .class = ELFCLASS64, + .machine = EM_S390, + .alternate_machine = { 0xA390 }, + .R_JMP_SLOT = R_390_JMP_SLOT, + .R_COPY = R_390_COPY, + .R_RELATIVE = R_390_RELATIVE, + .dynamic_linker = "/lib/ld64.so.1", + .adjust_dyn = s390x_adjust_dyn, + .adjust_rel = s390x_adjust_rel, + .adjust_rela = s390x_adjust_rela, + .prelink_rel = s390x_prelink_rel, + .prelink_rela = s390x_prelink_rela, + .prelink_conflict_rel = s390x_prelink_conflict_rel, + .prelink_conflict_rela = s390x_prelink_conflict_rela, + .apply_conflict_rela = s390x_apply_conflict_rela, + .apply_rel = s390x_apply_rel, + .apply_rela = s390x_apply_rela, + .rel_to_rela = s390x_rel_to_rela, + .need_rel_to_rela = s390x_need_rel_to_rela, + .reloc_size = s390x_reloc_size, + .reloc_class = s390x_reloc_class, + .max_reloc_size = 8, + .arch_prelink = s390x_arch_prelink, + .arch_undo_prelink = s390x_arch_undo_prelink, + .undo_prelink_rela = s390x_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x4000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x4010000000LL, + .mmap_end = 0x5000000000LL, + .max_page_size = 0x1000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-sh.c b/trunk/src/arch-sh.c new file mode 100644 index 0000000..6ddf5f6 --- /dev/null +++ b/trunk/src/arch-sh.c @@ -0,0 +1,445 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +sh_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf32_Addr data; + + if (sec == -1) + return 0; + + data = read_une32 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_ne32 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_une32 (dso, dyn->d_un.d_ptr + 4); + /* If .got.plt[1] points to .plt + 36, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 36 + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_ne32 (dso, dyn->d_un.d_ptr + 4, data + adjust); + break; + } + } + } + return 0; +} + +static int +sh_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: SH doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sh_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf32_Addr data; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_RELATIVE: + if (rela->r_addend && (Elf32_Addr) rela->r_addend >= start) + { + rela->r_addend += (Elf32_Sword) adjust; + break; + } + /* FALLTHROUGH */ + case R_SH_JMP_SLOT: + data = read_une32 (dso, rela->r_offset); + if (data >= start) + write_ne32 (dso, rela->r_offset, data + adjust); + break; + break; + } + return 0; +} + +static int +sh_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: SH doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +sh_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + dso = info->dso; + if (GELF_R_TYPE (rela->r_info) == R_SH_NONE) + /* Fast path: nothing to do. */ + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_SH_RELATIVE) + { + if (rela->r_addend) + write_ne32 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + case R_SH_DIR32: + write_ne32 (dso, rela->r_offset, value); + break; + case R_SH_REL32: + write_ne32 (dso, rela->r_offset, value - rela->r_addend); + break; + case R_SH_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SH_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sh relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sh_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + case R_SH_DIR32: + buf_write_ne32 (info->dso, buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +sh_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: SH doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +sh_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_NONE: + break; + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + case R_SH_DIR32: + buf_write_ne32 (info->dso, buf, value); + break; + case R_SH_REL32: + buf_write_ne32 (info->dso, buf, value - rela->r_offset); + break; + case R_SH_COPY: + abort (); + case R_SH_RELATIVE: + error (0, 0, "%s: R_SH_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +sh_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: SH doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sh_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_SH_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_SH_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + return 0; + value = conflict_lookup_value (conflict); + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_REL32: + value -= rela->r_offset; + ret->r_info = GELF_R_INFO (0, R_SH_DIR32); + /* FALLTHROUGH */ + case R_SH_DIR32: + if ((rela->r_offset & 3) == 0) + ret->r_info = GELF_R_INFO (0, R_SH_GLOB_DAT); + /* FALLTHROUGH */ + case R_SH_GLOB_DAT: + case R_SH_JMP_SLOT: + ret->r_addend = (Elf32_Sword) (value + rela->r_addend); + break; + case R_SH_COPY: + error (0, 0, "R_SH_COPY should not be present in shared libraries"); + return 1; + default: + error (0, 0, "%s: Unknown sh relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sh_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + return 0; +} + +static int +sh_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +sh_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 36 into got[1]. + .plt + 36 is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = dso->shdr[i].sh_addr + 36; + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, data); + } + + return 0; +} + +static int +sh_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt + 36. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf32_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_une32 (dso, dso->info[DT_PLTGOT] + 4); + if (data == dso->shdr[i].sh_addr + 36) + write_ne32 (dso, dso->info[DT_PLTGOT] + 4, 0); + } + + return 0; +} + +static int +sh_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SH_NONE: + break; + case R_SH_RELATIVE: + if (rela->r_addend) + write_ne32 (dso, rela->r_offset, 0); + break; + case R_SH_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_SH_JMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf32_Addr data = read_une32 (dso, dso->shdr[sec].sh_addr + 4); + + assert (rela->r_offset >= dso->shdr[sec].sh_addr + 12); + assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 3) == 0); + write_ne32 (dso, rela->r_offset, + 7 * (rela->r_offset - dso->shdr[sec].sh_addr - 12) + + data); + } + break; + case R_SH_GLOB_DAT: + case R_SH_DIR32: + case R_SH_REL32: + write_ne32 (dso, rela->r_offset, 0); + break; + case R_SH_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SH_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sh relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sh_reloc_size (int reloc_type) +{ + return 4; +} + +static int +sh_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_SH_COPY: return RTYPE_CLASS_COPY; + case R_SH_JMP_SLOT: return RTYPE_CLASS_PLT; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "SuperH", + .class = ELFCLASS32, + .machine = EM_SH, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_SH_JMP_SLOT, + .R_COPY = R_SH_COPY, + .R_RELATIVE = R_SH_RELATIVE, + .dynamic_linker = "/lib/ld-linux.so.2", + .adjust_dyn = sh_adjust_dyn, + .adjust_rel = sh_adjust_rel, + .adjust_rela = sh_adjust_rela, + .prelink_rel = sh_prelink_rel, + .prelink_rela = sh_prelink_rela, + .prelink_conflict_rel = sh_prelink_conflict_rel, + .prelink_conflict_rela = sh_prelink_conflict_rela, + .apply_conflict_rela = sh_apply_conflict_rela, + .apply_rel = sh_apply_rel, + .apply_rela = sh_apply_rela, + .rel_to_rela = sh_rel_to_rela, + .need_rel_to_rela = sh_need_rel_to_rela, + .reloc_size = sh_reloc_size, + .reloc_class = sh_reloc_class, + .max_reloc_size = 4, + .arch_prelink = sh_arch_prelink, + .arch_undo_prelink = sh_arch_undo_prelink, + .undo_prelink_rela = sh_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x29555000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x30000000, + .mmap_end = 0x40000000, + .max_page_size = 0x10000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-sparc.c b/trunk/src/arch-sparc.c new file mode 100644 index 0000000..98bacac --- /dev/null +++ b/trunk/src/arch-sparc.c @@ -0,0 +1,637 @@ +/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +sparc_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".got")) + { + Elf32_Addr data; + + data = read_ube32 (dso, dso->shdr[i].sh_addr); + /* .got[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be32 (dso, dso->shdr[i].sh_addr, data + adjust); + break; + } + } + + return 0; +} + +static int +sparc_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + if (rela->r_addend) + { + if ((Elf32_Addr) rela->r_addend >= start) + rela->r_addend += (Elf32_Sword) adjust; + } + else + { + GElf_Addr val = read_ube32 (dso, rela->r_offset); + + if (val >= start) + write_be32 (dso, rela->r_offset, val + adjust); + } + } + return 0; +} + +static int +sparc_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static void +sparc_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr value) +{ + Elf32_Sword disp = value - rela->r_offset; + + if (disp >= -0x800000 && disp < 0x800000) + { + /* b,a value + nop + nop */ + write_be32 (dso, rela->r_offset, 0x30800000 | ((disp >> 2) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x01000000); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } + else + { + /* sethi %hi(value), %g1 + jmpl %g1 + %lo(value), %g0 + nop */ + write_be32 (dso, rela->r_offset, 0x03000000 | ((value >> 10) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x81c06000 | (value & 0x3ff)); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } +} + +static int +sparc_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (GELF_R_TYPE (rela->r_info) == R_SPARC_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + /* 32-bit SPARC handles RELATIVE relocs as + *(int *)rela->r_offset += l_addr + rela->r_addend. + RELATIVE relocs against .got traditionally used to have the + addend in memory pointed by r_offset and 0 r_addend, + other RELATIVE relocs and more recent .got RELATIVE relocs + too have 0 in memory and non-zero r_addend. For prelinking, + we need the value in memory to be already relocated for + l_addr == 0 case, so we have to make sure r_addend will be 0. */ + if (rela->r_addend == 0) + return 0; + value = read_ube32 (dso, rela->r_offset); + value += rela->r_addend; + rela->r_addend = 0; + write_be32 (dso, rela->r_offset, value); + /* Tell prelink_rela routine it should update the relocation. */ + return 2; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + case R_SPARC_UA32: + write_be32 (dso, rela->r_offset, value); + break; + case R_SPARC_JMP_SLOT: + sparc_fixup_plt (dso, rela, value); + break; + case R_SPARC_8: + write_8 (dso, rela->r_offset, value); + break; + case R_SPARC_16: + case R_SPARC_UA16: + write_be16 (dso, rela->r_offset, value); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + (value & 0x3ff) | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_HI22: + write_be32 (dso, rela->r_offset, + ((value >> 10) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + (((value - rela->r_offset) >> 2) & 0x3fffffff) + | (read_ube32 (dso, rela->r_offset) & 0xc0000000)); + break; + case R_SPARC_TLS_DTPOFF32: + write_be32 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD32 and TPOFF32 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_SPARC_TLS_DTPMOD32: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_SPARC_TLS_DTPMOD32 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_SPARC_TLS_TPOFF32: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + value + rela->r_addend - info->resolvetls->offset); + break; + case R_SPARC_TLS_LE_HIX22: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | (((~(value + rela->r_addend - info->resolvetls->offset)) + >> 10) & 0x3fffff)); + break; + case R_SPARC_TLS_LE_LOX10: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_be32 (dso, rela->r_offset, + (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00 + | ((value + rela->r_addend - info->resolvetls->offset) + & 0x3ff)); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, rela->r_addend); + break; + case R_SPARC_8: + buf_write_8 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +sparc_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +sparc_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + break; + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, value); + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, value); + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + buf_write_8 (buf, value); + break; + case R_SPARC_LO10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) | (value & 0x3ff)); + break; + case R_SPARC_HI22: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 10) & 0x3fffff)); + break; + case R_SPARC_WDISP30: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff)); + break; + case R_SPARC_RELATIVE: + error (0, 0, "%s: R_SPARC_RELATIVE in ET_EXEC object?", + info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +sparc_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + int r_type; + + if (GELF_R_TYPE (rela->r_info) == R_SPARC_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_SPARC_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD32 and TPOFF32 relocs need conflicts. */ + case R_SPARC_TLS_DTPMOD32: + case R_SPARC_TLS_TPOFF32: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF32 wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_SPARC_TLS_DTPOFF32 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + value += rela->r_addend; + r_type = GELF_R_TYPE (rela->r_info); + switch (r_type) + { + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + r_type = R_SPARC_32; + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + r_type = R_SPARC_16; + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + r_type = R_SPARC_8; + break; + /* Attempt to transform all reloc which read-modify-write into + simple writes. */ + case R_SPARC_LO10: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) | (value & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_HI22: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 10) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_WDISP30: + value = (read_ube32 (dso, rela->r_offset) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff); + r_type = R_SPARC_32; + break; + case R_SPARC_UA16: + case R_SPARC_UA32: + case R_SPARC_JMP_SLOT: + break; + case R_SPARC_TLS_DTPMOD32: + case R_SPARC_TLS_DTPOFF32: + case R_SPARC_TLS_TPOFF32: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + r_type = R_SPARC_32; + tls = conflict ? conflict->lookup.tls : info->curtls; + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_TLS_DTPMOD32: + value = tls->modid; + break; + case R_SPARC_TLS_DTPOFF32: + break; + case R_SPARC_TLS_TPOFF32: + value -= tls->offset; + break; + case R_SPARC_TLS_LE_HIX22: + value -= tls->offset; + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | (((~value) >> 10) & 0x3fffff); + break; + case R_SPARC_TLS_LE_LOX10: + value -= tls->offset; + value = (read_ube32 (dso, rela->r_offset) & 0xffffe000) | 0x1c00 + | (value & 0x3ff); + break; + } + break; + default: + error (0, 0, "%s: Unknown Sparc relocation type %d", dso->filename, + r_type); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + ret->r_addend = (Elf32_Sword) value; + return 0; +} + +static int +sparc_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +sparc_arch_prelink (struct prelink_info *info) +{ + return 0; +} + +static int +sparc_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + return 0; + case R_SPARC_RELATIVE: + /* 32-bit SPARC handles RELATIVE relocs as + *(int *)rela->r_offset += l_addr + rela->r_addend. + RELATIVE relocs against .got traditionally used to have the + addend in memory pointed by r_offset and 0 r_addend, + other RELATIVE relocs and more recent RELATIVE relocs have 0 + in memory and non-zero r_addend. + Always store 0 to memory when doing undo. */ + assert (rela->r_addend == 0); + rela->r_addend = (Elf32_Sword) read_ube32 (dso, rela->r_offset); + write_be32 (dso, rela->r_offset, 0); + /* Tell undo_prelink_rela routine it should update the + relocation. */ + return 2; + case R_SPARC_GLOB_DAT: + case R_SPARC_32: + case R_SPARC_UA32: + case R_SPARC_DISP32: + case R_SPARC_TLS_DTPMOD32: + case R_SPARC_TLS_DTPOFF32: + case R_SPARC_TLS_TPOFF32: + write_be32 (dso, rela->r_offset, 0); + break; + case R_SPARC_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + if (sec != -1) + { + /* sethi .-.plt, %g1 + b,a .plt+0 */ + write_be32 (dso, rela->r_offset, + 0x03000000 + | ((rela->r_offset - dso->shdr[sec].sh_addr) + & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, + 0x30800000 + | (((dso->shdr[sec].sh_addr - rela->r_offset - 4) >> 2) + & 0x3fffff)); + } + break; + case R_SPARC_8: + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, 0); + break; + case R_SPARC_16: + case R_SPARC_UA16: + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, 0); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_TLS_LE_LOX10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffffe000); + break; + case R_SPARC_HI22: + case R_SPARC_TLS_LE_HIX22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xc0000000); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_8: + case R_SPARC_DISP8: + return 1; + case R_SPARC_16: + case R_SPARC_DISP16: + case R_SPARC_UA16: + return 2; + default: + break; + } + return 4; +} + +static int +sparc_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_COPY: return RTYPE_CLASS_COPY; + case R_SPARC_JMP_SLOT: return RTYPE_CLASS_PLT; + case R_SPARC_TLS_DTPMOD32: + case R_SPARC_TLS_DTPOFF32: + case R_SPARC_TLS_TPOFF32: + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "SPARC", + .class = ELFCLASS32, + .machine = EM_SPARC, + .alternate_machine = { EM_SPARC32PLUS }, + .R_JMP_SLOT = R_SPARC_JMP_SLOT, + .R_COPY = R_SPARC_COPY, + .R_RELATIVE = R_SPARC_RELATIVE, + .dynamic_linker = "/lib/ld-linux.so.2", + .adjust_dyn = sparc_adjust_dyn, + .adjust_rel = sparc_adjust_rel, + .adjust_rela = sparc_adjust_rela, + .prelink_rel = sparc_prelink_rel, + .prelink_rela = sparc_prelink_rela, + .prelink_conflict_rel = sparc_prelink_conflict_rel, + .prelink_conflict_rela = sparc_prelink_conflict_rela, + .apply_conflict_rela = sparc_apply_conflict_rela, + .apply_rel = sparc_apply_rel, + .apply_rela = sparc_apply_rela, + .rel_to_rela = sparc_rel_to_rela, + .need_rel_to_rela = sparc_need_rel_to_rela, + .reloc_size = sparc_reloc_size, + .reloc_class = sparc_reloc_class, + .max_reloc_size = 4, + .arch_prelink = sparc_arch_prelink, + .undo_prelink_rela = sparc_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x70000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x71000000LL, + .mmap_end = 0x80000000LL, + .max_page_size = 0x10000, + .page_size = 0x1000 +}; diff --git a/trunk/src/arch-sparc64.c b/trunk/src/arch-sparc64.c new file mode 100644 index 0000000..e673e99 --- /dev/null +++ b/trunk/src/arch-sparc64.c @@ -0,0 +1,725 @@ +/* Copyright (C) 2001, 2002, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +#define SPARC64_R_TYPE(info) (GELF_R_TYPE (info) & 0xff) + +static int +sparc64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".got")) + { + Elf64_Addr data; + + data = read_ube64 (dso, dso->shdr[i].sh_addr); + /* .got[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_be64 (dso, dso->shdr[i].sh_addr, data + adjust); + break; + } + } + + return 0; +} + +static int +sparc64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + if (rela->r_addend >= start) + rela->r_addend += adjust; + } + else if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_JMP_SLOT + && rela->r_addend) + { + /* .plt[32768+] r_addends are -some_address_in_plt_section. */ + if ((- rela->r_addend) >= start) + rela->r_addend -= adjust; + } + return 0; +} + +static int +sparc64_prelink_rel (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static void +sparc64_fixup_plt (DSO *dso, GElf_Rela *rela, GElf_Addr value) +{ + Elf64_Sxword disp = value - rela->r_offset; + + if (rela->r_addend) + { + /* .plt[32768+] */ + write_be64 (dso, rela->r_offset, value); + } + else if (disp >= -0x800000 && disp < 0x800000) + { + /* b,a value + nop + nop */ + write_be32 (dso, rela->r_offset, 0x30800000 | ((disp >> 2) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x01000000); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } + else if (! (value >> 32)) + { + /* sethi %hi(value), %g1 + jmpl %g1 + %lo(value), %g0 + nop */ + write_be32 (dso, rela->r_offset, 0x03000000 | ((value >> 10) & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, 0x81c06000 | (value & 0x3ff)); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + } + else if ((rela->r_offset + 4 > value + && ((rela->r_offset - value) >> 31) == 0) + || (value > rela->r_offset + 4 + && ((value - rela->r_offset - 4) >> 31) == 0)) + { + /* mov %o7, %g1 + call value + mov %g1, %o7 */ + write_be32 (dso, rela->r_offset, 0x8210000f); + write_be32 (dso, rela->r_offset + 4, 0x40000000 + | (((value - rela->r_offset - 4) >> 2) & 0x3fffffff)); + write_be32 (dso, rela->r_offset + 8, 0x9e100001); + } + else + { + unsigned int csts[4]; + int i = 0; + + /* sethi %hh(value), %g1 + sethi %lm(value), %g5 + or %g1, %hm(value), %g1 + or %g5, %lo(value), %g5 + sllx %g1, 32, %g1 + jmpl %g1 + %g5, %g0 + nop */ + + csts[0] = value >> 42; + csts[1] = (value >> 32) & 0x3ff; + csts[2] = (value >> 10) & 0x3fffff; + csts[3] = value & 0x3ff; + write_be32 (dso, rela->r_offset, 0x03000000 | csts[0]); + write_be32 (dso, rela->r_offset + 4, 0x0b000000 | csts[2]); + /* Sparc64 shared libs are often 0xfffff800XXXXXXXX, so optimize + for this common case. */ + if (csts[1] == 0) + write_be32 (dso, rela->r_offset + 8, 0x83287020); + else + write_be32 (dso, rela->r_offset + 8, 0x82106000 | csts[1]); + write_be32 (dso, rela->r_offset + 12, 0x8a116000 | csts[3]); + if (csts[1] != 0) + write_be32 (dso, rela->r_offset + 16, 0x83287020), i = 4; + write_be32 (dso, rela->r_offset + 16 + i, 0x81c04005); + write_be32 (dso, rela->r_offset + 20 + i, 0x01000000); + } +} + +static int +sparc64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso = info->dso; + GElf_Addr value; + + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_NONE) + return 0; + else if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE) + { + /* 64-bit SPARC handles RELATIVE relocs as + *(long *)rela->r_offset = l_addr + rela->r_addend, + so we must update the memory. */ + write_be64 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + write_be64 (dso, rela->r_offset, value); + break; + case R_SPARC_32: + case R_SPARC_UA32: + write_be32 (dso, rela->r_offset, value); + break; + case R_SPARC_JMP_SLOT: + sparc64_fixup_plt (dso, rela, value); + break; + case R_SPARC_8: + write_8 (dso, rela->r_offset, value); + break; + case R_SPARC_16: + case R_SPARC_UA16: + write_be16 (dso, rela->r_offset, value); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + (value & 0x3ff) | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + write_be32 (dso, rela->r_offset, + ((value >> 10) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP32: + write_be32 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_DISP64: + write_be64 (dso, rela->r_offset, value - rela->r_offset); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + (((value - rela->r_offset) >> 2) & 0x3fffffff) + | (read_ube32 (dso, rela->r_offset) & 0xc0000000)); + break; + case R_SPARC_H44: + write_be32 (dso, rela->r_offset, + ((value >> 22) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_M44: + write_be32 (dso, rela->r_offset, + ((value >> 12) & 0x3ff) + | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_L44: + write_be32 (dso, rela->r_offset, + (value & 0xfff) | (read_ube32 (dso, rela->r_offset) & ~0xfff)); + break; + case R_SPARC_HH22: + write_be32 (dso, rela->r_offset, + ((value >> 42) & 0x3fffff) + | (read_ube32 (dso, rela->r_offset) & 0xffc00000)); + break; + case R_SPARC_HM10: + write_be32 (dso, rela->r_offset, + ((value >> 32) & 0x3ff) + | (read_ube32 (dso, rela->r_offset) & ~0x3ff)); + break; + case R_SPARC_OLO10: + write_be32 (dso, rela->r_offset, + (((value & 0x3ff) + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff) + | (read_ube32 (dso, rela->r_offset) & ~0x1fff)); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) SPARC64_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_64: + case R_SPARC_UA64: + buf_write_be64 (buf, rela->r_addend); + break; + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, rela->r_addend); + break; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, rela->r_addend); + break; + case R_SPARC_8: + buf_write_8 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +sparc64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +sparc64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + value += rela->r_addend; + switch (SPARC64_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + break; + case R_SPARC_DISP64: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + buf_write_be64 (buf, value); + break; + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_32: + case R_SPARC_UA32: + buf_write_be32 (buf, value); + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + case R_SPARC_UA16: + buf_write_be16 (buf, value); + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + buf_write_8 (buf, value); + break; + case R_SPARC_LO10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) | (value & 0x3ff)); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 10) & 0x3fffff)); + break; + case R_SPARC_WDISP30: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff)); + break; + case R_SPARC_H44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 22) & 0x3fffff)); + break; + case R_SPARC_M44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) + | ((value >> 12) & 0x3ff)); + break; + case R_SPARC_L44: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0xfff) | (value & 0xfff)); + break; + case R_SPARC_HH22: + buf_write_be32 (buf, (buf_read_ube32 (buf) & 0xffc00000) + | ((value >> 42) & 0x3fffff)); + break; + case R_SPARC_HM10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x3ff) + | ((value >> 32) & 0x3ff)); + break; + case R_SPARC_OLO10: + buf_write_be32 (buf, (buf_read_ube32 (buf) & ~0x1fff) + | (((value & 0x3ff) + + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff)); + break; + case R_SPARC_RELATIVE: + error (0, 0, "%s: R_SPARC_RELATIVE in ET_EXEC object?", + info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +sparc64_prelink_conflict_rel (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + GElf_Rela *ret; + int r_type; + + if (SPARC64_R_TYPE (rela->r_info) == R_SPARC_RELATIVE + || SPARC64_R_TYPE (rela->r_info) == R_SPARC_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + SPARC64_R_TYPE (rela->r_info)); + if (conflict == NULL) + return 0; + value = conflict_lookup_value (conflict); + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + value += rela->r_addend; + r_type = SPARC64_R_TYPE (rela->r_info); + switch (r_type) + { + case R_SPARC_DISP64: + value -= rela->r_offset; + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + r_type = R_SPARC_64; + break; + case R_SPARC_DISP32: + value -= rela->r_offset; + case R_SPARC_32: + r_type = R_SPARC_32; + break; + case R_SPARC_DISP16: + value -= rela->r_offset; + case R_SPARC_16: + r_type = R_SPARC_16; + break; + case R_SPARC_DISP8: + value -= rela->r_offset; + case R_SPARC_8: + r_type = R_SPARC_8; + break; + /* Attempt to transform all reloc which read-modify-write into + simple writes. */ + case R_SPARC_LO10: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) | (value & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 10) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_WDISP30: + value = (read_ube32 (dso, rela->r_offset) & 0xc0000000) + | (((value - rela->r_offset) >> 2) & 0x3fffffff); + r_type = R_SPARC_32; + break; + case R_SPARC_H44: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 22) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_M44: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) + | ((value >> 12) & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_L44: + value = (read_ube32 (dso, rela->r_offset) & ~0xfff) | (value & 0xfff); + r_type = R_SPARC_32; + break; + case R_SPARC_HH22: + value = (read_ube32 (dso, rela->r_offset) & 0xffc00000) + | ((value >> 42) & 0x3fffff); + r_type = R_SPARC_32; + break; + case R_SPARC_HM10: + value = (read_ube32 (dso, rela->r_offset) & ~0x3ff) + | ((value >> 32) & 0x3ff); + r_type = R_SPARC_32; + break; + case R_SPARC_OLO10: + value = (read_ube32 (dso, rela->r_offset) & ~0x1fff) + | (((value & 0x3ff) + (GELF_R_TYPE (rela->r_info) >> 8)) & 0x1fff); + r_type = R_SPARC_32; + break; + case R_SPARC_JMP_SLOT: + if (rela->r_addend) + r_type = R_SPARC_64; + break; + case R_SPARC_UA16: + case R_SPARC_UA32: + case R_SPARC_UA64: + break; + default: + error (0, 0, "%s: Unknown Sparc relocation type %d", dso->filename, + r_type); + return 1; + } + ret->r_info = GELF_R_INFO (0, r_type); + ret->r_addend = value; + return 0; +} + +static int +sparc64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: Sparc doesn't support REL relocs", dso->filename); + return 1; +} + +static int +sparc64_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +sparc64_arch_prelink (struct prelink_info *info) +{ + return 0; +} + +static int +sparc64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_SPARC_NONE: + break; + case R_SPARC_JMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + if (sec != -1) + { + if (rela->r_addend == 0) + { + /* sethi .-.plt, %g1 + b,a %xcc, .plt+0x20 */ + write_be32 (dso, rela->r_offset, + 0x03000000 + | ((rela->r_offset - dso->shdr[sec].sh_addr) + & 0x3fffff)); + write_be32 (dso, rela->r_offset + 4, + 0x30680000 + | (((dso->shdr[sec].sh_addr + 32 + - rela->r_offset - 4) >> 2) + & 0x7ffff)); + write_be32 (dso, rela->r_offset + 8, 0x01000000); + write_be32 (dso, rela->r_offset + 12, 0x01000000); + write_be32 (dso, rela->r_offset + 16, 0x01000000); + write_be32 (dso, rela->r_offset + 20, 0x01000000); + write_be32 (dso, rela->r_offset + 24, 0x01000000); + write_be32 (dso, rela->r_offset + 28, 0x01000000); + } + else + { + GElf_Addr slot = ((rela->r_offset + 0x400 + - dso->shdr[sec].sh_addr) + / 0x1400) * 0x1400 + + dso->shdr[sec].sh_addr - 0x400; + /* slot+12 contains: ldx [%o7 + X], %g1 */ + GElf_Addr ptr = slot + (read_ube32 (dso, slot + 12) & 0xfff) + 4; + + write_be64 (dso, rela->r_offset, + dso->shdr[sec].sh_addr + - (slot + ((rela->r_offset - ptr) / 8) * 24 + 4)); + } + } + break; + case R_SPARC_RELATIVE: + case R_SPARC_GLOB_DAT: + case R_SPARC_64: + case R_SPARC_UA64: + case R_SPARC_DISP64: + write_be64 (dso, rela->r_offset, 0); + break; + case R_SPARC_32: + case R_SPARC_UA32: + case R_SPARC_DISP32: + write_be32 (dso, rela->r_offset, 0); + break; + case R_SPARC_8: + case R_SPARC_DISP8: + write_8 (dso, rela->r_offset, 0); + break; + case R_SPARC_16: + case R_SPARC_UA16: + case R_SPARC_DISP16: + write_be16 (dso, rela->r_offset, 0); + break; + case R_SPARC_LO10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_LM22: + case R_SPARC_HI22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_WDISP30: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xc0000000); + break; + case R_SPARC_H44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_M44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_L44: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0xfff); + break; + case R_SPARC_HH22: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & 0xffc00000); + break; + case R_SPARC_HM10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x3ff); + break; + case R_SPARC_OLO10: + write_be32 (dso, rela->r_offset, + read_ube32 (dso, rela->r_offset) & ~0x1fff); + break; + case R_SPARC_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_SPARC_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown sparc relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +sparc64_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_8: + case R_SPARC_DISP8: + return 1; + case R_SPARC_16: + case R_SPARC_DISP16: + case R_SPARC_UA16: + return 2; + case R_SPARC_RELATIVE: + case R_SPARC_64: + case R_SPARC_UA64: + case R_SPARC_GLOB_DAT: + return 8; + default: + break; + } + return 4; +} + +static int +sparc64_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_SPARC_COPY: return RTYPE_CLASS_COPY; + case R_SPARC_JMP_SLOT: return RTYPE_CLASS_PLT; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "SPARC", + .class = ELFCLASS64, + .machine = EM_SPARCV9, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_SPARC_JMP_SLOT, + .R_COPY = R_SPARC_COPY, + .R_RELATIVE = R_SPARC_RELATIVE, + .dynamic_linker = "/lib64/ld-linux.so.2", + .adjust_dyn = sparc64_adjust_dyn, + .adjust_rel = sparc64_adjust_rel, + .adjust_rela = sparc64_adjust_rela, + .prelink_rel = sparc64_prelink_rel, + .prelink_rela = sparc64_prelink_rela, + .prelink_conflict_rel = sparc64_prelink_conflict_rel, + .prelink_conflict_rela = sparc64_prelink_conflict_rela, + .apply_conflict_rela = sparc64_apply_conflict_rela, + .apply_rel = sparc64_apply_rel, + .apply_rela = sparc64_apply_rela, + .rel_to_rela = sparc64_rel_to_rela, + .need_rel_to_rela = sparc64_need_rel_to_rela, + .reloc_size = sparc64_reloc_size, + .reloc_class = sparc64_reloc_class, + .max_reloc_size = 8, + .arch_prelink = sparc64_arch_prelink, + .undo_prelink_rela = sparc64_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0xfffff80000000000, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0xfffff80001000000LL, + /* If we need yet more space for shared libraries, we can of course + expand, but limiting all DSOs into 4 GB means stack overflows + jumping to shared library functions is much harder (there is + '\0' byte in the address before the bytes that matter). */ + .mmap_end = 0xfffff80100000000LL, + .max_page_size = 0x100000, + .page_size = 0x2000 +}; diff --git a/trunk/src/arch-x86_64.c b/trunk/src/arch-x86_64.c new file mode 100644 index 0000000..8079f1a --- /dev/null +++ b/trunk/src/arch-x86_64.c @@ -0,0 +1,536 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> + +#include "prelink.h" + +static int +x86_64_adjust_dyn (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust) +{ + if (dyn->d_tag == DT_PLTGOT) + { + int sec = addr_to_sec (dso, dyn->d_un.d_ptr); + Elf64_Addr data; + + if (sec == -1) + return 0; + + data = read_ule64 (dso, dyn->d_un.d_ptr); + /* If .got.plt[0] points to _DYNAMIC, it needs to be adjusted. */ + if (data == dso->shdr[n].sh_addr && data >= start) + write_le64 (dso, dyn->d_un.d_ptr, data + adjust); + + data = read_ule64 (dso, dyn->d_un.d_ptr + 8); + /* If .got.plt[1] points to .plt + 0x16, it needs to be adjusted. */ + if (data && data >= start) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (data == dso->shdr[i].sh_addr + 0x16 + && dso->shdr[i].sh_type == SHT_PROGBITS + && strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), ".plt") == 0) + { + write_le64 (dso, dyn->d_un.d_ptr + 8, data + adjust); + break; + } + } + } + return 0; +} + +static int +x86_64_adjust_rel (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust) +{ + error (0, 0, "%s: X86-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +x86_64_adjust_rela (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust) +{ + Elf64_Addr addr; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_RELATIVE: + if (rela->r_addend >= start) + { + if (read_ule64 (dso, rela->r_offset) == rela->r_addend) + write_le64 (dso, rela->r_offset, rela->r_addend + adjust); + rela->r_addend += adjust; + } + break; + case R_X86_64_JUMP_SLOT: + addr = read_ule64 (dso, rela->r_offset); + if (addr >= start) + write_le64 (dso, rela->r_offset, addr + adjust); + break; + } + return 0; +} + +static int +x86_64_prelink_rel (struct prelink_info *info, GElf_Rel *rel, GElf_Addr reladdr) +{ + error (0, 0, "%s: X86-64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +x86_64_prelink_rela (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr) +{ + DSO *dso; + GElf_Addr value; + + dso = info->dso; + if (GELF_R_TYPE (rela->r_info) == R_X86_64_NONE) + return 0; + else if (GELF_R_TYPE (rela->r_info) == R_X86_64_RELATIVE) + { + write_le64 (dso, rela->r_offset, rela->r_addend); + return 0; + } + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + case R_X86_64_64: + write_le64 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_X86_64_32: + write_le32 (dso, rela->r_offset, value + rela->r_addend); + break; + case R_X86_64_PC32: + write_le32 (dso, rela->r_offset, value + rela->r_addend - rela->r_offset); + break; + case R_X86_64_DTPOFF64: + write_le64 (dso, rela->r_offset, value + rela->r_addend); + break; + /* DTPMOD64 and TPOFF64 is impossible to predict in shared libraries + unless prelink sets the rules. */ + case R_X86_64_DTPMOD64: + if (dso->ehdr.e_type == ET_EXEC) + { + error (0, 0, "%s: R_X86_64_DTPMOD64 reloc in executable?", + dso->filename); + return 1; + } + break; + case R_X86_64_TPOFF64: + if (dso->ehdr.e_type == ET_EXEC && info->resolvetls) + write_le64 (dso, rela->r_offset, + value + rela->r_addend - info->resolvetls->offset); + break; + case R_X86_64_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_X86_64_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown X86-64 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +x86_64_apply_conflict_rela (struct prelink_info *info, GElf_Rela *rela, + char *buf) +{ + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + case R_X86_64_64: + buf_write_le64 (buf, rela->r_addend); + break; + case R_X86_64_32: + buf_write_le32 (buf, rela->r_addend); + break; + default: + abort (); + } + return 0; +} + +static int +x86_64_apply_rel (struct prelink_info *info, GElf_Rel *rel, char *buf) +{ + error (0, 0, "%s: X86-64 doesn't support REL relocs", info->dso->filename); + return 1; +} + +static int +x86_64_apply_rela (struct prelink_info *info, GElf_Rela *rela, char *buf) +{ + GElf_Addr value; + + value = info->resolve (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_NONE: + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + case R_X86_64_64: + buf_write_le64 (buf, value + rela->r_addend); + break; + case R_X86_64_32: + buf_write_le32 (buf, value + rela->r_addend); + break; + case R_X86_64_PC32: + buf_write_le32 (buf, value + rela->r_addend - rela->r_offset); + break; + case R_X86_64_COPY: + abort (); + case R_X86_64_RELATIVE: + error (0, 0, "%s: R_X86_64_RELATIVE in ET_EXEC object?", info->dso->filename); + return 1; + default: + return 1; + } + return 0; +} + +static int +x86_64_prelink_conflict_rel (DSO *dso, struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr) +{ + error (0, 0, "%s: X86-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +x86_64_prelink_conflict_rela (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr) +{ + GElf_Addr value; + struct prelink_conflict *conflict; + struct prelink_tls *tls; + GElf_Rela *ret; + + if (GELF_R_TYPE (rela->r_info) == R_X86_64_RELATIVE + || GELF_R_TYPE (rela->r_info) == R_X86_64_NONE) + /* Fast path: nothing to do. */ + return 0; + conflict = prelink_conflict (info, GELF_R_SYM (rela->r_info), + GELF_R_TYPE (rela->r_info)); + if (conflict == NULL) + { + if (info->curtls == NULL) + return 0; + switch (GELF_R_TYPE (rela->r_info)) + { + /* Even local DTPMOD and TPOFF relocs need conflicts. */ + case R_X86_64_DTPMOD64: + case R_X86_64_TPOFF64: + break; + default: + return 0; + } + value = 0; + } + else + { + /* DTPOFF wants to see only real conflicts, not lookups + with reloc_class RTYPE_CLASS_TLS. */ + if (GELF_R_TYPE (rela->r_info) == R_X86_64_DTPOFF64 + && conflict->lookup.tls == conflict->conflict.tls + && conflict->lookupval == conflict->conflictval) + return 0; + + value = conflict_lookup_value (conflict); + } + ret = prelink_conflict_add_rela (info); + if (ret == NULL) + return 1; + ret->r_offset = rela->r_offset; + ret->r_info = GELF_R_INFO (0, GELF_R_TYPE (rela->r_info)); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_GLOB_DAT: + ret->r_info = GELF_R_INFO (0, R_X86_64_64); + /* FALLTHROUGH */ + case R_X86_64_JUMP_SLOT: + case R_X86_64_64: + ret->r_addend = value + rela->r_addend; + break; + case R_X86_64_32: + value += rela->r_addend; + ret->r_addend = value; + break; + case R_X86_64_PC32: + ret->r_addend = value + rela->r_addend - rela->r_offset; + ret->r_info = GELF_R_INFO (0, R_X86_64_32); + break; + case R_X86_64_COPY: + error (0, 0, "R_X86_64_COPY should not be present in shared libraries"); + return 1; + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + if (conflict != NULL + && (conflict->reloc_class != RTYPE_CLASS_TLS + || conflict->lookup.tls == NULL)) + { + error (0, 0, "%s: TLS reloc not resolving to STT_TLS symbol", + dso->filename); + return 1; + } + tls = conflict ? conflict->lookup.tls : info->curtls; + ret->r_info = GELF_R_INFO (0, R_X86_64_64); + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_DTPMOD64: + ret->r_addend = tls->modid; + break; + case R_X86_64_DTPOFF64: + ret->r_addend = value + rela->r_addend; + break; + case R_X86_64_TPOFF64: + ret->r_addend = value + rela->r_addend - tls->offset; + break; + } + break; + + default: + error (0, 0, "%s: Unknown X86-64 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +x86_64_rel_to_rela (DSO *dso, GElf_Rel *rel, GElf_Rela *rela) +{ + error (0, 0, "%s: X86-64 doesn't support REL relocs", dso->filename); + return 1; +} + +static int +x86_64_need_rel_to_rela (DSO *dso, int first, int last) +{ + return 0; +} + +static int +x86_64_arch_prelink (struct prelink_info *info) +{ + DSO *dso; + int i; + + dso = info->dso; + if (dso->info[DT_PLTGOT]) + { + /* Write address of .plt + 0x16 into got[1]. + .plt + 0x16 is what got[3] contains unless prelinking. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf64_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + assert (i < dso->ehdr.e_shnum); + data = dso->shdr[i].sh_addr + 0x16; + write_le64 (dso, dso->info[DT_PLTGOT] + 8, data); + } + + return 0; +} + +static int +x86_64_arch_undo_prelink (DSO *dso) +{ + int i; + + if (dso->info[DT_PLTGOT]) + { + /* Clear got[1] if it contains address of .plt + 0x16. */ + int sec = addr_to_sec (dso, dso->info[DT_PLTGOT]); + Elf64_Addr data; + + if (sec == -1) + return 1; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_PROGBITS + && ! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".plt")) + break; + + if (i == dso->ehdr.e_shnum) + return 0; + data = read_ule64 (dso, dso->info[DT_PLTGOT] + 8); + if (data == dso->shdr[i].sh_addr + 0x16) + write_le64 (dso, dso->info[DT_PLTGOT] + 8, 0); + } + + return 0; +} + +static int +x86_64_undo_prelink_rela (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr) +{ + int sec; + const char *name; + + switch (GELF_R_TYPE (rela->r_info)) + { + case R_X86_64_NONE: + case R_X86_64_RELATIVE: + break; + case R_X86_64_JUMP_SLOT: + sec = addr_to_sec (dso, rela->r_offset); + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[sec].sh_name); + if (sec == -1 || (strcmp (name, ".got") && strcmp (name, ".got.plt"))) + { + error (0, 0, "%s: R_X86_64_JUMP_SLOT not pointing into .got section", + dso->filename); + return 1; + } + else + { + Elf64_Addr data = read_ule64 (dso, dso->shdr[sec].sh_addr + 8); + + assert (rela->r_offset >= dso->shdr[sec].sh_addr + 24); + assert (((rela->r_offset - dso->shdr[sec].sh_addr) & 7) == 0); + write_le64 (dso, rela->r_offset, + 2 * (rela->r_offset - dso->shdr[sec].sh_addr - 24) + + data); + } + break; + case R_X86_64_GLOB_DAT: + case R_X86_64_64: + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + write_le64 (dso, rela->r_offset, 0); + break; + case R_X86_64_32: + case R_X86_64_PC32: + write_le32 (dso, rela->r_offset, 0); + break; + case R_X86_64_COPY: + if (dso->ehdr.e_type == ET_EXEC) + /* COPY relocs are handled specially in generic code. */ + return 0; + error (0, 0, "%s: R_X86_64_COPY reloc in shared library?", dso->filename); + return 1; + default: + error (0, 0, "%s: Unknown X86-64 relocation type %d", dso->filename, + (int) GELF_R_TYPE (rela->r_info)); + return 1; + } + return 0; +} + +static int +x86_64_reloc_size (int reloc_type) +{ + switch (reloc_type) + { + case R_X86_64_GLOB_DAT: + case R_X86_64_JUMP_SLOT: + case R_X86_64_64: + return 8; + default: + return 4; + } +} + +static int +x86_64_reloc_class (int reloc_type) +{ + switch (reloc_type) + { + case R_X86_64_COPY: return RTYPE_CLASS_COPY; + case R_X86_64_JUMP_SLOT: return RTYPE_CLASS_PLT; + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + return RTYPE_CLASS_TLS; + default: return RTYPE_CLASS_VALID; + } +} + +PL_ARCH = { + .name = "x86-64", + .class = ELFCLASS64, + .machine = EM_X86_64, + .alternate_machine = { EM_NONE }, + .R_JMP_SLOT = R_X86_64_JUMP_SLOT, + .R_COPY = R_X86_64_COPY, + .R_RELATIVE = R_X86_64_RELATIVE, + .dynamic_linker = "/lib64/ld-linux-x86-64.so.2", + .adjust_dyn = x86_64_adjust_dyn, + .adjust_rel = x86_64_adjust_rel, + .adjust_rela = x86_64_adjust_rela, + .prelink_rel = x86_64_prelink_rel, + .prelink_rela = x86_64_prelink_rela, + .prelink_conflict_rel = x86_64_prelink_conflict_rel, + .prelink_conflict_rela = x86_64_prelink_conflict_rela, + .apply_conflict_rela = x86_64_apply_conflict_rela, + .apply_rel = x86_64_apply_rel, + .apply_rela = x86_64_apply_rela, + .rel_to_rela = x86_64_rel_to_rela, + .need_rel_to_rela = x86_64_need_rel_to_rela, + .reloc_size = x86_64_reloc_size, + .reloc_class = x86_64_reloc_class, + .max_reloc_size = 8, + .arch_prelink = x86_64_arch_prelink, + .arch_undo_prelink = x86_64_arch_undo_prelink, + .undo_prelink_rela = x86_64_undo_prelink_rela, + /* Although TASK_UNMAPPED_BASE is 0x2a95555555, we leave some + area so that mmap of /etc/ld.so.cache and ld.so's malloc + does not take some library's VA slot. + Also, if this guard area isn't too small, typically + even dlopened libraries will get the slots they desire. */ + .mmap_base = 0x3000000000LL, + .mmap_end = 0x4000000000LL, + .max_page_size = 0x200000, + .page_size = 0x1000 +}; diff --git a/trunk/src/cache.c b/trunk/src/cache.c new file mode 100644 index 0000000..2a72267 --- /dev/null +++ b/trunk/src/cache.c @@ -0,0 +1,856 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include <sys/mman.h> +#include "prelinktab.h" + +htab_t prelink_devino_htab, prelink_filename_htab; + +int prelink_entry_count; + +static hashval_t +devino_hash (const void *p) +{ + struct prelink_entry *e = (struct prelink_entry *)p; + + return (e->dev << 2) ^ (e->ino) ^ (e->ino >> 20); +} + +static int +devino_eq (const void *p, const void *q) +{ + struct prelink_entry *e = (struct prelink_entry *)p; + struct prelink_entry *f = (struct prelink_entry *)q; + + return e->ino == f->ino && e->dev == f->dev; +} + +static hashval_t +filename_hash (const void *p) +{ + struct prelink_entry *e = (struct prelink_entry *)p; + const unsigned char *s = (const unsigned char *)e->filename; + hashval_t h = 0; + unsigned char c; + size_t len = 0; + + while ((c = *s++) != '\0') + { + h += c + (c << 17); + h ^= h >> 2; + ++len; + } + return h + len + (len << 17); +} + +static int +filename_eq (const void *p, const void *q) +{ + struct prelink_entry *e = (struct prelink_entry *)p; + struct prelink_entry *f = (struct prelink_entry *)q; + + return strcmp (e->filename, f->filename) == 0; +} + +int +prelink_init_cache (void) +{ + prelink_devino_htab = htab_try_create (100, devino_hash, devino_eq, NULL); + prelink_filename_htab = htab_try_create (100, filename_hash, filename_eq, + NULL); + if (prelink_devino_htab == NULL || prelink_filename_htab == NULL) + error (EXIT_FAILURE, ENOMEM, "Could not create hash table"); + return 0; +} + +struct prelink_entry * +prelink_find_entry (const char *filename, const struct stat64 *stp, + int insert) +{ + struct prelink_entry e, *ent = NULL; + void **filename_slot, *dummy = NULL; + void **devino_slot = NULL; + struct stat64 st; + char *canon_filename = NULL; + + e.filename = filename; + filename_slot = htab_find_slot (prelink_filename_htab, &e, + insert ? INSERT : NO_INSERT); + if (filename_slot == NULL) + { + if (insert) + goto error_out; + filename_slot = &dummy; + } + + if (*filename_slot != NULL) + return (struct prelink_entry *) *filename_slot; + + if (! stp) + { + canon_filename = wrap_prelink_canonicalize (filename, &st); + if (canon_filename == NULL && wrap_stat64 (filename, &st) < 0) + { + error (0, errno, "Could not stat %s", filename); + if (insert) + { + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } + return NULL; + } + stp = &st; + } + + e.dev = stp->st_dev; + e.ino = stp->st_ino; + devino_slot = htab_find_slot (prelink_devino_htab, &e, + insert ? INSERT : NO_INSERT); + if (devino_slot == NULL) + { + if (insert) + goto error_out; + free (canon_filename); + return NULL; + } + + if (*devino_slot != NULL) + { + ent = (struct prelink_entry *) *devino_slot; + if (canon_filename == NULL) + canon_filename = wrap_prelink_canonicalize (filename, NULL); + if (canon_filename == NULL) + { + error (0, 0, "Could not canonicalize filename %s", filename); + goto error_out2; + } + + if (strcmp (canon_filename, ent->canon_filename) != 0) + { + struct prelink_link *hardlink; + + hardlink = (struct prelink_link *) + malloc (sizeof (struct prelink_link)); + if (hardlink == NULL) + { + error (0, ENOMEM, "Could not record hardlink %s to %s", + canon_filename, ent->canon_filename); + goto error_out2; + } + + hardlink->canon_filename = canon_filename; + hardlink->next = ent->hardlink; + ent->hardlink = hardlink; + } + else + free (canon_filename); + return ent; + } + + if (! insert) + { + if (canon_filename != NULL) + free (canon_filename); + return NULL; + } + + ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1); + if (ent == NULL) + goto error_out; + + ent->filename = strdup (filename); + if (ent->filename == NULL) + goto error_out; + + if (canon_filename != NULL) + ent->canon_filename = canon_filename; + else + ent->canon_filename = wrap_prelink_canonicalize (filename, NULL); + if (ent->canon_filename == NULL) + { + error (0, 0, "Could not canonicalize filename %s", filename); + free ((char *) ent->filename); + free (ent); + goto error_out2; + } + + ent->dev = stp->st_dev; + ent->ino = stp->st_ino; + ent->ctime = stp->st_ctime; + ent->mtime = stp->st_mtime; + + *filename_slot = ent; + *devino_slot = ent; + ++prelink_entry_count; + return ent; + +error_out: + free (ent); + error (0, ENOMEM, "Could not insert %s into hash table", filename); +error_out2: + if (insert) + { + if (filename_slot != NULL) + { + assert (*filename_slot == NULL); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } + if (devino_slot != NULL && *devino_slot == NULL) + { + *devino_slot = &dummy; + htab_clear_slot (prelink_devino_htab, devino_slot); + } + } + free (canon_filename); + return NULL; +} + +static struct prelink_entry * +prelink_load_entry (const char *filename) +{ + struct prelink_entry e, *ent = NULL; + void **filename_slot, *dummy = NULL; + void **devino_slot = &dummy; + struct stat64 st; + uint32_t ctime = 0, mtime = 0; + char *canon_filename = NULL; + + e.filename = filename; + filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT); + if (filename_slot == NULL) + goto error_out; + + if (*filename_slot != NULL) + return (struct prelink_entry *) *filename_slot; + + canon_filename = wrap_prelink_canonicalize (filename, &st); + if (canon_filename == NULL) + goto error_out2; + if (strcmp (canon_filename, filename) != 0) + { + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + + e.filename = canon_filename; + filename_slot = htab_find_slot (prelink_filename_htab, &e, INSERT); + if (filename_slot == NULL) + goto error_out; + + if (*filename_slot != NULL) + { + free (canon_filename); + return (struct prelink_entry *) *filename_slot; + } + } + + if (! S_ISREG (st.st_mode)) + { + free (canon_filename); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + return NULL; + } + else + { + e.dev = st.st_dev; + e.ino = st.st_ino; + ctime = (uint32_t) st.st_ctime; + mtime = (uint32_t) st.st_mtime; + devino_slot = htab_find_slot (prelink_devino_htab, &e, INSERT); + if (devino_slot == NULL) + goto error_out; + } + + if (*devino_slot != NULL) + { + free (canon_filename); + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + return (struct prelink_entry *) *devino_slot; + } + + ent = (struct prelink_entry *) calloc (sizeof (struct prelink_entry), 1); + if (ent == NULL) + goto error_out; + + ent->filename = strdup (filename); + if (ent->filename == NULL) + goto error_out; + + ent->canon_filename = canon_filename; + ent->dev = e.dev; + ent->ino = e.ino; + ent->ctime = ctime; + ent->mtime = mtime; + *filename_slot = ent; + *devino_slot = ent; + ++prelink_entry_count; + return ent; + +error_out: + free (ent); + error (0, ENOMEM, "Could not insert %s into hash table", filename); +error_out2: + if (filename_slot != NULL) + { + *filename_slot = &dummy; + htab_clear_slot (prelink_filename_htab, filename_slot); + } + if (devino_slot != NULL && devino_slot != &dummy) + { + *devino_slot = &dummy; + htab_clear_slot (prelink_devino_htab, devino_slot); + } + free (canon_filename); + return NULL; +} + +static int +deps_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + + if (a == NULL) + return (b != NULL); + if (a != NULL && b == NULL) + return -1; + + if (a->type == ET_NONE && b->type != ET_NONE) + return 1; + if (a->type != ET_NONE && b->type == ET_NONE) + return -1; + + /* Libraries with fewest dependencies first. */ + if (a->ndepends < b->ndepends) + return -1; + if (a->ndepends > b->ndepends) + return 1; + return 0; +} + +int +prelink_load_cache (void) +{ + int fd, i, j; + struct stat64 st; + struct prelink_cache *cache; + struct prelink_entry **ents; + size_t cache_size; + uint32_t string_start, *dep; + + fd = wrap_open (prelink_cache, O_RDONLY); + if (fd < 0) + return 0; /* The cache does not exist yet. */ + + if (fstat64 (fd, &st) < 0 + || st.st_size == 0) + { + close (fd); + return 0; + } + + cache = mmap (0, st.st_size, PROT_READ, MAP_SHARED, fd, 0); + if (cache == MAP_FAILED) + error (EXIT_FAILURE, errno, "mmap of prelink cache file failed."); + cache_size = st.st_size; + if (memcmp (cache->magic, PRELINK_CACHE_MAGIC, + sizeof (PRELINK_CACHE_MAGIC) - 1)) + { + if (memcmp (cache->magic, PRELINK_CACHE_NAME, + sizeof (PRELINK_CACHE_NAME) - 1)) + error (EXIT_FAILURE, 0, "%s: is not prelink cache file", + prelink_cache); + munmap (cache, cache_size); + return 0; + } + dep = (uint32_t *) & cache->entry[cache->nlibs]; + string_start = ((long) dep) - ((long) cache) + + cache->ndeps * sizeof (uint32_t); + ents = (struct prelink_entry **) + alloca (cache->nlibs * sizeof (struct prelink_entry *)); + memset (ents, 0, cache->nlibs * sizeof (struct prelink_entry *)); + for (i = 0; i < cache->nlibs; i++) + { + /* Sanity checks. */ + if (cache->entry[i].filename < string_start + || cache->entry[i].filename >= string_start + cache->len_strings + || cache->entry[i].depends >= cache->ndeps) + error (EXIT_FAILURE, 0, "%s: bogus prelink cache file", + prelink_cache); + + ents[i] = prelink_load_entry (((char *) cache) + + cache->entry[i].filename); + } + + for (i = 0; i < cache->nlibs; i++) + { + if (ents[i] == NULL) + continue; + + if (ents[i]->type != ET_NONE) + continue; + + ents[i]->checksum = cache->entry[i].checksum; + ents[i]->base = cache->entry[i].base; + ents[i]->end = cache->entry[i].end; + ents[i]->type = (ents[i]->base == 0 && ents[i]->end == 0) + ? ET_CACHE_EXEC : ET_CACHE_DYN; + ents[i]->flags = cache->entry[i].flags; + + if (ents[i]->flags == PCF_UNPRELINKABLE) + ents[i]->type = (quick || print_cache) ? ET_UNPRELINKABLE : ET_NONE; + + /* If mtime is equal to ctime, assume the filesystem does not store + ctime. */ + if (quick + && ((ents[i]->ctime == ents[i]->mtime + && ents[i]->type != ET_UNPRELINKABLE) + || ents[i]->ctime != cache->entry[i].ctime + || ents[i]->mtime != cache->entry[i].mtime)) + ents[i]->type = ET_NONE; + + for (j = cache->entry[i].depends; dep[j] != i; ++j) + if (dep[j] >= cache->nlibs) + error (EXIT_FAILURE, 0, "%s: bogus prelink cache file", + prelink_cache); + else if (ents[dep[j]] == NULL) + ents[i]->type = ET_NONE; + + if (ents[i]->type == ET_NONE) + continue; + + ents[i]->ndepends = j - cache->entry[i].depends; + if (ents[i]->ndepends) + { + ents[i]->depends = + (struct prelink_entry **) + malloc (ents[i]->ndepends * sizeof (struct prelink_entry *)); + if (ents[i]->depends == NULL) + error (EXIT_FAILURE, ENOMEM, "Cannot read cache file %s", + prelink_cache); + + for (j = 0; j < ents[i]->ndepends; ++j) + ents[i]->depends[j] = ents[dep[cache->entry[i].depends + j]]; + } + } + + if (quick) + { + qsort (ents, cache->nlibs, sizeof (struct prelink_entry *), deps_cmp); + for (i = 0; i < cache->nlibs; ++i) + { + if (ents[i] == NULL || ents[i]->type == ET_NONE) + continue; + + for (j = 0; j < ents[i]->ndepends; ++j) + if (ents[i]->depends[j]->type == ET_NONE) + { + ents[i]->type = ET_NONE; + free (ents[i]->depends); + ents[i]->depends = NULL; + ents[i]->ndepends = 0; + break; + } + } + } + + munmap (cache, cache_size); + close (fd); + return 0; +} + +static int +prelink_print_cache_size (void **p, void *info) +{ + struct prelink_entry *e = * (struct prelink_entry **) p; + int *psize = (int *) info; + + if ((e->base & 0xffffffff) != e->base + || (e->end & 0xffffffff) != e->end) + { + *psize = 16; + return 0; + } + + return 1; +} + +static int +prelink_print_cache_object (void **p, void *info) +{ + struct prelink_entry *e = * (struct prelink_entry **) p; + int *psize = (int *) info, i; + + if (e->type == ET_UNPRELINKABLE) + { + printf ("%s (not prelinkable)%s\n", e->filename, e->ndepends ? ":" : ""); + for (i = 0; i < e->ndepends; i++) + if (e->depends[i]->type == ET_UNPRELINKABLE) + printf (" %s (not prelinkable)\n", e->depends[i]->filename); + else + printf (" %s [0x%08x]\n", e->depends[i]->filename, + e->depends[i]->checksum); + return 1; + } + + if (e->type == ET_CACHE_DYN) + printf ("%s [0x%08x] 0x%0*llx-0x%0*llx%s\n", e->filename, e->checksum, + *psize, (long long) e->base, *psize, (long long) e->end, + e->ndepends ? ":" : ""); + else + printf ("%s%s\n", e->filename, e->ndepends ? ":" : ""); + for (i = 0; i < e->ndepends; i++) + printf (" %s [0x%08x]\n", e->depends[i]->filename, + e->depends[i]->checksum); + return 1; +} + +int +prelink_print_cache (void) +{ + int size = 8; + + printf ("%d objects found in prelink cache `%s'\n", prelink_entry_count, + prelink_cache); + + htab_traverse (prelink_filename_htab, prelink_print_cache_size, &size); + htab_traverse (prelink_filename_htab, prelink_print_cache_object, &size); + return 0; +} + +struct collect_ents +{ + struct prelink_entry **ents; + size_t len_strings; + int nents; + int ndeps; +}; + +static int +prelink_save_cache_check (struct prelink_entry *ent) +{ + int i; + + for (i = 0; i < ent->ndepends; ++i) + switch (ent->depends[i]->type) + { + case ET_DYN: + if (ent->depends[i]->done < 2 + || (quick && (ent->depends[i]->flags & PCF_PRELINKED))) + return 1; + break; + case ET_CACHE_DYN: + break; + case ET_UNPRELINKABLE: + if (ent->type != ET_UNPRELINKABLE) + return 1; + break; + default: + return 1; + } + + return 0; +} + +static int +find_ents (void **p, void *info) +{ + struct collect_ents *l = (struct collect_ents *) info; + struct prelink_entry *e = * (struct prelink_entry **) p; + + if (((e->type == ET_DYN || e->type == ET_EXEC) && e->done == 2) + || ((e->type == ET_CACHE_DYN || e->type == ET_CACHE_EXEC + || e->type == ET_UNPRELINKABLE) + && ! prelink_save_cache_check (e))) + { + l->ents[l->nents++] = e; + l->ndeps += e->ndepends + 1; + l->len_strings += strlen (e->canon_filename) + 1; + } + return 1; +} + +int +prelink_save_cache (int do_warn) +{ + struct prelink_cache cache; + struct collect_ents l; + struct prelink_cache_entry *data; + uint32_t *deps, ndeps = 0, i, j, k; + char *strings; + int fd, len; + struct prelink_entry *ents_array[prelink_entry_count]; + + memset (&cache, 0, sizeof (cache)); + memcpy ((char *) & cache, PRELINK_CACHE_MAGIC, + sizeof (PRELINK_CACHE_MAGIC) - 1); + l.ents = ents_array; + l.nents = 0; + l.ndeps = 0; + l.len_strings = 0; + htab_traverse (prelink_filename_htab, find_ents, &l); + cache.nlibs = l.nents; + cache.ndeps = l.ndeps; + cache.len_strings = l.len_strings; + + len = cache.nlibs * sizeof (struct prelink_cache_entry) + + cache.ndeps * sizeof (uint32_t) + cache.len_strings; + char data_buf[len]; + data = (struct prelink_cache_entry *) data_buf; + deps = (uint32_t *) & data[cache.nlibs]; + strings = (char *) & deps[cache.ndeps]; + + for (i = 0; i < l.nents; ++i) + { + data[i].filename = (strings - (char *) data) + sizeof (cache); + strings = stpcpy (strings, l.ents[i]->canon_filename) + 1; + data[i].checksum = l.ents[i]->checksum; + data[i].flags = l.ents[i]->flags & ~PCF_PRELINKED; + data[i].ctime = l.ents[i]->ctime; + data[i].mtime = l.ents[i]->mtime; + if (l.ents[i]->type == ET_EXEC || l.ents[i]->type == ET_CACHE_EXEC) + { + data[i].base = 0; + data[i].end = 0; + } + else if (l.ents[i]->type == ET_UNPRELINKABLE) + { + data[i].base = 0; + data[i].end = 0; + data[i].checksum = 0; + data[i].flags = PCF_UNPRELINKABLE; + } + else + { + data[i].base = l.ents[i]->base; + data[i].end = l.ents[i]->end; + } + } + + for (i = 0; i < cache.nlibs; i++) + { + data[i].depends = ndeps; + for (j = 0; j < l.ents[i]->ndepends; j++) + { + for (k = 0; k < cache.nlibs; k++) + if (l.ents[k] == l.ents[i]->depends[j]) + break; + if (k == cache.nlibs) + abort (); + deps[ndeps++] = k; + } + deps[ndeps++] = i; + } + + size_t prelink_cache_len = strlen (prelink_cache); + char prelink_cache_tmp [prelink_cache_len + sizeof (".XXXXXX")]; + memcpy (mempcpy (prelink_cache_tmp, prelink_cache, prelink_cache_len), + ".XXXXXX", sizeof (".XXXXXX")); + fd = wrap_mkstemp (prelink_cache_tmp); + if (fd < 0) + { + error (0, errno, "Could not write prelink cache"); + return 1; + } + + if (write (fd, &cache, sizeof (cache)) != sizeof (cache) + || write (fd, data, len) != len + || fchmod (fd, 0644) + || close (fd) + || wrap_rename (prelink_cache_tmp, prelink_cache)) + { + error (0, errno, "Could not write prelink cache"); + wrap_unlink (prelink_cache_tmp); + return 1; + } + return 0; +} + +#ifndef NDEBUG +static void +prelink_entry_dumpfn (FILE *f, const void *ptr) +{ + struct prelink_entry *e = (struct prelink_entry *) ptr; + struct prelink_link *l; + int i; + + fprintf (f, "%s|%s|%s|%x|%x|%llx|%llx|%llx|%llx|%llx|%d|%d|%d|%d|%d|%d|%d|", + e->filename, + strcmp (e->canon_filename, e->filename) ? e->canon_filename : "", + e->soname && strcmp (e->soname, e->filename) ? e->soname : "", + e->timestamp, e->checksum, + (long long) e->base, (long long) e->end, (long long) e->pltgot, + (long long) e->dev, (long long) e->ino, + e->type, e->done, e->ndepends, e->refs, e->flags, + e->prev ? e->prev->u.tmp : -1, e->next ? e->next->u.tmp : -1); + for (i = 0; i < e->ndepends; ++i) + fprintf (f, "%d-", e->depends [i]->u.tmp); + fputc ('|', f); + for (l = e->hardlink; l; l = l->next) + fprintf (f, "%s|", l->canon_filename); + fputs ("\n", f); +} + +void +prelink_entry_dump (htab_t htab, const char *filename) +{ + size_t i; + + for (i = 0; i < htab->size; ++i) + if (htab->entries [i] && htab->entries [i] != (void *) 1) + ((struct prelink_entry *) htab->entries [i])->u.tmp = i; + htab_dump (htab, filename, prelink_entry_dumpfn); +} + +static char *restore_line; +static size_t restore_size; + +static void * +prelink_entry_restorefn (FILE *f) +{ + struct prelink_entry *e; + struct prelink_link **plink; + char *p, *q, *s; + long long ll[5]; + int ii[5]; + int i; + + if (getline (&restore_line, &restore_size, f) < 0) + abort (); + e = (struct prelink_entry *) calloc (1, sizeof (struct prelink_entry)); + if (e == NULL) + abort (); + p = restore_line; + q = strchr (p, '|'); + s = malloc (q - p + 1); + memcpy (s, p, q - p); + s [q - p] = '\0'; + e->filename = s; + ++q; + p = q; + if (*p == '|') + e->canon_filename = strdup (e->filename); + else + { + q = strchr (p, '|'); + s = malloc (q - p + 1); + memcpy (s, p, q - p); + s [q - p] = '\0'; + e->canon_filename = s; + } + ++q; + p = q; + if (*p == '|') + e->soname = strdup (e->filename); + else + { + q = strchr (p, '|'); + s = malloc (q - p + 1); + memcpy (s, p, q - p); + s [q - p] = '\0'; + e->soname = s; + } + p = q + 1; + if (sscanf (p, "%x|%x|%llx|%llx|%llx|%llx|%llx|%d|%d|%d|%d|%d|%d|%d|%n", + ii, ii + 1, ll, ll + 1, ll + 2, ll + 3, ll + 4, + &e->type, &e->done, &e->ndepends, &e->refs, &e->flags, + ii + 2, ii + 3, ii + 4) < 14) + abort (); + e->timestamp = ii[0]; + e->checksum = ii[1]; + e->base = ll[0]; + e->end = ll[1]; + e->pltgot = ll[2]; + e->dev = ll[3]; + e->ino = ll[4]; + e->prev = (void *) (long) ii[2]; + e->next = (void *) (long) ii[3]; + e->depends = (struct prelink_entry **) + malloc (e->ndepends * sizeof (struct prelink_entry *)); + p += ii[4]; + for (i = 0; i < e->ndepends; ++i) + { + e->depends [i] = (void *) strtol (p, &q, 0); + if (p == q || *q != '-') + abort (); + p = q + 1; + } + if (*p++ != '|') + abort (); + plink = &e->hardlink; + while (*p != '\n') + { + struct prelink_link *link = (struct prelink_link *) + malloc (sizeof (struct prelink_link)); + q = strchr (p, '|'); + *plink = link; + plink = &link->next; + s = malloc (q - p + 1); + memcpy (s, p, q - p); + s [q - p] = '\0'; + e->soname = s; + link->canon_filename = s; + p = q + 1; + } + *plink = NULL; + ++prelink_entry_count; + return e; +} + +void +prelink_entry_restore (htab_t htab, const char *filename) +{ + size_t i, j; + struct prelink_entry *e; + + prelink_entry_count = 0; + htab_restore (htab, filename, prelink_entry_restorefn); + free (restore_line); + for (i = 0; i < htab->size; ++i) + if (htab->entries [i] && htab->entries [i] != (void *) 1) + { + e = (struct prelink_entry *) htab->entries [i]; + if (e->prev == (void *) -1) + e->prev = NULL; + else + e->prev = (struct prelink_entry *) + htab->entries [(long) e->prev]; + if (e->next == (void *) -1) + e->next = NULL; + else + e->next = (struct prelink_entry *) + htab->entries [(long) e->next]; + for (j = 0; j < e->ndepends; ++j) + { + e->depends [j] = (struct prelink_entry *) + htab->entries [(long) e->depends [j]]; + } + } +} +#endif diff --git a/trunk/src/canonicalize.c b/trunk/src/canonicalize.c new file mode 100644 index 0000000..79df44e --- /dev/null +++ b/trunk/src/canonicalize.c @@ -0,0 +1,319 @@ +/* Return the canonical absolute name of a given file. + Copyright (C) 1996-2002, 2004, 2005, 2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#include <assert.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <limits.h> +#include <sys/param.h> +#include <sys/stat.h> +#include <errno.h> +#include <stddef.h> + +#include "hashtab.h" + +htab_t prelink_dirname_htab; + +struct dirname_entry +{ + const char *dirname; + size_t dirname_len; + const char *canon_dirname; + size_t canon_dirname_len; +}; + +static hashval_t +dirname_hash (const void *p) +{ + struct dirname_entry *e = (struct dirname_entry *)p; + const unsigned char *s = (const unsigned char *)e->dirname; + hashval_t h = 0; + unsigned char c; + size_t len = e->dirname_len; + + while (len--) + { + c = *s++; + h += c + (c << 17); + h ^= h >> 2; + } + return h + e->dirname_len + (e->dirname_len << 17); +} + +static int +dirname_eq (const void *p, const void *q) +{ + struct dirname_entry *e = (struct dirname_entry *)p; + struct dirname_entry *f = (struct dirname_entry *)q; + + return (e->dirname_len == f->dirname_len + && memcmp (e->dirname, f->dirname, e->dirname_len) == 0); +} + +/* Return the canonical absolute name of file NAME. A canonical name + does not contain any `.', `..' components nor any repeated path + separators ('/') or symlinks. All path components must exist. + The result is malloc'd. */ + +static char * +canon_filename (const char *name, int nested, struct stat64 *stp) +{ + char *rpath, *dest, *extra_buf = NULL; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + int stp_initialized = 0; + + if (name == NULL) + { + errno = EINVAL; + return NULL; + } + + if (name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + rpath = malloc (path_max); + if (rpath == NULL) + return NULL; + rpath_limit = rpath + path_max; + + if (name[0] != '/') + { + if (!getcwd (rpath, path_max)) + { + rpath[0] = '\0'; + goto error; + } + dest = strchr (rpath, '\0'); + } + else + { + rpath[0] = '/'; + dest = rpath + 1; + + if (!nested) + { + if (prelink_dirname_htab == NULL) + prelink_dirname_htab = htab_try_create (100, dirname_hash, + dirname_eq, NULL); + if (prelink_dirname_htab == NULL) + nested = 1; + } + if (!nested) + { + struct dirname_entry e; + void **dirname_slot; + + end = strrchr (name, '/'); + + e.dirname = name; + e.dirname_len = end - name; + dirname_slot = htab_find_slot (prelink_dirname_htab, &e, INSERT); + if (*dirname_slot == NULL) + { + struct dirname_entry *ep = malloc (sizeof (struct dirname_entry) + + e.dirname_len + 1); + if (ep != NULL) + { + char *dirname = (char *) (ep + 1); + struct stat64 st; + + ep->dirname = (const char *) dirname; + ep->dirname_len = e.dirname_len; + memcpy (dirname, name, ep->dirname_len); + dirname[ep->dirname_len] = '\0'; + ep->canon_dirname = canon_filename (ep->dirname, 1, &st); + if (ep->canon_dirname == NULL || !S_ISDIR (st.st_mode)) + free (ep); + else + { + ep->canon_dirname_len = strlen (ep->canon_dirname); + *dirname_slot = ep; + } + } + } + + if (*dirname_slot != NULL) + { + struct dirname_entry *ep = *dirname_slot; + + if (rpath + ep->canon_dirname_len + 1 >= rpath_limit) + { + size_t new_size; + char *new_rpath; + + new_size = rpath_limit - rpath; + if (ep->canon_dirname_len + 1 > path_max) + new_size += ep->canon_dirname_len + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + } + dest = mempcpy (rpath, ep->canon_dirname, ep->canon_dirname_len); + *dest = '\0'; + name = end + 1; + } + } + } + + for (start = end = name; *start; start = end) + { + int n; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') + ++start; + + /* Find end of path component. */ + for (end = start; *end && *end != '/'; ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + stp_initialized = 0; + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + + dest = mempcpy (dest, start, end - start); + *dest = '\0'; + + if (lstat64 (rpath, stp) < 0) + goto error; + + stp_initialized = 1; + + if (S_ISLNK (stp->st_mode)) + { + char *buf = alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + errno = ELOOP; + goto error; + } + + n = readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + errno = ENAMETOOLONG; + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (buf[0] == '/') + dest = rpath + 1; /* It's an absolute symlink */ + else + /* Back up to previous component, ignore if at root already: */ + if (dest > rpath + 1) + while ((--dest)[-1] != '/'); + } + else if (!S_ISDIR (stp->st_mode) && *end != '\0') + { + errno = ENOTDIR; + goto error; + } + } + } + if (dest > rpath + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + if (!stp_initialized && lstat64 (rpath, stp) < 0) + goto error; + + if (dest + 1 - rpath <= (rpath_limit - rpath) / 2) + { + char *new_rpath = realloc (rpath, dest + 1 - rpath); + + if (new_rpath != NULL) + return new_rpath; + } + return rpath; + +error: + free (rpath); + return NULL; +} + +char * +prelink_canonicalize (const char *name, struct stat64 *stp) +{ + struct stat64 st; + return canon_filename (name, 0, stp ? stp : &st); +} diff --git a/trunk/src/checksum.c b/trunk/src/checksum.c new file mode 100644 index 0000000..20a23a0 --- /dev/null +++ b/trunk/src/checksum.c @@ -0,0 +1,89 @@ +/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "prelink.h" + +int +prelink_set_checksum (DSO *dso) +{ + extern uint32_t crc32 (uint32_t crc, unsigned char *buf, size_t len); + uint32_t crc; + int i, cvt; + + if (set_dynamic (dso, DT_CHECKSUM, 0, 1)) + return 1; + + if (dso->info_DT_GNU_PRELINKED + && set_dynamic (dso, DT_GNU_PRELINKED, 0, 1)) + return 1; + + /* Ensure any pending .mdebug/.dynsym/.dynstr etc. modifications + write_dso would do happen before checksumming. */ + if (prepare_write_dso (dso)) + return 1; + + cvt = ! ((__BYTE_ORDER == __LITTLE_ENDIAN + && dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + || (__BYTE_ORDER == __BIG_ENDIAN + && dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB)); + crc = 0; + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))) + continue; + if (dso->shdr[i].sh_type != SHT_NOBITS && dso->shdr[i].sh_size) + { + Elf_Scn *scn = dso->scn[i]; + Elf_Data *d = NULL; + + /* Cannot use elf_rawdata here, since the image is not written + yet. */ + while ((d = elf_getdata (scn, d)) != NULL) + { + if (cvt && d->d_type != ELF_T_BYTE) + { + gelf_xlatetof (dso->elf, d, d, + dso->ehdr.e_ident[EI_DATA]); + crc = crc32 (crc, d->d_buf, d->d_size); + gelf_xlatetom (dso->elf, d, d, + dso->ehdr.e_ident[EI_DATA]); + } + else + crc = crc32 (crc, d->d_buf, d->d_size); + } + } + } + + if (set_dynamic (dso, DT_CHECKSUM, crc, 1)) + abort (); + if (dso->info_DT_GNU_PRELINKED + && set_dynamic (dso, DT_GNU_PRELINKED, dso->info_DT_GNU_PRELINKED, 1)) + abort (); + dso->info_DT_CHECKSUM = crc; + + return 0; +} diff --git a/trunk/src/conflict.c b/trunk/src/conflict.c new file mode 100644 index 0000000..db36054 --- /dev/null +++ b/trunk/src/conflict.c @@ -0,0 +1,804 @@ +/* Copyright (C) 2001, 2002, 2003, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" + +struct prelink_conflict * +prelink_conflict (struct prelink_info *info, GElf_Word r_sym, + int reloc_type) +{ + GElf_Word symoff = info->symtab_start + r_sym * info->symtab_entsize; + struct prelink_conflict *conflict; + int reloc_class = info->dso->arch->reloc_class (reloc_type); + + for (conflict = info->curconflicts; conflict; conflict = conflict->next) + if (conflict->symoff == symoff && conflict->reloc_class == reloc_class) + { + conflict->used = 1; + return conflict; + } + + return NULL; +} + +GElf_Rela * +prelink_conflict_add_rela (struct prelink_info *info) +{ + GElf_Rela *ret; + + if (info->conflict_rela_alloced == info->conflict_rela_size) + { + info->conflict_rela_alloced += 10; + info->conflict_rela = realloc (info->conflict_rela, + info->conflict_rela_alloced + * sizeof (GElf_Rela)); + if (info->conflict_rela == NULL) + { + error (0, ENOMEM, "Could not build .gnu.conflict section memory image"); + return NULL; + } + } + ret = info->conflict_rela + info->conflict_rela_size++; + ret->r_offset = 0; + ret->r_info = 0; + ret->r_addend = 0; + return ret; +} + +static int +prelink_conflict_rel (DSO *dso, int n, struct prelink_info *info) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + if (dso->arch->prelink_conflict_rel (dso, info, &rel, addr)) + return 1; + } + } + return 0; +} + +static int +prelink_conflict_rela (DSO *dso, int n, struct prelink_info *info) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + if (dso->arch->prelink_conflict_rela (dso, info, &rela, addr)) + return 1; + } + } + return 0; +} + +struct copy_relocs +{ + GElf_Rela *rela; + int alloced; + int count; +}; + +static int +prelink_add_copy_rel (DSO *dso, int n, GElf_Rel *rel, struct copy_relocs *cr) +{ + Elf_Data *data = NULL; + int symsec = dso->shdr[n].sh_link; + Elf_Scn *scn = dso->scn[symsec]; + GElf_Sym sym; + size_t entsize = dso->shdr[symsec].sh_entsize; + off_t off = GELF_R_SYM (rel->r_info) * entsize; + + while ((data = elf_getdata (scn, data)) != NULL) + { + if (data->d_off <= off && + data->d_off + data->d_size >= off + entsize) + { + gelfx_getsym (dso->elf, data, (off - data->d_off) / entsize, &sym); + if (sym.st_size == 0) + { + error (0, 0, "%s: Copy reloc against symbol with zero size", + dso->filename); + return 1; + } + + if (cr->alloced == cr->count) + { + cr->alloced += 10; + cr->rela = realloc (cr->rela, cr->alloced * sizeof (GElf_Rela)); + if (cr->rela == NULL) + { + error (0, ENOMEM, "%s: Could not build list of COPY relocs", + dso->filename); + return 1; + } + } + cr->rela[cr->count].r_offset = rel->r_offset; + cr->rela[cr->count].r_info = rel->r_info; + cr->rela[cr->count].r_addend = sym.st_size; + ++cr->count; + return 0; + } + } + + error (0, 0, "%s: Copy reloc against unknown symbol", dso->filename); + return 1; +} + +static int +prelink_find_copy_rel (DSO *dso, int n, struct copy_relocs *cr) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + if (GELF_R_TYPE (rel.r_info) == dso->arch->R_COPY + && prelink_add_copy_rel (dso, n, &rel, cr)) + return 1; + } + } + return 0; +} + +static int +prelink_find_copy_rela (DSO *dso, int n, struct copy_relocs *cr) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + union { + GElf_Rel rel; + GElf_Rela rela; + } u; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrela (dso->elf, data, ndx, &u.rela); + sec = addr_to_sec (dso, u.rela.r_offset); + if (sec == -1) + continue; + + if (GELF_R_TYPE (u.rela.r_info) == dso->arch->R_COPY) + { + if (u.rela.r_addend != 0) + { + error (0, 0, "%s: COPY reloc with non-zero addend?", + dso->filename); + return 1; + } + if (prelink_add_copy_rel (dso, n, &u.rel, cr)) + return 1; + } + } + } + return 0; +} + +static int +rela_cmp (const void *A, const void *B) +{ + GElf_Rela *a = (GElf_Rela *)A; + GElf_Rela *b = (GElf_Rela *)B; + + if (a->r_offset < b->r_offset) + return -1; + if (a->r_offset > b->r_offset) + return 1; + return 0; +} + +static int +conflict_rela_cmp (const void *A, const void *B) +{ + GElf_Rela *a = (GElf_Rela *)A; + GElf_Rela *b = (GElf_Rela *)B; + + if (GELF_R_SYM (a->r_info) < GELF_R_SYM (b->r_info)) + return -1; + if (GELF_R_SYM (a->r_info) > GELF_R_SYM (b->r_info)) + return 1; + if (a->r_offset < b->r_offset) + return -1; + if (a->r_offset > b->r_offset) + return 1; + return 0; +} + +int +get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr, + char *buf, GElf_Word size) +{ + int sec = addr_to_sec (dso, addr), j; + Elf_Scn *scn; + Elf_Data *data; + off_t off; + + if (sec == -1) + return 1; + + memset (buf, 0, size); + if (dso->shdr[sec].sh_type != SHT_NOBITS) + { + scn = dso->scn[sec]; + data = NULL; + off = addr - dso->shdr[sec].sh_addr; + while ((data = elf_rawdata (scn, data)) != NULL) + { + if (data->d_off < off + size + && data->d_off + data->d_size > off) + { + off_t off2 = off - data->d_off; + size_t len = size; + + if (off2 < 0) + { + len += off2; + off2 = 0; + } + if (off2 + len > data->d_size) + len = data->d_size - off2; + assert (off2 + len <= data->d_size); + assert (len <= size); + memcpy (buf + off2 - off, data->d_buf + off2, len); + } + } + } + + if (info->dso != dso) + { + /* This is tricky. We need to apply any conflicts + against memory area which we've copied to the COPY + reloc offset. */ + for (j = 0; j < info->conflict_rela_size; ++j) + { + int reloc_type, reloc_size; + off_t off; + + if (info->conflict_rela[j].r_offset >= addr + size) + continue; + if (info->conflict_rela[j].r_offset + dso->arch->max_reloc_size + <= addr) + continue; + + reloc_type = GELF_R_TYPE (info->conflict_rela[j].r_info); + reloc_size = dso->arch->reloc_size (reloc_type); + if (info->conflict_rela[j].r_offset + reloc_size <= addr) + continue; + + off = info->conflict_rela[j].r_offset - addr; + + /* Check if whole relocation fits into the area. + Punt if not. */ + if (off < 0 || size - off < reloc_size) + return 2; + /* Note that apply_conflict_rela shouldn't rely on R_SYM + field of conflict to be 0. */ + dso->arch->apply_conflict_rela (info, info->conflict_rela + j, + buf + off); + } + } + else + { + int i, ndx, maxndx; + int reloc_type, reloc_size; + union { GElf_Rel rel; GElf_Rela rela; } u; + off_t off; + + if (addr + size > info->dynbss_base + && addr < info->dynbss_base + info->dynbss_size) + { + if (addr < info->dynbss_base + || addr + size > info->dynbss_base + info->dynbss_size) + return 4; + + memcpy (buf, info->dynbss + (addr - info->dynbss_base), size); + return 0; + } + + if (addr + size > info->sdynbss_base + && addr < info->sdynbss_base + info->sdynbss_size) + { + if (addr < info->sdynbss_base + || addr + size > info->sdynbss_base + info->sdynbss_size) + return 4; + + memcpy (buf, info->sdynbss + (addr - info->sdynbss_base), size); + return 0; + } + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + + if (! (dso->shdr[i].sh_flags & SHF_ALLOC)) + continue; + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".gnu.conflict")) + continue; + switch (dso->shdr[i].sh_type) + { + case SHT_REL: + case SHT_RELA: + break; + default: + continue; + } + scn = dso->scn[i]; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + if (dso->shdr[i].sh_type == SHT_REL) + gelfx_getrel (dso->elf, data, ndx, &u.rel); + else + gelfx_getrela (dso->elf, data, ndx, &u.rela); + + if (u.rel.r_offset >= addr + size) + continue; + if (u.rel.r_offset + dso->arch->max_reloc_size <= addr) + continue; + + reloc_type = GELF_R_TYPE (u.rel.r_info); + reloc_size = dso->arch->reloc_size (reloc_type); + if (u.rel.r_offset + reloc_size <= addr) + continue; + + if (reloc_type == dso->arch->R_COPY) + return 3; + + off = u.rel.r_offset - addr; + + /* Check if whole relocation fits into the area. + Punt if not. */ + if (off < 0 || size - off < reloc_size) + return 2; + + if (dso->shdr[i].sh_type == SHT_REL) + dso->arch->apply_rel (info, &u.rel, buf + off); + else + dso->arch->apply_rela (info, &u.rela, buf + off); + } + } + } + } + + return 0; +} + +int +prelink_build_conflicts (struct prelink_info *info) +{ + int i, ndeps = info->ent->ndepends + 1; + struct prelink_entry *ent; + int ret = 0; + DSO *dso; + struct copy_relocs cr; + + info->dsos = alloca (sizeof (struct DSO *) * ndeps); + memset (info->dsos, 0, sizeof (struct DSO *) * ndeps); + memset (&cr, 0, sizeof (cr)); + info->dsos[0] = info->dso; + for (i = 1; i < ndeps; ++i) + { + ent = info->ent->depends[i - 1]; + if ((dso = open_dso (ent->filename)) == NULL) + goto error_out; + info->dsos[i] = dso; + /* Now check that the DSO matches what we recorded about it. */ + if (ent->timestamp != dso->info_DT_GNU_PRELINKED + || ent->checksum != dso->info_DT_CHECKSUM + || ent->base != dso->base) + { + error (0, 0, "%s: Library %s has changed since it has been prelinked", + info->dso->filename, ent->filename); + goto error_out; + } + } + + for (i = 1; i < ndeps; ++i) + { + dso = info->dsos[i]; + ent = info->ent->depends[i - 1]; + + /* Verify .gnu.liblist sections of all dependent libraries. */ + if (ent->ndepends > 0) + { + int j; + const char *name; + int nliblist; + Elf32_Lib *liblist; + Elf_Scn *scn; + Elf_Data *data; + + for (j = 1; j < dso->ehdr.e_shnum; ++j) + if (dso->shdr[j].sh_type == SHT_GNU_LIBLIST + && (name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[j].sh_name)) + && ! strcmp (name, ".gnu.liblist") + && (dso->shdr[j].sh_size % sizeof (Elf32_Lib)) == 0) + break; + + if (j == dso->ehdr.e_shnum) + { + error (0, 0, "%s: Library %s has dependencies, but doesn't contain .gnu.liblist section", + info->dso->filename, ent->filename); + goto error_out; + } + + nliblist = dso->shdr[j].sh_size / sizeof (Elf32_Lib); + scn = dso->scn[j]; + data = elf_getdata (scn, NULL); + if (data == NULL || elf_getdata (scn, data) + || data->d_buf == NULL || data->d_off + || data->d_size != dso->shdr[j].sh_size) + { + error (0, 0, "%s: Could not read .gnu.liblist section from %s", + info->dso->filename, ent->filename); + goto error_out; + } + + if (nliblist != ent->ndepends) + { + error (0, 0, "%s: Library %s has different number of libs in .gnu.liblist than expected", + info->dso->filename, ent->filename); + goto error_out; + } + liblist = (Elf32_Lib *) data->d_buf; + for (j = 0; j < nliblist; ++j) + if (liblist[j].l_time_stamp != ent->depends[j]->timestamp + || liblist[j].l_checksum != ent->depends[j]->checksum) + { + error (0, 0, "%s: .gnu.liblist in library %s is inconsistent with recorded dependencies", + info->dso->filename, ent->filename); + goto error_out; + } + + /* Extra check, maybe not needed. */ + for (j = 0; j < nliblist; ++j) + { + int k; + for (k = 0; k < info->ent->ndepends; ++k) + if (liblist[j].l_time_stamp == info->ent->depends[k]->timestamp + && liblist[j].l_checksum == info->ent->depends[k]->checksum) + break; + + if (k == info->ent->ndepends) + abort (); + } + } + + if (info->conflicts[i] || info->tls[i].modid) + { + int j, sec, first_conflict; + struct prelink_conflict *conflict; + + info->curconflicts = info->conflicts[i]; + info->curtls = info->tls[i].modid ? info->tls + i : NULL; + first_conflict = info->conflict_rela_size; + sec = addr_to_sec (dso, dso->info[DT_SYMTAB]); + /* DT_SYMTAB should be found and should point to + start of .dynsym section. */ + if (sec == -1 + || dso->info[DT_SYMTAB] != dso->shdr[sec].sh_addr) + { + error (0, 0, "Bad symtab"); + goto error_out; + } + info->symtab_start = dso->shdr[sec].sh_addr - dso->base; + info->symtab_end = info->symtab_start + dso->shdr[sec].sh_size; + for (j = 0; j < dso->ehdr.e_shnum; ++j) + { + if (! (dso->shdr[j].sh_flags & SHF_ALLOC)) + continue; + switch (dso->shdr[j].sh_type) + { + case SHT_REL: + if (prelink_conflict_rel (dso, j, info)) + goto error_out; + break; + case SHT_RELA: + if (prelink_conflict_rela (dso, j, info)) + goto error_out; + break; + } + } + + if (dso->arch->arch_prelink_conflict + && dso->arch->arch_prelink_conflict (dso, info)) + goto error_out; + + for (conflict = info->curconflicts; conflict; + conflict = conflict->next) + if (! conflict->used) + { + error (0, 0, "%s: Conflict %08llx not found in any relocation", + dso->filename, (unsigned long long) conflict->symoff); + ret = 1; + } + + /* Record library's position in search scope into R_SYM field. */ + for (j = first_conflict; j < info->conflict_rela_size; ++j) + info->conflict_rela[j].r_info + = GELF_R_INFO (i, GELF_R_TYPE (info->conflict_rela[j].r_info)); + + if (dynamic_info_is_set (dso, DT_TEXTREL) + && info->conflict_rela_size > first_conflict) + { + /* We allow prelinking against non-PIC libraries, as long as + no conflict is against read-only segment. */ + int k; + + for (j = first_conflict; j < info->conflict_rela_size; ++j) + for (k = 0; k < dso->ehdr.e_phnum; ++k) + if (dso->phdr[k].p_type == PT_LOAD + && (dso->phdr[k].p_flags & PF_W) == 0 + && dso->phdr[k].p_vaddr + <= info->conflict_rela[j].r_offset + && dso->phdr[k].p_vaddr + dso->phdr[k].p_memsz + > info->conflict_rela[j].r_offset) + { + error (0, 0, "%s: Cannot prelink against non-PIC shared library %s", + info->dso->filename, dso->filename); + goto error_out; + } + } + } + } + + dso = info->dso; + for (i = 0; i < dso->ehdr.e_shnum; ++i) + { + if (! (dso->shdr[i].sh_flags & SHF_ALLOC)) + continue; + switch (dso->shdr[i].sh_type) + { + case SHT_REL: + if (prelink_find_copy_rel (dso, i, &cr)) + goto error_out; + break; + case SHT_RELA: + if (prelink_find_copy_rela (dso, i, &cr)) + goto error_out; + break; + } + } + + if (cr.count) + { + int bss1, bss2, firstbss2 = 0; + const char *name; + + qsort (cr.rela, cr.count, sizeof (GElf_Rela), rela_cmp); + bss1 = addr_to_sec (dso, cr.rela[0].r_offset); + bss2 = addr_to_sec (dso, cr.rela[cr.count - 1].r_offset); + if (bss1 != bss2) + { + for (i = 1; i < cr.count; ++i) + if (cr.rela[i].r_offset + > dso->shdr[bss1].sh_addr + dso->shdr[bss1].sh_size) + break; + if (cr.rela[i].r_offset < dso->shdr[bss2].sh_addr) + { + error (0, 0, "%s: Copy relocs against 3 or more sections", + dso->filename); + goto error_out; + } + firstbss2 = i; + info->sdynbss_size = cr.rela[i - 1].r_offset - cr.rela[0].r_offset; + info->sdynbss_size += cr.rela[i - 1].r_addend; + info->sdynbss = calloc (info->sdynbss_size, 1); + info->sdynbss_base = cr.rela[0].r_offset; + if (info->sdynbss == NULL) + { + error (0, ENOMEM, "%s: Cannot build .sdynbss", dso->filename); + goto error_out; + } + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->shdr[bss1].sh_addr >= dso->phdr[i].p_vaddr + && dso->shdr[bss1].sh_addr + < dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + break; + if (i == dso->ehdr.e_phnum + || dso->shdr[bss2].sh_addr + dso->shdr[bss2].sh_size + > dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + { + error (0, 0, "%s: Copy relocs against more than one segment", + dso->filename); + goto error_out; + } + } + + info->dynbss_size = cr.rela[cr.count - 1].r_offset + - cr.rela[firstbss2].r_offset; + info->dynbss_size += cr.rela[cr.count - 1].r_addend; + info->dynbss = calloc (info->dynbss_size, 1); + info->dynbss_base = cr.rela[firstbss2].r_offset; + if (info->dynbss == NULL) + { + error (0, ENOMEM, "%s: Cannot build .dynbss", dso->filename); + goto error_out; + } + + /* emacs apparently has .rel.bss relocations against .data section, + crap. */ + if (dso->shdr[bss1].sh_type != SHT_NOBITS + && strcmp (name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[bss1].sh_name), + ".dynbss") != 0 + && strcmp (name, ".sdynbss") != 0) + { + error (0, 0, "%s: COPY relocations don't point into .bss or .sbss section", + dso->filename); + goto error_out; + } + if (bss1 != bss2 + && dso->shdr[bss2].sh_type != SHT_NOBITS + && strcmp (name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[bss2].sh_name), + ".dynbss") != 0 + && strcmp (name, ".sdynbss") != 0) + { + error (0, 0, "%s: COPY relocations don't point into .bss or .sbss section", + dso->filename); + goto error_out; + } + + for (i = 0; i < cr.count; ++i) + { + struct prelink_symbol *s; + DSO *ndso = NULL; + int j, reloc_class; + + reloc_class + = dso->arch->reloc_class (GELF_R_TYPE (cr.rela[i].r_info)); + + assert (reloc_class != RTYPE_CLASS_TLS); + + for (s = & info->symbols[GELF_R_SYM (cr.rela[i].r_info)]; s; + s = s->next) + if (s->reloc_class == reloc_class) + break; + + if (s == NULL || s->u.ent == NULL) + { + error (0, 0, "%s: Could not find symbol copy reloc is against", + dso->filename); + goto error_out; + } + + for (j = 1; j < ndeps; ++j) + if (info->ent->depends[j - 1] == s->u.ent) + { + ndso = info->dsos[j]; + break; + } + + assert (j < ndeps); + if (i < firstbss2) + j = get_relocated_mem (info, ndso, s->u.ent->base + s->value, + info->sdynbss + cr.rela[i].r_offset + - info->sdynbss_base, cr.rela[i].r_addend); + else + j = get_relocated_mem (info, ndso, s->u.ent->base + s->value, + info->dynbss + cr.rela[i].r_offset + - info->dynbss_base, cr.rela[i].r_addend); + + switch (j) + { + case 1: + error (0, 0, "%s: Could not find variable copy reloc is against", + dso->filename); + goto error_out; + case 2: + error (0, 0, "%s: Conflict partly overlaps with %08llx-%08llx area", + dso->filename, + (long long) cr.rela[i].r_offset, + (long long) (cr.rela[i].r_offset + cr.rela[i].r_addend)); + goto error_out; + } + } + } + + if (info->conflict_rela_size) + { + qsort (info->conflict_rela, info->conflict_rela_size, sizeof (GElf_Rela), + conflict_rela_cmp); + + /* Now make sure all conflict RELA's are against absolute 0 symbol. */ + for (i = 0; i < info->conflict_rela_size; ++i) + info->conflict_rela[i].r_info + = GELF_R_INFO (0, GELF_R_TYPE (info->conflict_rela[i].r_info)); + + if (enable_cxx_optimizations && remove_redundant_cxx_conflicts (info)) + goto error_out; + } + + for (i = 1; i < ndeps; ++i) + if (info->dsos[i]) + close_dso (info->dsos[i]); + + info->dsos = NULL; + free (cr.rela); + return ret; + +error_out: + free (cr.rela); + free (info->dynbss); + free (info->sdynbss); + info->dynbss = NULL; + info->sdynbss = NULL; + for (i = 1; i < ndeps; ++i) + if (info->dsos[i]) + close_dso (info->dsos[i]); + return 1; +} diff --git a/trunk/src/crc32.c b/trunk/src/crc32.c new file mode 100644 index 0000000..f36abb5 --- /dev/null +++ b/trunk/src/crc32.c @@ -0,0 +1,87 @@ +/* Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <stdint.h> +#include <sys/types.h> + +/* Table computed with Mark Adler's makecrc.c utility. */ +static const uint32_t crc32_table[256] = +{ + 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, + 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, + 0xe0d5e91e, 0x97d2d988, 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, + 0x90bf1d91, 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de, + 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7, 0x136c9856, + 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9, + 0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, + 0xa2677172, 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, + 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, + 0x45df5c75, 0xdcd60dcf, 0xabd13d59, 0x26d930ac, 0x51de003a, + 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423, 0xcfba9599, + 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924, + 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, + 0x01db7106, 0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, + 0x9fbfe4a5, 0xe8b8d433, 0x7807c9a2, 0x0f00f934, 0x9609a88e, + 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01, + 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e, 0x6c0695ed, + 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950, + 0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, + 0xfbd44c65, 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, + 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, + 0x346ed9fc, 0xad678846, 0xda60b8d0, 0x44042d73, 0x33031de5, + 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa, 0xbe0b1010, + 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f, + 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, + 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, + 0x03b6e20c, 0x74b1d29a, 0xead54739, 0x9dd277af, 0x04db2615, + 0x73dc1683, 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8, + 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1, 0xf00f9344, + 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb, + 0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, + 0x67dd4acc, 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, + 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, + 0xa6bc5767, 0x3fb506dd, 0x48b2364b, 0xd80d2bda, 0xaf0a1b4c, + 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55, 0x316e8eef, + 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236, + 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, + 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, + 0x2cd99e8b, 0x5bdeae1d, 0x9b64c2b0, 0xec63f226, 0x756aa39c, + 0x026d930a, 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713, + 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38, 0x92d28e9b, + 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242, + 0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, + 0x18b74777, 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, + 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45, 0xa00ae278, + 0xd70dd2ee, 0x4e048354, 0x3903b3c2, 0xa7672661, 0xd06016f7, + 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc, 0x40df0b66, + 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9, + 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, + 0xcdd70693, 0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, + 0x5d681b02, 0x2a6f2b94, 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, + 0x2d02ef8d +}; + +uint32_t crc32 (uint32_t crc, unsigned char *buf, size_t len) +{ + unsigned char *end; + + crc = ~crc; + for (end = buf + len; buf < end; ++buf) + crc = crc32_table[(crc ^ *buf) & 0xff] ^ (crc >> 8); + return ~crc; +} diff --git a/trunk/src/cxx.c b/trunk/src/cxx.c new file mode 100644 index 0000000..b3530f0 --- /dev/null +++ b/trunk/src/cxx.c @@ -0,0 +1,377 @@ +/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include "prelink.h" + +struct find_cxx_sym +{ + DSO *dso; + int n; + struct prelink_entry *ent; + Elf_Data *symtab, *strtab; + int symsec, strsec; + GElf_Sym sym; +}; + +static int +find_cxx_sym (struct prelink_info *info, GElf_Addr addr, + struct find_cxx_sym *fcs, int reloc_size) +{ + int n, ndeps = info->ent->ndepends + 1; + int ndx, maxndx; + DSO *dso = NULL; + Elf_Scn *scn; + + if (fcs->dso == NULL + || addr < fcs->dso->base + || addr >= fcs->dso->end) + { + for (n = 1; n < ndeps; ++n) + { + dso = info->dsos[n]; + if (addr >= dso->base + && addr < dso->end) + break; + } + + if (n == ndeps + && addr >= info->dso->base + && addr < info->dso->end) + { + n = 0; + dso = info->dso; + } + + assert (n < ndeps); + fcs->n = n; + fcs->ent = n ? info->ent->depends[n - 1] : info->ent; + fcs->dso = dso; + fcs->symsec = addr_to_sec (dso, dso->info[DT_SYMTAB]); + if (fcs->symsec == -1) + { + fcs->ent = NULL; + return -1; + } + scn = dso->scn[fcs->symsec]; + fcs->symtab = elf_getdata (scn, NULL); + assert (elf_getdata (scn, fcs->symtab) == NULL); + fcs->strsec = addr_to_sec (dso, dso->info[DT_STRTAB]); + if (fcs->strsec == -1) + { + fcs->ent = NULL; + return -1; + } + scn = dso->scn[fcs->strsec]; + fcs->strtab = elf_getdata (scn, NULL); + assert (elf_getdata (scn, fcs->strtab) == NULL); + } + else + dso = fcs->dso; + + maxndx = fcs->symtab->d_size / dso->shdr[fcs->symsec].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, fcs->symtab, ndx, &fcs->sym); + if (fcs->sym.st_value <= addr + && fcs->sym.st_value + fcs->sym.st_size >= addr + reloc_size) + break; + } + + if (ndx == maxndx) + return -1; + + return ndx; +} + +/* The idea here is that C++ virtual tables are always emitted + in .gnu.linkonce.d.* sections as WEAK symbols and they + need to be the same. + We check if they are and if yes, remove conflicts against + virtual tables which will not be used. */ + +int +remove_redundant_cxx_conflicts (struct prelink_info *info) +{ + int i, j, k, n, o, state, removed = 0; + int ndx, maxndx, sec; + int reloc_type, reloc_size; + struct find_cxx_sym fcs1, fcs2; + char *mem1, *mem2; + const char *name = NULL, *secname = NULL; + GElf_Addr symtab_start; + GElf_Word symoff; + Elf_Data *binsymtab = NULL; + int binsymtabsec; + struct prelink_conflict *conflict; + static struct + { + unsigned char *prefix; + unsigned char prefix_len, st_info, check_pltref; + unsigned char *section; + } + specials[] = + { + /* G++ 3.0 ABI. */ + /* Virtual table. */ + { "_ZTV", 4, GELF_ST_INFO (STB_WEAK, STT_OBJECT), 1, ".data" }, + /* Typeinfo. */ + { "_ZTI", 4, GELF_ST_INFO (STB_WEAK, STT_OBJECT), 0, ".data" }, + /* G++ 2.96-RH ABI. */ + /* Virtual table. */ + { "__vt_", 5, GELF_ST_INFO (STB_WEAK, STT_OBJECT), 0, ".data" }, + { NULL, 0, 0, 0, NULL } + }; + + /* Don't bother doing this for non-C++ programs. */ + for (i = 0; i < info->ent->ndepends; ++i) + if (strstr (info->ent->depends[i]->canon_filename, "libstdc++")) + break; + if (i == info->ent->ndepends) + return 0; + + binsymtabsec = addr_to_sec (info->dso, info->dso->info[DT_SYMTAB]); + if (binsymtabsec != -1) + { + Elf_Scn *scn = info->dso->scn[binsymtabsec]; + + binsymtab = elf_getdata (scn, NULL); + assert (elf_getdata (scn, binsymtab) == NULL); + } + + state = 0; + memset (&fcs1, 0, sizeof (fcs1)); + memset (&fcs2, 0, sizeof (fcs2)); + for (i = 0; i < info->conflict_rela_size; ++i) + { + reloc_type = GELF_R_TYPE (info->conflict_rela[i].r_info); + reloc_size = info->dso->arch->reloc_size (reloc_type); + + if (GELF_R_SYM (info->conflict_rela[i].r_info) != 0) + continue; + + if (state + && fcs1.sym.st_value <= info->conflict_rela[i].r_offset + && fcs1.sym.st_value + fcs1.sym.st_size + >= info->conflict_rela[i].r_offset + reloc_size) + { + if (state == 3) + goto remove_noref; + if (state == 2) + goto check_pltref; + continue; + } + + n = find_cxx_sym (info, info->conflict_rela[i].r_offset, + &fcs1, reloc_size); + + name = (const char *) fcs1.strtab->d_buf + fcs1.sym.st_name; + state = 0; + if (n == -1) + continue; + state = 1; + sec = addr_to_sec (fcs1.dso, fcs1.sym.st_value); + if (sec == -1) + continue; + secname = strptr (fcs1.dso, fcs1.dso->ehdr.e_shstrndx, + fcs1.dso->shdr[sec].sh_name); + if (secname == NULL) + continue; + + for (k = 0; specials[k].prefix; ++k) + if (ELF32_ST_VISIBILITY (fcs1.sym.st_other) == STV_DEFAULT + && fcs1.sym.st_info == specials[k].st_info + && strncmp (name, specials[k].prefix, specials[k].prefix_len) == 0 + && strcmp (secname, specials[k].section) == 0) + break; + + if (specials[k].prefix == NULL) + continue; + + /* Now check there are no other symbols pointing to it. */ + maxndx = fcs1.symtab->d_size / fcs1.dso->shdr[fcs1.symsec].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + if (ndx != n) + { + GElf_Sym sym; + + gelfx_getsym (fcs1.dso->elf, fcs1.symtab, ndx, &sym); + if ((sym.st_value + sym.st_size > fcs1.sym.st_value + && sym.st_value < fcs1.sym.st_value + fcs1.sym.st_size) + || sym.st_value == fcs1.sym.st_value) + break; + } + + if (ndx < maxndx) + continue; + + if (specials[k].check_pltref) + state = 2; + + symtab_start = fcs1.dso->shdr[fcs1.symsec].sh_addr - fcs1.dso->base; + symoff = symtab_start + n * fcs1.dso->shdr[fcs1.symsec].sh_entsize; + + for (conflict = info->conflicts[fcs1.n]; conflict; + conflict = conflict->next) + if (conflict->symoff == symoff + && conflict->reloc_class == RTYPE_CLASS_VALID) + break; + + if (conflict == NULL) + goto check_pltref; + + if (conflict->conflict.ent != fcs1.ent + || fcs1.dso->base + conflict->conflictval != fcs1.sym.st_value) + goto check_pltref; + + if (verbose > 4) + error (0, 0, "Possible C++ conflict removal from unreferenced table at %s:%s+%d", + fcs1.dso->filename, name, + (int) (info->conflict_rela[i].r_offset - fcs1.sym.st_value)); + + /* Limit size slightly. */ + if (fcs1.sym.st_size > 16384) + goto check_pltref; + + o = find_cxx_sym (info, conflict->lookup.ent->base + conflict->lookupval, + &fcs2, fcs1.sym.st_size); + + if (o == -1 + || fcs1.sym.st_size != fcs2.sym.st_size + || fcs1.sym.st_info != fcs2.sym.st_info + || ELF32_ST_VISIBILITY (fcs2.sym.st_other) != STV_DEFAULT + || strcmp (name, (char *) fcs2.strtab->d_buf + fcs2.sym.st_name) != 0) + goto check_pltref; + + mem1 = malloc (fcs1.sym.st_size * 2); + if (mem1 == NULL) + { + error (0, ENOMEM, "%s: Could not compare %s arrays", + info->dso->filename, name); + return 1; + } + + mem2 = mem1 + fcs1.sym.st_size; + + if (get_relocated_mem (info, fcs1.dso, fcs1.sym.st_value, mem1, + fcs1.sym.st_size) + || get_relocated_mem (info, fcs2.dso, fcs2.sym.st_value, mem2, + fcs1.sym.st_size) + || memcmp (mem1, mem2, fcs1.sym.st_size) != 0) + { + free (mem1); + goto check_pltref; + } + + free (mem1); + + state = 3; + +remove_noref: + if (verbose > 3) + error (0, 0, "Removing C++ conflict from unreferenced table at %s:%s+%d", + fcs1.dso->filename, name, + (int) (info->conflict_rela[i].r_offset - fcs1.sym.st_value)); + + info->conflict_rela[i].r_info = + GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info)); + ++removed; + continue; + +check_pltref: + /* If the binary calls directly (or takes its address) one of the + methods in a virtual table, but doesn't define it, there is no + need to leave conflicts in the virtual table which will only + slow down the code (as it has to hop through binary's .plt + back to the method). */ + if (state != 2 + || info->conflict_rela[i].r_addend < info->dso->base + || info->conflict_rela[i].r_addend >= info->dso->end + || binsymtab == NULL) + continue; + + maxndx = binsymtab->d_size / info->dso->shdr[binsymtabsec].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + GElf_Sym sym; + + gelfx_getsym (info->dso->elf, binsymtab, ndx, &sym); + if (sym.st_value == info->conflict_rela[i].r_addend) + { + if (sym.st_shndx == SHN_UNDEF && sym.st_value) + { + struct prelink_symbol *s; + + if (verbose > 4) + error (0, 0, "Possible C++ conflict removal due to reference to binary's .plt at %s:%s+%d", + fcs1.dso->filename, name, + (int) (info->conflict_rela[i].r_offset + - fcs1.sym.st_value)); + + for (s = &info->symbols[ndx]; s; s = s->next) + if (s->reloc_class == RTYPE_CLASS_PLT) + { + for (conflict = info->conflicts[fcs1.n]; conflict; + conflict = conflict->next) + if (conflict->lookup.ent->base + conflict->lookupval + == info->conflict_rela[i].r_addend + && conflict->conflict.ent + && (conflict->conflict.ent->base + + conflict->conflictval + == s->u.ent->base + s->value) + && conflict->reloc_class == RTYPE_CLASS_VALID) + { + if (verbose > 3) + error (0, 0, "Removing C++ conflict due to reference to binary's .plt at %s:%s+%d", + fcs1.dso->filename, name, + (int) (info->conflict_rela[i].r_offset + - fcs1.sym.st_value)); + + info->conflict_rela[i].r_info = + GELF_R_INFO (1, GELF_R_TYPE (info->conflict_rela[i].r_info)); + ++removed; + } + break; + } + } + break; + } + } + } + + if (removed) + { + for (i = 0, j = 0; i < info->conflict_rela_size; ++i) + if (GELF_R_SYM (info->conflict_rela[i].r_info) == 0) + { + if (i != j) + info->conflict_rela[j] = info->conflict_rela[i]; + ++j; + } + info->conflict_rela_size = j; + } + + return 0; +} diff --git a/trunk/src/data.c b/trunk/src/data.c new file mode 100644 index 0000000..13380da --- /dev/null +++ b/trunk/src/data.c @@ -0,0 +1,339 @@ +/* Copyright (C) 2001, 2002 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include "prelink.h" + +#define UREAD(le,nn) \ +uint##nn##_t \ +read_u##le##nn (DSO *dso, GElf_Addr addr) \ +{ \ + Elf_Type type; \ + unsigned char *data = get_data (dso, addr, NULL, &type); \ + \ + if (data == NULL) \ + return 0; \ + \ + if (type == ELF_T_BYTE) \ + return buf_read_u##le##nn (data); \ + else \ + return *(uint##nn##_t *)data; \ +} + +#define WRITE(le,nn) \ +int \ +write_##le##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val) \ +{ \ + int sec; \ + Elf_Type type; \ + unsigned char *data = get_data (dso, addr, &sec, &type); \ + \ + if (data == NULL) \ + return -1; \ + \ + if (type == ELF_T_BYTE) \ + buf_write_##le##nn (data, val); \ + else \ + *(uint##nn##_t *)data = val; \ + elf_flagscn (dso->scn[sec], ELF_C_SET, ELF_F_DIRTY); \ + return 0; \ +} + +#define BUFREADUNE(nn) \ +uint##nn##_t \ +buf_read_une##nn (DSO *dso, unsigned char *buf) \ +{ \ + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \ + return buf_read_ule32 (buf); \ + else \ + return buf_read_ube32 (buf); \ +} + +#define READUNE(nn) \ +uint##nn##_t \ +read_une##nn (DSO *dso, GElf_Addr addr) \ +{ \ + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \ + return read_ule##nn (dso, addr); \ + else \ + return read_ube##nn (dso, addr); \ +} + +#define WRITENE(nn) \ +void \ +write_ne##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val) \ +{ \ + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \ + write_le##nn (dso, addr, val); \ + else \ + write_be##nn (dso, addr, val); \ +} + +#define BUFWRITENE(nn) \ +void \ +buf_write_ne##nn (DSO *dso, unsigned char *buf, \ + uint##nn##_t val) \ +{ \ + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) \ + buf_write_le##nn (buf, val); \ + else \ + buf_write_be##nn (buf, val); \ +} + +#define READWRITE(le,nn) UREAD(le,nn) WRITE(le,nn) +#define READWRITESIZE(nn) \ + READWRITE(le,nn) READWRITE(be,nn) \ + BUFREADUNE(nn) READUNE(nn) \ + WRITENE(nn) BUFWRITENE(nn) + +unsigned char * +get_data (DSO *dso, GElf_Addr addr, int *secp, Elf_Type *typep) +{ + int sec = addr_to_sec (dso, addr); + Elf_Data *data = NULL; + + if (sec == -1) + return NULL; + + if (secp) + *secp = sec; + + addr -= dso->shdr[sec].sh_addr; + while ((data = elf_getdata (dso->scn[sec], data)) != NULL) + if (data->d_off <= addr && data->d_off + data->d_size > addr) + { + if (typep) *typep = data->d_type; + return (unsigned char *) data->d_buf + (addr - data->d_off); + } + return NULL; +} + +/* Initialize IT so that the first byte it provides is address ADDR + of DSO. */ + +void +init_data_iterator (struct data_iterator *it, DSO *dso, GElf_Addr addr) +{ + it->dso = dso; + it->data = NULL; + it->addr = addr; +} + +/* Return a pointer to the next SIZE bytes pointed to by IT, and move + IT to the end of the returned block. Return null if the data could + not be read for some reason. */ + +unsigned char * +get_data_from_iterator (struct data_iterator *it, GElf_Addr size) +{ + unsigned char *ptr; + + /* If we're at the end of a data block, move onto the next. */ + if (it->data && it->data->d_off + it->data->d_size == it->sec_offset) + it->data = elf_getdata (it->dso->scn[it->sec], it->data); + + if (it->data == NULL) + { + /* Find out which section contains the next byte. */ + it->sec = addr_to_sec (it->dso, it->addr); + if (it->sec < 0) + return NULL; + + /* Fast-forward to the block that contains ADDR, if any. */ + it->sec_offset = it->addr - it->dso->shdr[it->sec].sh_addr; + do + it->data = elf_getdata (it->dso->scn[it->sec], it->data); + while (it->data && it->data->d_off + it->data->d_size <= it->sec_offset); + } + + /* Make sure that all the data we want is included in this block. */ + if (it->data == NULL + || it->data->d_off > it->sec_offset + || it->data->d_off + it->data->d_size < it->sec_offset + size) + return NULL; + + ptr = (unsigned char *) it->data->d_buf + (it->sec_offset - it->data->d_off); + it->sec_offset += size; + it->addr += size; + return ptr; +} + +/* Read the symbol pointed to by IT into SYM and move IT onto the + next symbol. Return true on success. */ + +int +get_sym_from_iterator (struct data_iterator *it, GElf_Sym *sym) +{ + GElf_Addr offset, size; + unsigned char *ptr; + + size = gelf_fsize (it->dso->elf, ELF_T_SYM, 1, EV_CURRENT); + ptr = get_data_from_iterator (it, size); + if (ptr != NULL) + { + offset = ptr - (unsigned char *) it->data->d_buf; + if (offset % size == 0) + { + gelfx_getsym (it->dso->elf, it->data, offset / size, sym); + return 1; + } + } + return 0; +} + +inline uint8_t +buf_read_u8 (unsigned char *data) +{ + return *data; +} + +inline uint16_t +buf_read_ule16 (unsigned char *data) +{ + return data[0] | (data[1] << 8); +} + +inline uint16_t +buf_read_ube16 (unsigned char *data) +{ + return data[1] | (data[0] << 8); +} + +inline uint32_t +buf_read_ule32 (unsigned char *data) +{ + return data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); +} + +inline uint32_t +buf_read_ube32 (unsigned char *data) +{ + return data[3] | (data[2] << 8) | (data[1] << 16) | (data[0] << 24); +} + +inline uint64_t +buf_read_ule64 (unsigned char *data) +{ + return (data[0] | (data[1] << 8) | (data[2] << 16)) + | (((uint64_t)data[3]) << 24) + | (((uint64_t)data[4]) << 32) + | (((uint64_t)data[5]) << 40) + | (((uint64_t)data[6]) << 48) + | (((uint64_t)data[7]) << 56); +} + +inline uint64_t +buf_read_ube64 (unsigned char *data) +{ + return (data[7] | (data[6] << 8) | (data[5] << 16)) + | (((uint64_t)data[4]) << 24) + | (((uint64_t)data[3]) << 32) + | (((uint64_t)data[2]) << 40) + | (((uint64_t)data[1]) << 48) + | (((uint64_t)data[0]) << 56); +} + +inline void +buf_write_8 (unsigned char *data, uint8_t val) +{ + *data = val; +} + +inline void +buf_write_le16 (unsigned char *data, uint16_t val) +{ + data[0] = val; + data[1] = val >> 8; +} + +inline void +buf_write_be16 (unsigned char *data, uint16_t val) +{ + data[1] = val; + data[0] = val >> 8; +} + +inline void +buf_write_le32 (unsigned char *data, uint32_t val) +{ + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; +} + +inline void +buf_write_be32 (unsigned char *data, uint32_t val) +{ + data[3] = val; + data[2] = val >> 8; + data[1] = val >> 16; + data[0] = val >> 24; +} + +inline void +buf_write_le64 (unsigned char *data, uint64_t val) +{ + data[0] = val; + data[1] = val >> 8; + data[2] = val >> 16; + data[3] = val >> 24; + data[4] = val >> 32; + data[5] = val >> 40; + data[6] = val >> 48; + data[7] = val >> 56; +} + +inline void +buf_write_be64 (unsigned char *data, uint64_t val) +{ + data[7] = val; + data[6] = val >> 8; + data[5] = val >> 16; + data[4] = val >> 24; + data[3] = val >> 32; + data[2] = val >> 40; + data[1] = val >> 48; + data[0] = val >> 56; +} + +READWRITE(,8) +READWRITESIZE(16) +READWRITESIZE(32) +READWRITESIZE(64) + +const char * +strptr (DSO *dso, int sec, off_t offset) +{ + Elf_Scn *scn; + Elf_Data *data; + + scn = dso->scn[sec]; + if (offset >= 0 && offset < dso->shdr[sec].sh_size) + { + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + if (data->d_buf + && offset >= data->d_off + && offset < data->d_off + data->d_size) + return (const char *) data->d_buf + (offset - data->d_off); + } + } + + return NULL; +} diff --git a/trunk/src/doit.c b/trunk/src/doit.c new file mode 100644 index 0000000..2208ece --- /dev/null +++ b/trunk/src/doit.c @@ -0,0 +1,270 @@ +/* Copyright (C) 2001, 2003, 2004, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <alloca.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include "prelinktab.h" + +struct collect_ents + { + struct prelink_entry **ents; + int nents; + }; + +static int +find_ents (void **p, void *info) +{ + struct collect_ents *l = (struct collect_ents *) info; + struct prelink_entry *e = * (struct prelink_entry **) p; + + if ((e->type == ET_DYN && e->done == 1) + || (e->type == ET_EXEC && e->done == 0 && ! libs_only)) + l->ents[l->nents++] = e; + + return 1; +} + +static void +clear_ent_marks (struct prelink_entry *ent) +{ + int i; + + ent->u.tmp = 0; + for (i = 0; i < ent->ndepends; ++i) + clear_ent_marks (ent->depends[i]); +} + +static struct prelink_entry * +find_unlisted_dependency (struct prelink_entry *ent) +{ + int i; + struct prelink_entry *ret; + + if (ent->u.tmp == 0) + return ent; + for (i = 0; i < ent->ndepends; ++i) + if ((ret = find_unlisted_dependency (ent->depends[i])) != NULL) + return ret; + return NULL; +} + +static void +prelink_ent (struct prelink_entry *ent) +{ + int i; + DSO *dso; + struct stat64 st; + struct prelink_link *hardlink; + char *move = NULL; + size_t movelen = 0; + struct prelink_entry *dep; + + for (i = 0; i < ent->ndepends; ++i) + if (ent->depends[i]->done == 1) + prelink_ent (ent->depends[i]); + + for (i = 0; i < ent->ndepends; ++i) + if (ent->depends[i]->done != 2) + { + ent->done = 0; + if (! undo) + ent->type = ET_UNPRELINKABLE; + if (verbose) + error (0, 0, "Could not prelink %s because its dependency %s could not be prelinked", + ent->filename, ent->depends[i]->filename); + return; + } + else + clear_ent_marks (ent->depends[i]); + + ent->u.tmp = 1; + for (i = 0; i < ent->ndepends; ++i) + ent->depends[i]->u.tmp = 1; + + if ((dep = find_unlisted_dependency (ent)) != NULL) + { + ent->done = 0; + if (! undo) + ent->type = ET_UNPRELINKABLE; + if (verbose) + error (0, 0, "Could not prelink %s because it doesn't use %s, but one of its dependencies has been prelinked against it", + ent->filename, dep->filename); + return; + } + + if (verbose) + { + if (dry_run) + printf ("Would prelink %s\n", ent->canon_filename); + else + printf ("Prelinking %s\n", ent->canon_filename); + } + + dso = open_dso (ent->canon_filename); + if (dso == NULL) + goto error_out; + + if (fstat64 (dso->fd, &st) < 0) + { + error (0, errno, "%s changed during prelinking", ent->filename); + goto error_out; + } + + if (st.st_dev != ent->dev || st.st_ino != ent->ino) + { + error (0, 0, "%s changed during prelinking", ent->filename); + goto error_out; + } + + if (dry_run) + close_dso (dso); + else + { + if (prelink_prepare (dso)) + goto make_unprelinkable; + if (ent->type == ET_DYN && relocate_dso (dso, ent->base)) + goto make_unprelinkable; + if (prelink (dso, ent)) + goto make_unprelinkable; + if (update_dso (dso, NULL)) + { + dso = NULL; + goto error_out; + } + } + ent->done = 2; + ent->flags |= PCF_PRELINKED; + + /* Redo hardlinks. */ + for (hardlink = ent->hardlink; hardlink; hardlink = hardlink->next) + { + size_t len; + + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) + { + error (0, 0, "Could not stat %s (former hardlink to %s)", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (st.st_dev != ent->dev || st.st_ino != ent->ino) + { + error (0, 0, "%s is no longer hardlink to %s", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (verbose) + { + if (dry_run) + printf ("Would link %s to %s\n", hardlink->canon_filename, + ent->canon_filename); + else + printf ("Linking %s to %s\n", hardlink->canon_filename, + ent->canon_filename); + } + + if (dry_run) + continue; + + len = strlen (hardlink->canon_filename); + if (len + sizeof (".#prelink#") > movelen) + { + movelen = len + sizeof (".#prelink#"); + move = realloc (move, movelen); + if (move == NULL) + { + error (0, ENOMEM, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + movelen = 0; + continue; + } + } + + memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", + sizeof (".#prelink#")); + if (wrap_rename (hardlink->canon_filename, move) < 0) + { + error (0, errno, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) + { + error (0, errno, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + + if (wrap_rename (move, hardlink->canon_filename) < 0) + { + error (0, errno, "Could not rename %s back to %s", + move, hardlink->canon_filename); + } + continue; + } + + if (wrap_unlink (move) < 0) + { + error (0, errno, "Could not unlink %s", move); + continue; + } + } + free (move); + + if (! dry_run && wrap_stat64 (ent->canon_filename, &st) >= 0) + { + ent->dev = st.st_dev; + ent->ino = st.st_ino; + ent->ctime = st.st_ctime; + ent->mtime = st.st_mtime; + } + return; + +make_unprelinkable: + if (! undo) + ent->type = ET_UNPRELINKABLE; +error_out: + ent->done = 0; + if (dso) + close_dso (dso); + return; +} + +void +prelink_all (void) +{ + struct collect_ents l; + int i; + + l.ents = + (struct prelink_entry **) alloca (prelink_entry_count + * sizeof (struct prelink_entry *)); + l.nents = 0; + htab_traverse (prelink_filename_htab, find_ents, &l); + + for (i = 0; i < l.nents; ++i) + if (l.ents[i]->done == 1 + || (l.ents[i]->done == 0 && l.ents[i]->type == ET_EXEC)) + prelink_ent (l.ents[i]); +} diff --git a/trunk/src/dso-readonly.c b/trunk/src/dso-readonly.c new file mode 100644 index 0000000..8ad5865 --- /dev/null +++ b/trunk/src/dso-readonly.c @@ -0,0 +1,1823 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#if defined HAVE_LIBSELINUX && defined HAVE_SELINUX_SELINUX_H +#include <selinux/selinux.h> +#define USE_SELINUX +#endif + +#define RELOCATE_SCN(shf) \ + ((shf) & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + +#ifndef ELF_F_PERMISSIVE +# define ELF_F_PERMISSIVE 0 +#endif + +void +read_dynamic (DSO *dso) +{ + int i; + + memset (dso->info, 0, sizeof(dso->info)); + dso->info_set_mask = 0; + for (i = 0; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_DYNAMIC) + { + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[i]; + GElf_Dyn dyn; + + dso->dynamic = i; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if ((GElf_Xword) dyn.d_tag < DT_NUM) + { + dso->info[dyn.d_tag] = dyn.d_un.d_val; + if (dyn.d_tag < 50) + dso->info_set_mask |= (1ULL << dyn.d_tag); + } + else if (dyn.d_tag == DT_CHECKSUM) + { + dso->info_DT_CHECKSUM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_CHECKSUM_BIT); + } + else if (dyn.d_tag == DT_GNU_PRELINKED) + { + dso->info_DT_GNU_PRELINKED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_PRELINKED_BIT); + } + else if (dyn.d_tag == DT_VERDEF) + { + dso->info_DT_VERDEF = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERDEF_BIT); + } + else if (dyn.d_tag == DT_VERNEED) + { + dso->info_DT_VERNEED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERNEED_BIT); + } + else if (dyn.d_tag == DT_VERSYM) + { + dso->info_DT_VERSYM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERSYM_BIT); + } + else if (dyn.d_tag == DT_FILTER) + dso->info_set_mask |= (1ULL << DT_FILTER_BIT); + else if (dyn.d_tag == DT_AUXILIARY) + dso->info_set_mask |= (1ULL << DT_AUXILIARY_BIT); + else if (dyn.d_tag == DT_LOPROC) + dso->info_set_mask |= (1ULL << DT_LOPROC_BIT); + else if (dyn.d_tag == DT_GNU_HASH) + { + dso->info_DT_GNU_HASH = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_HASH_BIT); + } + if (dso->ehdr.e_machine == EM_MIPS) + { + if (dyn.d_tag == DT_MIPS_LOCAL_GOTNO) + dso->info_DT_MIPS_LOCAL_GOTNO = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_GOTSYM) + dso->info_DT_MIPS_GOTSYM = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_SYMTABNO) + dso->info_DT_MIPS_SYMTABNO = dyn.d_un.d_val; + } + } + if (ndx < maxndx) + break; + } + } +} + +int +set_dynamic (DSO *dso, GElf_Word tag, GElf_Addr value, int fatal) +{ + Elf_Data *data; + Elf_Scn *scn; + GElf_Dyn dyn; + int ndx, maxndx; + uint64_t mask = dso->info_set_mask; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + + scn = dso->scn[dso->dynamic]; + + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + + switch (tag) + { + case DT_CHECKSUM: + mask |= (1ULL << DT_CHECKSUM_BIT); break; + case DT_GNU_PRELINKED: + mask |= (1ULL << DT_GNU_PRELINKED_BIT); break; + case DT_VERDEF: + mask |= (1ULL << DT_VERDEF_BIT); break; + case DT_VERNEED: + mask |= (1ULL << DT_VERNEED_BIT); break; + case DT_VERSYM: + mask |= (1ULL << DT_VERSYM_BIT); break; + default: + if (tag < DT_NUM && tag < 50) + mask |= (1ULL << tag); + break; + } + + maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if (dyn.d_tag == tag) + { + if (dyn.d_un.d_ptr != value) + { + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + } + + return 0; + } + } + assert (ndx < maxndx); + + if (ndx + 1 < maxndx) + { + /* DT_NULL is not the last dynamic entry. */ + gelfx_update_dyn (dso->elf, data, ndx + 1, &dyn); + dyn.d_tag = tag; + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + dso->info_set_mask = mask; + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; + } + + if (fatal) + error (0, 0, "%s: Not enough room to add .dynamic entry", + dso->filename); + return 1; +} + +int +check_dso (DSO *dso) +{ + int i, last = 1; + + /* FIXME: Several routines in prelink and in libelf-0.7.0 too + rely on sh_offset's monotonically increasing. */ + for (i = 2; i < dso->ehdr.e_shnum; ++i) + { + if (dso->shdr[last].sh_offset + + (dso->shdr[last].sh_type == SHT_NOBITS + ? 0 : dso->shdr[last].sh_size) > dso->shdr[i].sh_offset) + { + if (!dso->permissive + || RELOCATE_SCN (dso->shdr[last].sh_flags) + || RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + error (0, 0, "%s: section file offsets not monotonically increasing", + dso->filename); + return 1; + } + } + if (!dso->permissive + || (dso->shdr[i].sh_type != SHT_NOBITS && dso->shdr[i].sh_size != 0)) + last = i; + } + return 0; +} + +DSO * +open_dso (const char *name) +{ + int fd; + + fd = wrap_open (name, O_RDONLY); + if (fd == -1) + { + error (0, errno, "cannot open \"%s\"", name); + return NULL; + } + return fdopen_dso (fd, name); +} + +/* WARNING: If prelink is ever multi-threaded, this will not work + Other alternatives are: + 1) make section_cmp nested function - trampolines + vs. non-exec stack needs to be resolved for it though + 2) make the variable __thread + 3) use locking around the qsort + */ +static DSO *section_cmp_dso; + +static int +section_cmp (const void *A, const void *B) +{ + int *a = (int *) A; + int *b = (int *) B; + DSO *dso = section_cmp_dso; + + if (dso->shdr[*a].sh_offset < dso->shdr[*b].sh_offset) + return -1; + if (dso->shdr[*a].sh_offset > dso->shdr[*b].sh_offset) + return 1; + if (*a < *b) + return -1; + return *a > *b; +} + +DSO * +fdopen_dso (int fd, const char *name) +{ + Elf *elf = NULL; + GElf_Ehdr ehdr; + GElf_Addr last_off; + int i, j, k, last, *sections, *invsections; + DSO *dso = NULL; +#if 0 + struct PLArch *plarch; + extern struct PLArch __start_pl_arch[], __stop_pl_arch[]; +#endif + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s (dso_readonly)", elf_errmsg (-1)); + goto error_out; + } + + if (elf_kind (elf) != ELF_K_ELF) + { + error (0, 0, "\"%s\" is not an ELF file", name); + goto error_out; + } + + if (gelf_getehdr (elf, &ehdr) == NULL) + { + error (0, 0, "cannot get the ELF header: %s", + elf_errmsg (-1)); + goto error_out; + } + + if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC) + { + error (0, 0, "\"%s\" is not a shared library", name); + goto error_out; + } + + if (ehdr.e_shnum == 0) + { + GElf_Phdr phdr; + + /* Check for UPX compressed executables. */ + if (ehdr.e_type == ET_EXEC + && ehdr.e_phnum > 0 + && (gelf_getphdr (elf, 0, &phdr), phdr.p_type == PT_LOAD) + && phdr.p_filesz >= 256 + && phdr.p_filesz <= 4096 + && phdr.p_offset == 0 + && ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize < phdr.p_filesz) + { + char *buf = alloca (phdr.p_filesz); + size_t start = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; + + if (pread (fd, buf, phdr.p_filesz, 0) == phdr.p_filesz + && memmem (buf + start, phdr.p_filesz - start, + "UPX!", 4) != NULL) + { + error (0, 0, "\"%s\" is UPX compressed executable", name); + goto error_out; + } + } + error (0, 0, "\"%s\" has no section headers", name); + goto error_out; + } + + /* Allocate DSO structure. Leave place for additional 20 new section + headers. */ + dso = (DSO *) + malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr) + + (ehdr.e_phnum + 1) * sizeof(GElf_Phdr) + + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *)); + if (!dso) + { + error (0, ENOMEM, "Could not open DSO"); + goto error_out; + } + + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + + memset (dso, 0, sizeof(DSO)); + dso->elf = elf; + dso->ehdr = ehdr; + dso->phdr = (GElf_Phdr *) &dso->shdr[ehdr.e_shnum + 20]; + dso->scn = (Elf_Scn **) &dso->phdr[ehdr.e_phnum + 1]; + switch (ehdr.e_ident[EI_CLASS]) + { + case ELFCLASS32: + dso->mask = 0xffffffff; break; + case ELFCLASS64: + dso->mask = 0xffffffffffffffffULL; break; + } + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_getphdr (elf, i, dso->phdr + i); + dso->fd = fd; + + for (i = 0, j = 0; i < ehdr.e_shnum; ++i) + { + dso->scn[i] = elf_getscn (elf, i); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + if ((dso->shdr[i].sh_flags & SHF_ALLOC) && dso->shdr[i].sh_type != SHT_NOBITS) + j = 1; + } + if (j == 0) + { + /* If all ALLOC sections are SHT_NOBITS, then this is a + stripped-to-file debuginfo. Skip it silently. */ + goto error_out; + } + + sections = (int *) alloca (dso->ehdr.e_shnum * sizeof (int) * 2); + sections[0] = 0; + for (i = 1, j = 1, k = dso->ehdr.e_shnum, last = -1; + i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + last = i; + sections[j++] = i; + } + else + sections[--k] = i; + assert (j == k); + + section_cmp_dso = dso; + qsort (sections + k, dso->ehdr.e_shnum - k, sizeof (*sections), section_cmp); + invsections = sections + dso->ehdr.e_shnum; + invsections[0] = 0; + for (i = 1, j = 0; i < ehdr.e_shnum; ++i) + { + if (i != sections[i]) + { + j = 1; + dso->scn[i] = elf_getscn (elf, sections[i]); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + } + invsections[sections[i]] = i; + } + +#if 0 + if (j) + { + dso->move = init_section_move (dso); + if (dso->move == NULL) + goto error_out; + memcpy (dso->move->old_to_new, invsections, dso->ehdr.e_shnum * sizeof (int)); + memcpy (dso->move->new_to_old, sections, dso->ehdr.e_shnum * sizeof (int)); + } +#endif + + last_off = 0; + for (i = 1; i < ehdr.e_shnum; ++i) + { + if (dso->shdr[i].sh_link >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", name, + dso->shdr[i].sh_link); + goto error_out; + } + dso->shdr[i].sh_link = invsections[dso->shdr[i].sh_link]; + if (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK)) + { + if (dso->shdr[i].sh_info >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", name, + dso->shdr[i].sh_info); + goto error_out; + } + dso->shdr[i].sh_info = invsections[dso->shdr[i].sh_info]; + } + + /* Some linkers mess up sh_offset fields for empty or nobits + sections. */ + if (RELOCATE_SCN (dso->shdr[i].sh_flags) + && (dso->shdr[i].sh_size == 0 + || dso->shdr[i].sh_type == SHT_NOBITS)) + { + for (j = i + 1; j < ehdr.e_shnum; ++j) + if (! RELOCATE_SCN (dso->shdr[j].sh_flags)) + break; + else if (dso->shdr[j].sh_size != 0 + && dso->shdr[j].sh_type != SHT_NOBITS) + break; + dso->shdr[i].sh_offset = (last_off + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + if (j < ehdr.e_shnum + && dso->shdr[i].sh_offset > dso->shdr[j].sh_offset) + { + GElf_Addr k; + + for (k = dso->shdr[i].sh_addralign - 1; k; ) + { + k >>= 1; + dso->shdr[i].sh_offset = (last_off + k) & ~k; + if (dso->shdr[i].sh_offset <= dso->shdr[j].sh_offset) + break; + } + } + last_off = dso->shdr[i].sh_offset; + } + else + last_off = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + dso->ehdr.e_shstrndx = invsections[dso->ehdr.e_shstrndx]; + +#if 0 + for (plarch = __start_pl_arch; plarch < __stop_pl_arch; plarch++) + if (plarch->class == ehdr.e_ident[EI_CLASS] + && (plarch->machine == ehdr.e_machine + || plarch->alternate_machine[0] == ehdr.e_machine + || plarch->alternate_machine[1] == ehdr.e_machine + || plarch->alternate_machine[2] == ehdr.e_machine)) + break; + + if (plarch == __stop_pl_arch || ehdr.e_machine == EM_NONE) + { + error (0, 0, "\"%s\"'s architecture is not supported", name); + goto error_out; + } + + dso->arch = plarch; +#else + dso->arch = NULL; +#endif + + dso->base = ~(GElf_Addr) 0; + dso->align = 0; + dso->end = 0; + for (i = 0; i < dso->ehdr.e_phnum; i++) + if (dso->phdr[i].p_type == PT_LOAD) + { + GElf_Addr base, end; + + if (dso->phdr[i].p_align > dso->align) + dso->align = dso->phdr[i].p_align; + base = dso->phdr[i].p_vaddr & ~(dso->phdr[i].p_align - 1); + end = dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz; + if (base < dso->base) + dso->base = base; + if (end > dso->end) + dso->end = end; + } + + if (dso->base == ~(GElf_Addr) 0) + { + error (0, 0, "%s: cannot find loadable segment", name); + goto error_out; + } + + read_dynamic (dso); + + dso->filename = (const char *) strdup (name); + dso->soname = dso->filename; + if (dso->info[DT_STRTAB] && dso->info[DT_SONAME]) + { + const char *soname; + + soname = get_data (dso, dso->info[DT_STRTAB] + dso->info[DT_SONAME], + NULL, NULL); + if (soname && soname[0] != '\0') + dso->soname = (const char *) strdup (soname); + } + +#if 0 + if (dso->arch->machine == EM_ALPHA + || dso->arch->machine == EM_MIPS) + for (i = 1; i < ehdr.e_shnum; ++i) + { + if ((dso->shdr[i].sh_type == SHT_ALPHA_DEBUG + && dso->arch->machine == EM_ALPHA) + || (dso->shdr[i].sh_type == SHT_MIPS_DEBUG + && dso->arch->machine == EM_MIPS)) + { + const char *name + = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".mdebug")) + dso->mdebug_orig_offset = dso->shdr[i].sh_offset; + break; + } + } +#endif + + return dso; + +error_out: + if (dso) + { + free (dso->move); + if (dso->soname != dso->filename) + free ((char *) dso->soname); + free ((char *) dso->filename); + free (dso); + } + if (elf) + elf_end (elf); + if (fd != -1) + close (fd); + return NULL; +} + +#if 0 + +static int +adjust_symtab_section_indices (DSO *dso, int n, int old_shnum, int *old_to_new) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int changed = 0, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + if (sym.st_shndx >= old_shnum + || old_to_new[sym.st_shndx] == -1) + { + if (! sym.st_size && + sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION)) + { + sym.st_value = 0; + sym.st_shndx = SHN_UNDEF; + gelfx_update_sym (dso->elf, data, ndx, &sym); + changed = 1; + continue; + } + else + { + if (sym.st_shndx >= old_shnum) + { + error (0, 0, "%s: Symbol section index outside of section numbers", + dso->filename); + return 1; + } + error (0, 0, "%s: Section symbol points into has been removed", + dso->filename); + return 1; + } + } + if (old_to_new[sym.st_shndx] != sym.st_shndx) + { + changed = 1; + sym.st_shndx = old_to_new[sym.st_shndx]; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + } + + if (changed) + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + return 0; +} + +static int +set_stt_section_values (DSO *dso, int n) +{ + Elf_Data *data; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx, sec; + char seen[dso->ehdr.e_shnum]; + + memset (seen, 0, dso->ehdr.e_shnum); + data = elf_getdata (scn, NULL); + assert (data != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + gelfx_getsym (dso->elf, data, 0, &sym); + if (sym.st_info != ELF32_ST_INFO (STB_LOCAL, STT_NOTYPE) + || sym.st_size != 0 || sym.st_other != 0 + || sym.st_value != 0 || sym.st_shndx != SHN_UNDEF + || sym.st_name != 0) + return 0; + + for (ndx = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + seen[sym.st_shndx] = 1; + sym.st_value = dso->shdr[sym.st_shndx].sh_addr; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + for (ndx = 1, sec = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx == SHN_UNDEF) + { + while (sec < dso->ehdr.e_shnum && seen[sec]) + ++sec; + + if (sec >= dso->ehdr.e_shnum) + sym.st_value = 0; + else + sym.st_value = dso->shdr[sec].sh_addr; + sym.st_shndx = sec++; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + return 0; +} + +struct section_move * +init_section_move (DSO *dso) +{ + struct section_move *move; + int i; + + move = malloc (sizeof (struct section_move) + + (dso->ehdr.e_shnum * 2 + 20) * sizeof (int)); + if (move == NULL) + { + error (0, ENOMEM, "%s: Could not move sections", dso->filename); + return move; + } + move->old_shnum = dso->ehdr.e_shnum; + move->new_shnum = dso->ehdr.e_shnum; + move->old_to_new = (int *)(move + 1); + move->new_to_old = move->old_to_new + move->new_shnum; + for (i = 0; i < move->new_shnum; i++) + { + move->old_to_new[i] = i; + move->new_to_old[i] = i; + } + return move; +} + +void +add_section (struct section_move *move, int sec) +{ + int i; + + assert (move->new_shnum < move->old_shnum + 20); + assert (sec <= move->new_shnum); + + memmove (move->new_to_old + sec + 1, move->new_to_old + sec, + (move->new_shnum - sec) * sizeof (int)); + ++move->new_shnum; + move->new_to_old[sec] = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] >= sec) + ++move->old_to_new[i]; +} + +void +remove_section (struct section_move *move, int sec) +{ + int i; + + assert (sec < move->new_shnum); + + memmove (move->new_to_old + sec, move->new_to_old + sec + 1, + (move->new_shnum - sec - 1) * sizeof (int)); + --move->new_shnum; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] == sec) + move->old_to_new[i] = -1; + else if (move->old_to_new[i] > sec) + --move->old_to_new[i]; +} + +int +reopen_dso (DSO *dso, struct section_move *move, const char *temp_base) +{ + char filename[strlen (temp_base ? temp_base : dso->filename) + + sizeof ("/dev/shm/.#prelink#.XXXXXX")]; + int adddel = 0; + int free_move = 0; + Elf *elf = NULL; + GElf_Ehdr ehdr; + char *e_ident; + int fd, i, j; + + if (move == NULL) + { + move = init_section_move (dso); + if (move == NULL) + return 1; + free_move = 1; + } + else + assert (dso->ehdr.e_shnum == move->old_shnum); + + if (temp_base == NULL) + temp_base = dso->filename; + sprintf (filename, "%s.#prelink#.XXXXXX", temp_base); + + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/tmp/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/dev/shm/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + } + if (fd == -1) + { + error (0, errno, "Could not create temporary file %s", filename); + goto error_out; + } + } + + elf = elf_begin (fd, ELF_C_WRITE, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s (elf_begin failed, dso_readonly)", elf_errmsg (-1)); + goto error_out; + + } + + /* Some gelf_newehdr implementations don't return the resulting + ElfNN_Ehdr, so we have to do it the hard way instead of: + e_ident = (char *) gelf_newehdr (elf, gelf_getclass (dso->elf)); */ + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + e_ident = (char *) elf32_newehdr (elf); + break; + case ELFCLASS64: + e_ident = (char *) elf64_newehdr (elf); + break; + default: + e_ident = NULL; + break; + } + + if (e_ident == NULL + /* This is here just for the gelfx wrapper, so that gelf_update_ehdr + already has the correct ELF class. */ + || memcpy (e_ident, dso->ehdr.e_ident, EI_NIDENT) == NULL + || gelf_update_ehdr (elf, &dso->ehdr) == 0 + || gelf_newphdr (elf, dso->ehdr.e_phnum) == 0) + { + error (0, 0, "Could not create new ELF headers"); + goto error_out; + } + ehdr = dso->ehdr; + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_update_phdr (elf, i, dso->phdr + i); + + for (i = 1; i < move->new_shnum; ++i) + { + Elf_Scn *scn; + Elf_Data data, *data1, *data2; + + if (move->new_to_old[i] == -1) + { + scn = elf_newscn (elf); + elf_newdata (scn); + } + else + { + j = move->new_to_old[i]; + scn = elf_newscn (elf); + gelfx_update_shdr (elf, scn, &dso->shdr[j]); + if (dso->shdr[j].sh_type == SHT_NOBITS) + { + data1 = elf_getdata (dso->scn[j], NULL); + data2 = elf_newdata (scn); + memcpy (data2, data1, sizeof (*data1)); + } + else + { + data.d_type = ELF_T_NUM; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + { + if (data.d_type == ELF_T_NUM) + data = *data1; + else if (data.d_type != data1->d_type + || data.d_version != data1->d_version) + abort (); + else + { + if (data1->d_off < data.d_off) + { + data.d_size += data.d_off - data1->d_off; + data.d_off = data1->d_off; + } + if (data1->d_off + data1->d_size + > data.d_off + data.d_size) + data.d_size = data1->d_off + data1->d_size + - data.d_off; + if (data1->d_align > data.d_align) + data.d_align = data1->d_align; + } + } + if (data.d_type == ELF_T_NUM) + { + assert (dso->shdr[j].sh_size == 0); + continue; + } + if (data.d_size != 0) + { + data.d_buf = calloc (1, data.d_size); + if (data.d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not copy section", + dso->filename); + goto error_out; + } + } + else + data.d_buf = NULL; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + memcpy (data.d_buf + data1->d_off - data.d_off, data1->d_buf, + data1->d_size); + data2 = elf_newdata (scn); + memcpy (data2, &data, sizeof (data)); + } + } + } + + ehdr.e_shnum = move->new_shnum; + dso->temp_filename = strdup (filename); + if (dso->temp_filename == NULL) + { + error (0, ENOMEM, "%s: Could not save temporary filename", dso->filename); + goto error_out; + } + dso->elfro = dso->elf; + dso->elf = elf; + dso->fdro = dso->fd; + dso->fd = fd; + dso->ehdr = ehdr; + dso->lastscn = 0; + elf = NULL; + fd = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] != i) + { + adddel = 1; + break; + } + if (! adddel) + for (i = 1; i < move->new_shnum; i++) + if (move->new_to_old[i] != i) + { + adddel = 1; + break; + } + + for (i = 1; i < move->new_shnum; i++) + { + dso->scn[i] = elf_getscn (dso->elf, i); + gelfx_getshdr (dso->elf, dso->scn[i], dso->shdr + i); + if (move->new_to_old[i] == -1) + continue; + if (dso->move + && (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM)) + { + if (adjust_symtab_section_indices (dso, i, dso->move->old_shnum, + dso->move->old_to_new)) + goto error_out; + } + if (adddel) + { + if (dso->shdr[i].sh_link) + { + if (dso->shdr[i].sh_link >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", dso->filename, + dso->shdr[i].sh_link); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_link] == -1) + { + error (0, 0, "Section sh_link points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_link = move->old_to_new[dso->shdr[i].sh_link]; + } + /* Only some section types use sh_info for section index. */ + if (dso->shdr[i].sh_info + && (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK))) + { + if (dso->shdr[i].sh_info >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", dso->filename, + dso->shdr[i].sh_info); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_info] == -1) + { + error (0, 0, "Section sh_info points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_info = move->old_to_new[dso->shdr[i].sh_info]; + } + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + { + if (adjust_symtab_section_indices (dso, i, move->old_shnum, + move->old_to_new)) + goto error_out; + } + } + } + + free (dso->move); + dso->move = NULL; + + dso->ehdr.e_shstrndx = move->old_to_new[dso->ehdr.e_shstrndx]; + gelf_update_ehdr (dso->elf, &dso->ehdr); + + read_dynamic (dso); + + /* If shoff does not point after last section, we need to adjust the sections + after it if we added or removed some sections. */ + if (move->old_shnum != move->new_shnum + && adjust_dso_nonalloc (dso, 0, dso->ehdr.e_shoff + 1, + ((long) move->new_shnum - (long) move->old_shnum) + * gelf_fsize (dso->elf, ELF_T_SHDR, 1, + EV_CURRENT))) + goto error_out; + + if (free_move) + free (move); + return 0; + +error_out: + if (free_move) + free (move); + if (elf) + elf_end (elf); + if (fd != -1) + { + wrap_unlink (filename); + close (fd); + } + return 1; +} + +/* Return true if the value of symbol SYM, which belongs to DSO, + should be treated as an address within the DSO, and should + therefore track DSO's relocations. */ + +int +adjust_symbol_p (DSO *dso, GElf_Sym *sym) +{ + if (sym->st_shndx == SHN_ABS + && sym->st_value != 0 + && (GELF_ST_TYPE (sym->st_info) <= STT_FUNC + || (dso->ehdr.e_machine == EM_ARM + && GELF_ST_TYPE (sym->st_info) == STT_ARM_TFUNC))) + /* This is problematic. How do we find out if + we should relocate this? Assume we should. */ + return 1; + + /* If a MIPS object does not define a symbol, but has a lazy binding + stub for it, st_value will point to that stub. Note that unlike + other targets, these stub addresses never participate in symbol + lookup; the stubs can only be called by the object that defines them. + st_values are only used in this way so that the associated GOT entry + can store a Quickstart value without losing the original stub + address. */ + if (dso->ehdr.e_machine == EM_MIPS + && sym->st_shndx == SHN_UNDEF + && sym->st_value != 0) + return 1; + + return (sym->st_shndx > SHN_UNDEF + && sym->st_shndx < dso->ehdr.e_shnum + && ELF32_ST_TYPE (sym->st_info) != STT_TLS + && RELOCATE_SCN (dso->shdr[sym->st_shndx].sh_flags)); +} + +static int +adjust_symtab (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (adjust_symbol_p (dso, &sym) && sym.st_value >= start) + { + sym.st_value += adjust; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +#endif + +int +dso_is_rdwr (DSO *dso) +{ + return dso->elfro != NULL; +} + +#if 0 + +GElf_Addr +adjust_old_to_new (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start) + { + addr += dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +GElf_Addr +adjust_new_to_old (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start + dso->adjust[i].adjust) + { + addr -= dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +static int +adjust_dynamic (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Dyn dyn; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dso->arch->adjust_dyn (dso, n, &dyn, start, adjust) == 0) + switch (dyn.d_tag) + { + case DT_REL: + case DT_RELA: + /* On some arches DT_REL* may be 0 indicating no relocations + (if DT_REL*SZ is also 0). Don't adjust it in that case. */ + if (dyn.d_un.d_ptr && dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + default: + if (dyn.d_tag < DT_ADDRRNGLO || dyn.d_tag > DT_ADDRRNGHI) + break; + /* FALLTHROUGH */ + case DT_INIT: + case DT_FINI: + case DT_HASH: + case DT_STRTAB: + case DT_SYMTAB: + case DT_JMPREL: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + case DT_PREINIT_ARRAY: + case DT_VERDEF: + case DT_VERNEED: + case DT_VERSYM: + case DT_PLTGOT: + if (dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + } + else + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + /* Update the cached dynamic info as well. */ + read_dynamic (dso); + return 0; +} + +#endif + +int +addr_to_sec (DSO *dso, GElf_Addr addr) +{ + GElf_Shdr *shdr; + int i; + + shdr = &dso->shdr[dso->lastscn]; + for (i = -1; i < dso->ehdr.e_shnum; shdr = &dso->shdr[++i]) + if (RELOCATE_SCN (shdr->sh_flags) + && shdr->sh_addr <= addr && shdr->sh_addr + shdr->sh_size > addr + && (shdr->sh_type != SHT_NOBITS || (shdr->sh_flags & SHF_TLS) == 0)) + { + if (i != -1) + dso->lastscn = i; + return dso->lastscn; + } + + return -1; +} + +#if 0 + +static int +adjust_rel (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rel (dso, &rel, start, adjust); + addr_adjust (rel.r_offset, start, adjust); + gelfx_update_rel (dso->elf, data, ndx, &rel); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +static int +adjust_rela (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rela (dso, &rela, start, adjust); + addr_adjust (rela.r_offset, start, adjust); + gelfx_update_rela (dso->elf, data, ndx, &rela); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +int +adjust_nonalloc (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int first, + GElf_Addr start, GElf_Addr adjust) +{ + int i; + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if ((shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + && (adjust & (shdr[i].sh_addralign - 1))) + adjust = (adjust + shdr[i].sh_addralign - 1) + & ~(shdr[i].sh_addralign - 1); + } + + if (ehdr->e_shoff >= start) + { + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + + if (adjust & (shdralign - 1)) + adjust = (adjust + shdralign - 1) & ~(shdralign - 1); + ehdr->e_shoff += adjust; + } + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if (shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + shdr[i].sh_offset += adjust; + } + return 0; +} + +int +adjust_dso_nonalloc (DSO *dso, int first, GElf_Addr start, GElf_Addr adjust) +{ + return adjust_nonalloc (dso, &dso->ehdr, dso->shdr, first, start, adjust); +} + +/* Add ADJUST to all addresses above START. */ +int +adjust_dso (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + int i; + + if (dso->arch->arch_adjust + && dso->arch->arch_adjust (dso, start, adjust)) + return 1; + + if (dso->ehdr.e_entry >= start) + { + dso->ehdr.e_entry += adjust; + gelf_update_ehdr (dso->elf, &dso->ehdr); + elf_flagehdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + } + + for (i = 0; i < dso->ehdr.e_phnum; i++) + { + /* Leave STACK segment alone, it has + p_vaddr == p_paddr == p_offset == p_filesz == p_memsz == 0. */ + if (dso->phdr[i].p_type == PT_GNU_STACK) + continue; + if (! start) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + } + else if (start <= dso->phdr[i].p_vaddr) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + dso->phdr[i].p_offset += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz) + { + dso->phdr[i].p_filesz += adjust; + dso->phdr[i].p_memsz += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + dso->phdr[i].p_memsz += adjust; + else + continue; + if (dso->phdr[i].p_type == PT_LOAD + && (dso->phdr[i].p_vaddr - dso->phdr[i].p_offset) + % dso->phdr[i].p_align) + { + error (0, 0, "%s: PT_LOAD %08llx %08llx 0x%x would be not properly aligned", + dso->filename, (long long) dso->phdr[i].p_offset, + (long long) dso->phdr[i].p_vaddr, (int) dso->phdr[i].p_align); + return 1; + } + gelf_update_phdr (dso->elf, i, dso->phdr + i); + } + elf_flagphdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + + for (i = 1; i < dso->ehdr.e_shnum; i++) + { + const char *name; + + if (dso->arch->adjust_section) + { + int ret = dso->arch->adjust_section (dso, i, start, adjust); + + if (ret == 1) + return 1; + else if (ret) + continue; + } + switch (dso->shdr[i].sh_type) + { + case SHT_PROGBITS: + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (strcmp (name, ".stab") == 0 + && adjust_stabs (dso, i, start, adjust)) + return 1; + if (strcmp (name, ".debug_info") == 0 + && adjust_dwarf2 (dso, i, start, adjust)) + return 1; + break; + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_NOBITS: + case SHT_STRTAB: + break; + case SHT_SYMTAB: + case SHT_DYNSYM: + if (adjust_symtab (dso, i, start, adjust)) + return 1; + break; + case SHT_DYNAMIC: + if (adjust_dynamic (dso, i, start, adjust)) + return 1; + break; + case SHT_REL: + /* Don't adjust reloc sections for debug info. */ + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rel (dso, i, start, adjust)) + return 1; + break; + case SHT_RELA: + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rela (dso, i, start, adjust)) + return 1; + break; + } + if ((dso->arch->machine == EM_ALPHA + && dso->shdr[i].sh_type == SHT_ALPHA_DEBUG) + || (dso->arch->machine == EM_MIPS + && dso->shdr[i].sh_type == SHT_MIPS_DEBUG)) + if (adjust_mdebug (dso, i, start, adjust)) + return 1; + } + + for (i = 0; i < dso->ehdr.e_shnum; i++) + { + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_addr >= start) + { + Elf_Scn *scn = dso->scn[i]; + + dso->shdr[i].sh_addr += adjust; + if (start) + dso->shdr[i].sh_offset += adjust; + gelfx_update_shdr (dso->elf, scn, dso->shdr + i); + elf_flagshdr (scn, ELF_C_SET, ELF_F_DIRTY); + } + } + } + + addr_adjust (dso->base, start, adjust); + addr_adjust (dso->end, start, adjust); + + if (start) + { + start = adjust_new_to_old (dso, start); + for (i = 0; i < dso->nadjust; i++) + if (start < dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + break; + if (i < dso->nadjust && start == dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + { + dso->adjust = + realloc (dso->adjust, (dso->nadjust + 1) * sizeof (*dso->adjust)); + if (dso->adjust == NULL) + { + error (0, ENOMEM, "Cannot record the list of adjustements being made"); + return 1; + } + memmove (dso->adjust + i + 1, dso->adjust + i, dso->nadjust - i); + dso->adjust[i].start = start; + dso->adjust[i].adjust = adjust; + ++dso->nadjust; + } + } + + return start ? adjust_dso_nonalloc (dso, 0, 0, adjust) : 0; +} + +int +recompute_nonalloc_offsets (DSO *dso) +{ + int i, first_nonalloc, sec_before_shoff = 0; + GElf_Addr last_offset = 0; + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + GElf_Addr shdrsize = gelf_fsize (dso->elf, ELF_T_SHDR, 1, EV_CURRENT) + * dso->ehdr.e_shnum; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_type == SHT_NOBITS) + last_offset = dso->shdr[i].sh_offset; + else + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + else + break; + + first_nonalloc = i; + if (dso->ehdr.e_shoff < dso->shdr[i].sh_offset) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + else + for (; i < dso->ehdr.e_shnum; ++i) + if (dso->shdr[i].sh_offset < dso->ehdr.e_shoff + && (i == dso->ehdr.e_shnum - 1 + || dso->shdr[i + 1].sh_offset > dso->ehdr.e_shoff)) + { + sec_before_shoff = i; + break; + } + + for (i = first_nonalloc; i < dso->ehdr.e_shnum; ++i) + { + assert (!RELOCATE_SCN (dso->shdr[i].sh_flags)); + assert (dso->shdr[i].sh_type != SHT_NOBITS); + dso->shdr[i].sh_offset = (last_offset + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + if (i == sec_before_shoff) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + } + + return 0; +} + +int +strtabfind (DSO *dso, int strndx, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + const char *p, *q, *r; + size_t len = strlen (name); + + if (dso->shdr[strndx].sh_type != SHT_STRTAB) + return 0; + + scn = dso->scn[strndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[strndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + return 0; +} + +int +shstrtabadd (DSO *dso, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr adjust; + const char *p, *q, *r; + size_t len = strlen (name), align; + int ret; + + scn = dso->scn[dso->ehdr.e_shstrndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[dso->ehdr.e_shstrndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + data->d_buf = realloc (data->d_buf, data->d_size + len + 1); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "Cannot add new section name %s", name); + return 0; + } + + memcpy (data->d_buf + data->d_size, name, len + 1); + ret = data->d_size; + data->d_size += len + 1; + align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + adjust = (len + 1 + align - 1) & ~(align - 1); + if (adjust_dso_nonalloc (dso, 0, + dso->shdr[dso->ehdr.e_shstrndx].sh_offset + + dso->shdr[dso->ehdr.e_shstrndx].sh_size, + adjust)) + return 0; + dso->shdr[dso->ehdr.e_shstrndx].sh_size += len + 1; + return ret; +} + +int +relocate_dso (DSO *dso, GElf_Addr base) +{ + /* Check if it is already relocated. */ + if (dso->base == base) + return 0; + + if (! dso_is_rdwr (dso)) + { + if (reopen_dso (dso, NULL, NULL)) + return 1; + } + + return adjust_dso (dso, 0, base - dso->base); +} + +#endif + +static int +close_dso_1 (DSO *dso) +{ + if (dso_is_rdwr (dso)) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + Elf_Scn *scn = dso->scn[i]; + Elf_Data *data = NULL; + + while ((data = elf_getdata (scn, data)) != NULL) + { + free (data->d_buf); + data->d_buf = NULL; + } + } + } + + elf_end (dso->elf); + close (dso->fd); + if (dso->elfro) + { + elf_end (dso->elfro); + close (dso->fdro); + } + if (dso->filename != dso->soname) + free ((char *) dso->soname); + free ((char *) dso->filename); + free ((char *) dso->temp_filename); + free (dso->move); + free (dso->adjust); + free (dso->undo.d_buf); + free (dso); + return 0; +} + +int +close_dso (DSO *dso) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr && dso->temp_filename != NULL) + wrap_unlink (dso->temp_filename); + close_dso_1 (dso); + return 0; +} + +#if 0 + +int +prepare_write_dso (DSO *dso) +{ + int i; + + if (check_dso (dso) + || (dso->mdebug_orig_offset && finalize_mdebug (dso))) + return 1; + + gelf_update_ehdr (dso->elf, &dso->ehdr); + for (i = 0; i < dso->ehdr.e_phnum; ++i) + gelf_update_phdr (dso->elf, i, dso->phdr + i); + for (i = 0; i < dso->ehdr.e_shnum; ++i) + { + gelfx_update_shdr (dso->elf, dso->scn[i], dso->shdr + i); + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + set_stt_section_values (dso, i); + } + return 0; +} + +int +write_dso (DSO *dso) +{ + if (prepare_write_dso (dso)) + return 1; + + if (! dso->permissive && ELF_F_PERMISSIVE) + elf_flagelf (dso->elf, ELF_C_CLR, ELF_F_PERMISSIVE); + + if (elf_update (dso->elf, ELF_C_WRITE) == -1) + return 2; + return 0; +} + +int +set_security_context (DSO *dso, const char *temp_name, const char *name) +{ +#ifdef USE_SELINUX + static int selinux_enabled = -1; + if (selinux_enabled == -1) + selinux_enabled = is_selinux_enabled (); + if (selinux_enabled > 0) + { + security_context_t scontext; + if (getfilecon (name, &scontext) < 0) + { + /* If the filesystem doesn't support extended attributes, + the original had no special security context and the + target cannot have one either. */ + if (errno == EOPNOTSUPP) + return 0; + + error (0, errno, "Could not get security context for %s", + name); + return 1; + } + if (setfilecon (temp_name, scontext) < 0) + { + error (0, errno, "Could not set security context for %s", + name); + freecon (scontext); + return 1; + } + freecon (scontext); + } +#endif + return 0; +} + +int +update_dso (DSO *dso, const char *orig_name) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr) + { + char *name1, *name2; + struct utimbuf u; + struct stat64 st; + + switch (write_dso (dso)) + { + case 2: + error (0, 0, "Could not write %s: %s", dso->filename, + elf_errmsg (-1)); + /* FALLTHROUGH */ + case 1: + close_dso (dso); + return 1; + case 0: + break; + } + + name1 = strdupa (dso->filename); + name2 = strdupa (dso->temp_filename); + if (fstat64 (dso->fdro, &st) < 0) + { + error (0, errno, "Could not stat %s", dso->filename); + close_dso (dso); + return 1; + } + if (fchown (dso->fd, st.st_uid, st.st_gid) < 0 + || fchmod (dso->fd, st.st_mode & 07777) < 0) + { + error (0, errno, "Could not set %s owner or mode", dso->filename); + close_dso (dso); + return 1; + } + close_dso_1 (dso); + u.actime = time (NULL); + u.modtime = st.st_mtime; + wrap_utime (name2, &u); + + if (set_security_context (dso, name2, orig_name ? orig_name : name1)) + { + wrap_unlink (name2); + return 1; + } + + if (wrap_rename (name2, name1)) + { + wrap_unlink (name2); + error (0, errno, "Could not rename temporary to %s", name1); + return 1; + } + } + else + close_dso_1 (dso); + + return 0; +} + +#endif diff --git a/trunk/src/dso.c b/trunk/src/dso.c new file mode 100644 index 0000000..5080ffc --- /dev/null +++ b/trunk/src/dso.c @@ -0,0 +1,1797 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#if defined HAVE_LIBSELINUX && defined HAVE_SELINUX_SELINUX_H +#include <selinux/selinux.h> +#define USE_SELINUX +#endif + +#define RELOCATE_SCN(shf) \ + ((shf) & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + +#ifndef ELF_F_PERMISSIVE +# define ELF_F_PERMISSIVE 0 +#endif + +void +read_dynamic (DSO *dso) +{ + int i; + + memset (dso->info, 0, sizeof(dso->info)); + dso->info_set_mask = 0; + for (i = 0; i < dso->ehdr.e_shnum; i++) + if (dso->shdr[i].sh_type == SHT_DYNAMIC) + { + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[i]; + GElf_Dyn dyn; + + dso->dynamic = i; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if ((GElf_Xword) dyn.d_tag < DT_NUM) + { + dso->info[dyn.d_tag] = dyn.d_un.d_val; + if (dyn.d_tag < 50) + dso->info_set_mask |= (1ULL << dyn.d_tag); + } + else if (dyn.d_tag == DT_CHECKSUM) + { + dso->info_DT_CHECKSUM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_CHECKSUM_BIT); + } + else if (dyn.d_tag == DT_GNU_PRELINKED) + { + dso->info_DT_GNU_PRELINKED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_PRELINKED_BIT); + } + else if (dyn.d_tag == DT_VERDEF) + { + dso->info_DT_VERDEF = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERDEF_BIT); + } + else if (dyn.d_tag == DT_VERNEED) + { + dso->info_DT_VERNEED = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERNEED_BIT); + } + else if (dyn.d_tag == DT_VERSYM) + { + dso->info_DT_VERSYM = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_VERSYM_BIT); + } + else if (dyn.d_tag == DT_FILTER) + dso->info_set_mask |= (1ULL << DT_FILTER_BIT); + else if (dyn.d_tag == DT_AUXILIARY) + dso->info_set_mask |= (1ULL << DT_AUXILIARY_BIT); + else if (dyn.d_tag == DT_LOPROC) + dso->info_set_mask |= (1ULL << DT_LOPROC_BIT); + else if (dyn.d_tag == DT_GNU_HASH) + { + dso->info_DT_GNU_HASH = dyn.d_un.d_val; + dso->info_set_mask |= (1ULL << DT_GNU_HASH_BIT); + } + if (dso->ehdr.e_machine == EM_MIPS) + { + if (dyn.d_tag == DT_MIPS_LOCAL_GOTNO) + dso->info_DT_MIPS_LOCAL_GOTNO = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_GOTSYM) + dso->info_DT_MIPS_GOTSYM = dyn.d_un.d_val; + else if (dyn.d_tag == DT_MIPS_SYMTABNO) + dso->info_DT_MIPS_SYMTABNO = dyn.d_un.d_val; + } + } + if (ndx < maxndx) + break; + } + } +} + +int +set_dynamic (DSO *dso, GElf_Word tag, GElf_Addr value, int fatal) +{ + Elf_Data *data; + Elf_Scn *scn; + GElf_Dyn dyn; + int ndx, maxndx; + uint64_t mask = dso->info_set_mask; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + + scn = dso->scn[dso->dynamic]; + + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + + switch (tag) + { + case DT_CHECKSUM: + mask |= (1ULL << DT_CHECKSUM_BIT); break; + case DT_GNU_PRELINKED: + mask |= (1ULL << DT_GNU_PRELINKED_BIT); break; + case DT_VERDEF: + mask |= (1ULL << DT_VERDEF_BIT); break; + case DT_VERNEED: + mask |= (1ULL << DT_VERNEED_BIT); break; + case DT_VERSYM: + mask |= (1ULL << DT_VERSYM_BIT); break; + default: + if (tag < DT_NUM && tag < 50) + mask |= (1ULL << tag); + break; + } + + maxndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + else if (dyn.d_tag == tag) + { + if (dyn.d_un.d_ptr != value) + { + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + } + + return 0; + } + } + assert (ndx < maxndx); + + if (ndx + 1 < maxndx) + { + /* DT_NULL is not the last dynamic entry. */ + gelfx_update_dyn (dso->elf, data, ndx + 1, &dyn); + dyn.d_tag = tag; + dyn.d_un.d_ptr = value; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + dso->info_set_mask = mask; + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; + } + + if (fatal) + error (0, 0, "%s: Not enough room to add .dynamic entry", + dso->filename); + return 1; +} + +int +check_dso (DSO *dso) +{ + int i, last = 1; + + /* FIXME: Several routines in prelink and in libelf-0.7.0 too + rely on sh_offset's monotonically increasing. */ + for (i = 2; i < dso->ehdr.e_shnum; ++i) + { + if (dso->shdr[last].sh_offset + + (dso->shdr[last].sh_type == SHT_NOBITS + ? 0 : dso->shdr[last].sh_size) > dso->shdr[i].sh_offset) + { + if (!dso->permissive + || RELOCATE_SCN (dso->shdr[last].sh_flags) + || RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + error (0, 0, "%s: section file offsets not monotonically increasing", + dso->filename); + return 1; + } + } + if (!dso->permissive + || (dso->shdr[i].sh_type != SHT_NOBITS && dso->shdr[i].sh_size != 0)) + last = i; + } + return 0; +} + +DSO * +open_dso (const char *name) +{ + int fd; + + fd = wrap_open (name, O_RDONLY); + if (fd == -1) + { + error (0, errno, "cannot open \"%s\"", name); + return NULL; + } + return fdopen_dso (fd, name); +} + +/* WARNING: If prelink is ever multi-threaded, this will not work + Other alternatives are: + 1) make section_cmp nested function - trampolines + vs. non-exec stack needs to be resolved for it though + 2) make the variable __thread + 3) use locking around the qsort + */ +static DSO *section_cmp_dso; + +static int +section_cmp (const void *A, const void *B) +{ + int *a = (int *) A; + int *b = (int *) B; + DSO *dso = section_cmp_dso; + + if (dso->shdr[*a].sh_offset < dso->shdr[*b].sh_offset) + return -1; + if (dso->shdr[*a].sh_offset > dso->shdr[*b].sh_offset) + return 1; + if (*a < *b) + return -1; + return *a > *b; +} + +DSO * +fdopen_dso (int fd, const char *name) +{ + Elf *elf = NULL; + GElf_Ehdr ehdr; + GElf_Addr last_off; + int i, j, k, last, *sections, *invsections; + DSO *dso = NULL; + struct PLArch *plarch; + extern struct PLArch __start_pl_arch[], __stop_pl_arch[]; + + elf = elf_begin (fd, ELF_C_READ, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1)); + goto error_out; + } + + if (elf_kind (elf) != ELF_K_ELF) + { + error (0, 0, "\"%s\" is not an ELF file", name); + goto error_out; + } + + if (gelf_getehdr (elf, &ehdr) == NULL) + { + error (0, 0, "cannot get the ELF header: %s", + elf_errmsg (-1)); + goto error_out; + } + + if (ehdr.e_type != ET_DYN && ehdr.e_type != ET_EXEC) + { + error (0, 0, "\"%s\" is not a shared library", name); + goto error_out; + } + + if (ehdr.e_shnum == 0) + { + GElf_Phdr phdr; + + /* Check for UPX compressed executables. */ + if (ehdr.e_type == ET_EXEC + && ehdr.e_phnum > 0 + && (gelf_getphdr (elf, 0, &phdr), phdr.p_type == PT_LOAD) + && phdr.p_filesz >= 256 + && phdr.p_filesz <= 4096 + && phdr.p_offset == 0 + && ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize < phdr.p_filesz) + { + char *buf = alloca (phdr.p_filesz); + size_t start = ehdr.e_phoff + ehdr.e_phnum * ehdr.e_phentsize; + + if (pread (fd, buf, phdr.p_filesz, 0) == phdr.p_filesz + && memmem (buf + start, phdr.p_filesz - start, + "UPX!", 4) != NULL) + { + error (0, 0, "\"%s\" is UPX compressed executable", name); + goto error_out; + } + } + error (0, 0, "\"%s\" has no section headers", name); + goto error_out; + } + + /* Allocate DSO structure. Leave place for additional 20 new section + headers. */ + dso = (DSO *) + malloc (sizeof(DSO) + (ehdr.e_shnum + 20) * sizeof(GElf_Shdr) + + (ehdr.e_phnum + 1) * sizeof(GElf_Phdr) + + (ehdr.e_shnum + 20) * sizeof(Elf_Scn *)); + if (!dso) + { + error (0, ENOMEM, "Could not open DSO"); + goto error_out; + } + + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + + memset (dso, 0, sizeof(DSO)); + dso->elf = elf; + dso->ehdr = ehdr; + dso->phdr = (GElf_Phdr *) &dso->shdr[ehdr.e_shnum + 20]; + dso->scn = (Elf_Scn **) &dso->phdr[ehdr.e_phnum + 1]; + switch (ehdr.e_ident[EI_CLASS]) + { + case ELFCLASS32: + dso->mask = 0xffffffff; break; + case ELFCLASS64: + dso->mask = 0xffffffffffffffffULL; break; + } + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_getphdr (elf, i, dso->phdr + i); + dso->fd = fd; + + for (i = 0, j = 0; i < ehdr.e_shnum; ++i) + { + dso->scn[i] = elf_getscn (elf, i); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + if ((dso->shdr[i].sh_flags & SHF_ALLOC) && dso->shdr[i].sh_type != SHT_NOBITS) + j = 1; + } + if (j == 0) + { + /* If all ALLOC sections are SHT_NOBITS, then this is a + stripped-to-file debuginfo. Skip it silently. */ + goto error_out; + } + + sections = (int *) alloca (dso->ehdr.e_shnum * sizeof (int) * 2); + sections[0] = 0; + for (i = 1, j = 1, k = dso->ehdr.e_shnum, last = -1; + i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + last = i; + sections[j++] = i; + } + else + sections[--k] = i; + assert (j == k); + + section_cmp_dso = dso; + qsort (sections + k, dso->ehdr.e_shnum - k, sizeof (*sections), section_cmp); + invsections = sections + dso->ehdr.e_shnum; + invsections[0] = 0; + for (i = 1, j = 0; i < ehdr.e_shnum; ++i) + { + if (i != sections[i]) + { + j = 1; + dso->scn[i] = elf_getscn (elf, sections[i]); + gelfx_getshdr (elf, dso->scn[i], dso->shdr + i); + } + invsections[sections[i]] = i; + } + + if (j) + { + dso->move = init_section_move (dso); + if (dso->move == NULL) + goto error_out; + memcpy (dso->move->old_to_new, invsections, dso->ehdr.e_shnum * sizeof (int)); + memcpy (dso->move->new_to_old, sections, dso->ehdr.e_shnum * sizeof (int)); + } + + last_off = 0; + for (i = 1; i < ehdr.e_shnum; ++i) + { + if (dso->shdr[i].sh_link >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", name, + dso->shdr[i].sh_link); + goto error_out; + } + dso->shdr[i].sh_link = invsections[dso->shdr[i].sh_link]; + if (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK)) + { + if (dso->shdr[i].sh_info >= ehdr.e_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", name, + dso->shdr[i].sh_info); + goto error_out; + } + dso->shdr[i].sh_info = invsections[dso->shdr[i].sh_info]; + } + + /* Some linkers mess up sh_offset fields for empty or nobits + sections. */ + if (RELOCATE_SCN (dso->shdr[i].sh_flags) + && (dso->shdr[i].sh_size == 0 + || dso->shdr[i].sh_type == SHT_NOBITS)) + { + for (j = i + 1; j < ehdr.e_shnum; ++j) + if (! RELOCATE_SCN (dso->shdr[j].sh_flags)) + break; + else if (dso->shdr[j].sh_size != 0 + && dso->shdr[j].sh_type != SHT_NOBITS) + break; + dso->shdr[i].sh_offset = (last_off + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + if (j < ehdr.e_shnum + && dso->shdr[i].sh_offset > dso->shdr[j].sh_offset) + { + GElf_Addr k; + + for (k = dso->shdr[i].sh_addralign - 1; k; ) + { + k >>= 1; + dso->shdr[i].sh_offset = (last_off + k) & ~k; + if (dso->shdr[i].sh_offset <= dso->shdr[j].sh_offset) + break; + } + } + last_off = dso->shdr[i].sh_offset; + } + else + last_off = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + dso->ehdr.e_shstrndx = invsections[dso->ehdr.e_shstrndx]; + + for (plarch = __start_pl_arch; plarch < __stop_pl_arch; plarch++) + if (plarch->class == ehdr.e_ident[EI_CLASS] + && (plarch->machine == ehdr.e_machine + || plarch->alternate_machine[0] == ehdr.e_machine + || plarch->alternate_machine[1] == ehdr.e_machine + || plarch->alternate_machine[2] == ehdr.e_machine)) + break; + + if (plarch == __stop_pl_arch || ehdr.e_machine == EM_NONE) + { + error (0, 0, "\"%s\"'s architecture is not supported", name); + goto error_out; + } + + dso->arch = plarch; + + dso->base = ~(GElf_Addr) 0; + dso->align = 0; + dso->end = 0; + for (i = 0; i < dso->ehdr.e_phnum; i++) + if (dso->phdr[i].p_type == PT_LOAD) + { + GElf_Addr base, end; + + if (dso->phdr[i].p_align > dso->align) + dso->align = dso->phdr[i].p_align; + base = dso->phdr[i].p_vaddr & ~(dso->phdr[i].p_align - 1); + end = dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz; + if (base < dso->base) + dso->base = base; + if (end > dso->end) + dso->end = end; + } + + if (dso->base == ~(GElf_Addr) 0) + { + error (0, 0, "%s: cannot find loadable segment", name); + goto error_out; + } + + read_dynamic (dso); + + dso->filename = (const char *) strdup (name); + dso->soname = dso->filename; + if (dso->info[DT_STRTAB] && dso->info[DT_SONAME]) + { + const char *soname; + + soname = get_data (dso, dso->info[DT_STRTAB] + dso->info[DT_SONAME], + NULL, NULL); + if (soname && soname[0] != '\0') + dso->soname = (const char *) strdup (soname); + } + + if (dso->arch->machine == EM_ALPHA + || dso->arch->machine == EM_MIPS) + for (i = 1; i < ehdr.e_shnum; ++i) + { + if ((dso->shdr[i].sh_type == SHT_ALPHA_DEBUG + && dso->arch->machine == EM_ALPHA) + || (dso->shdr[i].sh_type == SHT_MIPS_DEBUG + && dso->arch->machine == EM_MIPS)) + { + const char *name + = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".mdebug")) + dso->mdebug_orig_offset = dso->shdr[i].sh_offset; + break; + } + } + + return dso; + +error_out: + if (dso) + { + free (dso->move); + if (dso->soname != dso->filename) + free ((char *) dso->soname); + free ((char *) dso->filename); + free (dso); + } + if (elf) + elf_end (elf); + if (fd != -1) + close (fd); + return NULL; +} + +static int +adjust_symtab_section_indices (DSO *dso, int n, int old_shnum, int *old_to_new) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int changed = 0, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + if (sym.st_shndx >= old_shnum + || old_to_new[sym.st_shndx] == -1) + { + if (! sym.st_size && + sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION)) + { + sym.st_value = 0; + sym.st_shndx = SHN_UNDEF; + gelfx_update_sym (dso->elf, data, ndx, &sym); + changed = 1; + continue; + } + else + { + if (sym.st_shndx >= old_shnum) + { + error (0, 0, "%s: Symbol section index outside of section numbers", + dso->filename); + return 1; + } + error (0, 0, "%s: Section symbol points into has been removed", + dso->filename); + return 1; + } + } + if (old_to_new[sym.st_shndx] != sym.st_shndx) + { + changed = 1; + sym.st_shndx = old_to_new[sym.st_shndx]; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + } + + if (changed) + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + return 0; +} + +static int +set_stt_section_values (DSO *dso, int n) +{ + Elf_Data *data; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx, sec; + char seen[dso->ehdr.e_shnum]; + + memset (seen, 0, dso->ehdr.e_shnum); + data = elf_getdata (scn, NULL); + assert (data != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + gelfx_getsym (dso->elf, data, 0, &sym); + if (sym.st_info != ELF32_ST_INFO (STB_LOCAL, STT_NOTYPE) + || sym.st_size != 0 || sym.st_other != 0 + || sym.st_value != 0 || sym.st_shndx != SHN_UNDEF + || sym.st_name != 0) + return 0; + + for (ndx = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx > SHN_UNDEF && sym.st_shndx < SHN_LORESERVE) + { + seen[sym.st_shndx] = 1; + sym.st_value = dso->shdr[sym.st_shndx].sh_addr; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + for (ndx = 1, sec = 1; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (sym.st_info == ELF32_ST_INFO (STB_LOCAL, STT_SECTION) + && sym.st_size == 0 && sym.st_other == 0 + && sym.st_name == 0) + { + if (sym.st_shndx == SHN_UNDEF) + { + while (sec < dso->ehdr.e_shnum && seen[sec]) + ++sec; + + if (sec >= dso->ehdr.e_shnum) + sym.st_value = 0; + else + sym.st_value = dso->shdr[sec].sh_addr; + sym.st_shndx = sec++; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + else + break; + } + + return 0; +} + +struct section_move * +init_section_move (DSO *dso) +{ + struct section_move *move; + int i; + + move = malloc (sizeof (struct section_move) + + (dso->ehdr.e_shnum * 2 + 20) * sizeof (int)); + if (move == NULL) + { + error (0, ENOMEM, "%s: Could not move sections", dso->filename); + return move; + } + move->old_shnum = dso->ehdr.e_shnum; + move->new_shnum = dso->ehdr.e_shnum; + move->old_to_new = (int *)(move + 1); + move->new_to_old = move->old_to_new + move->new_shnum; + for (i = 0; i < move->new_shnum; i++) + { + move->old_to_new[i] = i; + move->new_to_old[i] = i; + } + return move; +} + +void +add_section (struct section_move *move, int sec) +{ + int i; + + assert (move->new_shnum < move->old_shnum + 20); + assert (sec <= move->new_shnum); + + memmove (move->new_to_old + sec + 1, move->new_to_old + sec, + (move->new_shnum - sec) * sizeof (int)); + ++move->new_shnum; + move->new_to_old[sec] = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] >= sec) + ++move->old_to_new[i]; +} + +void +remove_section (struct section_move *move, int sec) +{ + int i; + + assert (sec < move->new_shnum); + + memmove (move->new_to_old + sec, move->new_to_old + sec + 1, + (move->new_shnum - sec - 1) * sizeof (int)); + --move->new_shnum; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] == sec) + move->old_to_new[i] = -1; + else if (move->old_to_new[i] > sec) + --move->old_to_new[i]; +} + +int +reopen_dso (DSO *dso, struct section_move *move, const char *temp_base) +{ + char filename[strlen (temp_base ? temp_base : dso->filename) + + sizeof ("/dev/shm/.#prelink#.XXXXXX")]; + int adddel = 0; + int free_move = 0; + Elf *elf = NULL; + GElf_Ehdr ehdr; + char *e_ident; + int fd, i, j; + + if (move == NULL) + { + move = init_section_move (dso); + if (move == NULL) + return 1; + free_move = 1; + } + else + assert (dso->ehdr.e_shnum == move->old_shnum); + + if (temp_base == NULL) + temp_base = dso->filename; + sprintf (filename, "%s.#prelink#.XXXXXX", temp_base); + + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/tmp/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + if (fd == -1) + { + strcpy (filename, "/dev/shm/#prelink#.XXXXXX"); + fd = wrap_mkstemp (filename); + } + if (fd == -1) + { + error (0, errno, "Could not create temporary file %s", filename); + goto error_out; + } + } + + elf = elf_begin (fd, ELF_C_WRITE, NULL); + if (elf == NULL) + { + error (0, 0, "cannot open ELF file: %s", elf_errmsg (-1)); + goto error_out; + + } + + /* Some gelf_newehdr implementations don't return the resulting + ElfNN_Ehdr, so we have to do it the hard way instead of: + e_ident = (char *) gelf_newehdr (elf, gelf_getclass (dso->elf)); */ + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + e_ident = (char *) elf32_newehdr (elf); + break; + case ELFCLASS64: + e_ident = (char *) elf64_newehdr (elf); + break; + default: + e_ident = NULL; + break; + } + + if (e_ident == NULL + /* This is here just for the gelfx wrapper, so that gelf_update_ehdr + already has the correct ELF class. */ + || memcpy (e_ident, dso->ehdr.e_ident, EI_NIDENT) == NULL + || gelf_update_ehdr (elf, &dso->ehdr) == 0 + || gelf_newphdr (elf, dso->ehdr.e_phnum) == 0) + { + error (0, 0, "Could not create new ELF headers"); + goto error_out; + } + ehdr = dso->ehdr; + elf_flagelf (elf, ELF_C_SET, ELF_F_LAYOUT | ELF_F_PERMISSIVE); + for (i = 0; i < ehdr.e_phnum; ++i) + gelf_update_phdr (elf, i, dso->phdr + i); + + for (i = 1; i < move->new_shnum; ++i) + { + Elf_Scn *scn; + Elf_Data data, *data1, *data2; + + if (move->new_to_old[i] == -1) + { + scn = elf_newscn (elf); + elf_newdata (scn); + } + else + { + j = move->new_to_old[i]; + scn = elf_newscn (elf); + gelfx_update_shdr (elf, scn, &dso->shdr[j]); + if (dso->shdr[j].sh_type == SHT_NOBITS) + { + data1 = elf_getdata (dso->scn[j], NULL); + data2 = elf_newdata (scn); + memcpy (data2, data1, sizeof (*data1)); + } + else + { + data.d_type = ELF_T_NUM; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + { + if (data.d_type == ELF_T_NUM) + data = *data1; + else if (data.d_type != data1->d_type + || data.d_version != data1->d_version) + abort (); + else + { + if (data1->d_off < data.d_off) + { + data.d_size += data.d_off - data1->d_off; + data.d_off = data1->d_off; + } + if (data1->d_off + data1->d_size + > data.d_off + data.d_size) + data.d_size = data1->d_off + data1->d_size + - data.d_off; + if (data1->d_align > data.d_align) + data.d_align = data1->d_align; + } + } + if (data.d_type == ELF_T_NUM) + { + assert (dso->shdr[j].sh_size == 0); + continue; + } + if (data.d_size != 0) + { + data.d_buf = calloc (1, data.d_size); + if (data.d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not copy section", + dso->filename); + goto error_out; + } + } + else + data.d_buf = NULL; + data1 = NULL; + while ((data1 = elf_getdata (dso->scn[j], data1)) + != NULL) + memcpy (data.d_buf + data1->d_off - data.d_off, data1->d_buf, + data1->d_size); + data2 = elf_newdata (scn); + memcpy (data2, &data, sizeof (data)); + } + } + } + + ehdr.e_shnum = move->new_shnum; + dso->temp_filename = strdup (filename); + if (dso->temp_filename == NULL) + { + error (0, ENOMEM, "%s: Could not save temporary filename", dso->filename); + goto error_out; + } + dso->elfro = dso->elf; + dso->elf = elf; + dso->fdro = dso->fd; + dso->fd = fd; + dso->ehdr = ehdr; + dso->lastscn = 0; + elf = NULL; + fd = -1; + for (i = 1; i < move->old_shnum; i++) + if (move->old_to_new[i] != i) + { + adddel = 1; + break; + } + if (! adddel) + for (i = 1; i < move->new_shnum; i++) + if (move->new_to_old[i] != i) + { + adddel = 1; + break; + } + + for (i = 1; i < move->new_shnum; i++) + { + dso->scn[i] = elf_getscn (dso->elf, i); + gelfx_getshdr (dso->elf, dso->scn[i], dso->shdr + i); + if (move->new_to_old[i] == -1) + continue; + if (dso->move + && (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM)) + { + if (adjust_symtab_section_indices (dso, i, dso->move->old_shnum, + dso->move->old_to_new)) + goto error_out; + } + if (adddel) + { + if (dso->shdr[i].sh_link) + { + if (dso->shdr[i].sh_link >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_link value %d", dso->filename, + dso->shdr[i].sh_link); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_link] == -1) + { + error (0, 0, "Section sh_link points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_link = move->old_to_new[dso->shdr[i].sh_link]; + } + /* Only some section types use sh_info for section index. */ + if (dso->shdr[i].sh_info + && (dso->shdr[i].sh_type == SHT_REL + || dso->shdr[i].sh_type == SHT_RELA + || (dso->shdr[i].sh_flags & SHF_INFO_LINK))) + { + if (dso->shdr[i].sh_info >= move->old_shnum) + { + error (0, 0, "%s: bogus sh_info value %d", dso->filename, + dso->shdr[i].sh_info); + goto error_out; + } + if (move->old_to_new[dso->shdr[i].sh_info] == -1) + { + error (0, 0, "Section sh_info points to has been removed"); + goto error_out; + } + dso->shdr[i].sh_info = move->old_to_new[dso->shdr[i].sh_info]; + } + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + { + if (adjust_symtab_section_indices (dso, i, move->old_shnum, + move->old_to_new)) + goto error_out; + } + } + } + + free (dso->move); + dso->move = NULL; + + dso->ehdr.e_shstrndx = move->old_to_new[dso->ehdr.e_shstrndx]; + gelf_update_ehdr (dso->elf, &dso->ehdr); + + read_dynamic (dso); + + /* If shoff does not point after last section, we need to adjust the sections + after it if we added or removed some sections. */ + if (move->old_shnum != move->new_shnum + && adjust_dso_nonalloc (dso, 0, dso->ehdr.e_shoff + 1, + ((long) move->new_shnum - (long) move->old_shnum) + * gelf_fsize (dso->elf, ELF_T_SHDR, 1, + EV_CURRENT))) + goto error_out; + + if (free_move) + free (move); + return 0; + +error_out: + if (free_move) + free (move); + if (elf) + elf_end (elf); + if (fd != -1) + { + wrap_unlink (filename); + close (fd); + } + return 1; +} + +/* Return true if the value of symbol SYM, which belongs to DSO, + should be treated as an address within the DSO, and should + therefore track DSO's relocations. */ + +int +adjust_symbol_p (DSO *dso, GElf_Sym *sym) +{ + if (sym->st_shndx == SHN_ABS + && sym->st_value != 0 + && (GELF_ST_TYPE (sym->st_info) <= STT_FUNC + || (dso->ehdr.e_machine == EM_ARM + && GELF_ST_TYPE (sym->st_info) == STT_ARM_TFUNC))) + /* This is problematic. How do we find out if + we should relocate this? Assume we should. */ + return 1; + + /* If a MIPS object does not define a symbol, but has a lazy binding + stub for it, st_value will point to that stub. Note that unlike + other targets, these stub addresses never participate in symbol + lookup; the stubs can only be called by the object that defines them. + st_values are only used in this way so that the associated GOT entry + can store a Quickstart value without losing the original stub + address. */ + if (dso->ehdr.e_machine == EM_MIPS + && sym->st_shndx == SHN_UNDEF + && sym->st_value != 0) + return 1; + + return (sym->st_shndx > SHN_UNDEF + && sym->st_shndx < dso->ehdr.e_shnum + && ELF32_ST_TYPE (sym->st_info) != STT_TLS + && RELOCATE_SCN (dso->shdr[sym->st_shndx].sh_flags)); +} + +static int +adjust_symtab (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Sym sym; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getsym (dso->elf, data, ndx, &sym); + if (adjust_symbol_p (dso, &sym) && sym.st_value >= start) + { + sym.st_value += adjust; + gelfx_update_sym (dso->elf, data, ndx, &sym); + } + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +int +dso_is_rdwr (DSO *dso) +{ + return dso->elfro != NULL; +} + +GElf_Addr +adjust_old_to_new (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start) + { + addr += dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +GElf_Addr +adjust_new_to_old (DSO *dso, GElf_Addr addr) +{ + int i; + + if (dso->adjust == NULL) + return addr; /* Fast path. */ + + for (i = 0; i < dso->nadjust; i++) + if (addr >= dso->adjust[i].start + dso->adjust[i].adjust) + { + addr -= dso->adjust[i].adjust; + assert (dso->ehdr.e_ident[EI_CLASS] != ELFCLASS32 + || addr == (Elf32_Addr) addr); + return addr; + } + + return addr; +} + +static int +adjust_dynamic (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Dyn dyn; + int ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + if (dso->arch->adjust_dyn (dso, n, &dyn, start, adjust) == 0) + switch (dyn.d_tag) + { + case DT_REL: + case DT_RELA: + /* On some arches DT_REL* may be 0 indicating no relocations + (if DT_REL*SZ is also 0). Don't adjust it in that case. */ + if (dyn.d_un.d_ptr && dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + default: + if (dyn.d_tag < DT_ADDRRNGLO || dyn.d_tag > DT_ADDRRNGHI) + break; + /* FALLTHROUGH */ + case DT_INIT: + case DT_FINI: + case DT_HASH: + case DT_STRTAB: + case DT_SYMTAB: + case DT_JMPREL: + case DT_INIT_ARRAY: + case DT_FINI_ARRAY: + case DT_PREINIT_ARRAY: + case DT_VERDEF: + case DT_VERNEED: + case DT_VERSYM: + case DT_PLTGOT: + if (dyn.d_un.d_ptr >= start) + { + dyn.d_un.d_ptr += adjust; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + break; + } + else + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + + /* Update the cached dynamic info as well. */ + read_dynamic (dso); + return 0; +} + +int +addr_to_sec (DSO *dso, GElf_Addr addr) +{ + GElf_Shdr *shdr; + int i; + + shdr = &dso->shdr[dso->lastscn]; + for (i = -1; i < dso->ehdr.e_shnum; shdr = &dso->shdr[++i]) + if (RELOCATE_SCN (shdr->sh_flags) + && shdr->sh_addr <= addr && shdr->sh_addr + shdr->sh_size > addr + && (shdr->sh_type != SHT_NOBITS || (shdr->sh_flags & SHF_TLS) == 0)) + { + if (i != -1) + dso->lastscn = i; + return dso->lastscn; + } + + return -1; +} + +static int +adjust_rel (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rel (dso, &rel, start, adjust); + addr_adjust (rel.r_offset, start, adjust); + gelfx_update_rel (dso->elf, data, ndx, &rel); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +static int +adjust_rela (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec, ndx, maxndx; + + while ((data = elf_getdata (scn, data)) != NULL) + { + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + dso->arch->adjust_rela (dso, &rela, start, adjust); + addr_adjust (rela.r_offset, start, adjust); + gelfx_update_rela (dso->elf, data, ndx, &rela); + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} + +int +adjust_nonalloc (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int first, + GElf_Addr start, GElf_Addr adjust) +{ + int i; + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if ((shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + && (adjust & (shdr[i].sh_addralign - 1))) + adjust = (adjust + shdr[i].sh_addralign - 1) + & ~(shdr[i].sh_addralign - 1); + } + + if (ehdr->e_shoff >= start) + { + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + + if (adjust & (shdralign - 1)) + adjust = (adjust + shdralign - 1) & ~(shdralign - 1); + ehdr->e_shoff += adjust; + } + + for (i = 1; i < ehdr->e_shnum; i++) + { + if (RELOCATE_SCN (shdr[i].sh_flags) || shdr[i].sh_type == SHT_NULL) + continue; + + if (shdr[i].sh_offset > start + || (shdr[i].sh_offset == start && i >= first)) + shdr[i].sh_offset += adjust; + } + return 0; +} + +int +adjust_dso_nonalloc (DSO *dso, int first, GElf_Addr start, GElf_Addr adjust) +{ + return adjust_nonalloc (dso, &dso->ehdr, dso->shdr, first, start, adjust); +} + +/* Add ADJUST to all addresses above START. */ +int +adjust_dso (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + int i; + + if (dso->arch->arch_adjust + && dso->arch->arch_adjust (dso, start, adjust)) + return 1; + + if (dso->ehdr.e_entry >= start) + { + dso->ehdr.e_entry += adjust; + gelf_update_ehdr (dso->elf, &dso->ehdr); + elf_flagehdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + } + + for (i = 0; i < dso->ehdr.e_phnum; i++) + { + /* Leave STACK segment alone, it has + p_vaddr == p_paddr == p_offset == p_filesz == p_memsz == 0. */ + if (dso->phdr[i].p_type == PT_GNU_STACK) + continue; + if (! start) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + } + else if (start <= dso->phdr[i].p_vaddr) + { + dso->phdr[i].p_vaddr += adjust; + dso->phdr[i].p_paddr += adjust; + dso->phdr[i].p_offset += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz) + { + dso->phdr[i].p_filesz += adjust; + dso->phdr[i].p_memsz += adjust; + } + else if (start < dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + dso->phdr[i].p_memsz += adjust; + else + continue; + if (dso->phdr[i].p_type == PT_LOAD + && (dso->phdr[i].p_vaddr - dso->phdr[i].p_offset) + % dso->phdr[i].p_align) + { + error (0, 0, "%s: PT_LOAD %08llx %08llx 0x%x would be not properly aligned", + dso->filename, (long long) dso->phdr[i].p_offset, + (long long) dso->phdr[i].p_vaddr, (int) dso->phdr[i].p_align); + return 1; + } + gelf_update_phdr (dso->elf, i, dso->phdr + i); + } + elf_flagphdr (dso->elf, ELF_C_SET, ELF_F_DIRTY); + + for (i = 1; i < dso->ehdr.e_shnum; i++) + { + const char *name; + + if (dso->arch->adjust_section) + { + int ret = dso->arch->adjust_section (dso, i, start, adjust); + + if (ret == 1) + return 1; + else if (ret) + continue; + } + switch (dso->shdr[i].sh_type) + { + case SHT_PROGBITS: + name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (strcmp (name, ".stab") == 0 + && adjust_stabs (dso, i, start, adjust)) + return 1; + if (strcmp (name, ".debug_info") == 0 + && adjust_dwarf2 (dso, i, start, adjust)) + return 1; + break; + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_NOBITS: + case SHT_STRTAB: + break; + case SHT_SYMTAB: + case SHT_DYNSYM: + if (adjust_symtab (dso, i, start, adjust)) + return 1; + break; + case SHT_DYNAMIC: + if (adjust_dynamic (dso, i, start, adjust)) + return 1; + break; + case SHT_REL: + /* Don't adjust reloc sections for debug info. */ + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rel (dso, i, start, adjust)) + return 1; + break; + case SHT_RELA: + if (dso->shdr[i].sh_flags & SHF_ALLOC) + if (adjust_rela (dso, i, start, adjust)) + return 1; + break; + } + if ((dso->arch->machine == EM_ALPHA + && dso->shdr[i].sh_type == SHT_ALPHA_DEBUG) + || (dso->arch->machine == EM_MIPS + && dso->shdr[i].sh_type == SHT_MIPS_DEBUG)) + if (adjust_mdebug (dso, i, start, adjust)) + return 1; + } + + for (i = 0; i < dso->ehdr.e_shnum; i++) + { + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_addr >= start) + { + Elf_Scn *scn = dso->scn[i]; + + dso->shdr[i].sh_addr += adjust; + if (start) + dso->shdr[i].sh_offset += adjust; + gelfx_update_shdr (dso->elf, scn, dso->shdr + i); + elf_flagshdr (scn, ELF_C_SET, ELF_F_DIRTY); + } + } + } + + addr_adjust (dso->base, start, adjust); + addr_adjust (dso->end, start, adjust); + + if (start) + { + start = adjust_new_to_old (dso, start); + for (i = 0; i < dso->nadjust; i++) + if (start < dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + break; + if (i < dso->nadjust && start == dso->adjust[i].start) + dso->adjust[i].adjust += adjust; + else + { + dso->adjust = + realloc (dso->adjust, (dso->nadjust + 1) * sizeof (*dso->adjust)); + if (dso->adjust == NULL) + { + error (0, ENOMEM, "Cannot record the list of adjustements being made"); + return 1; + } + memmove (dso->adjust + i + 1, dso->adjust + i, dso->nadjust - i); + dso->adjust[i].start = start; + dso->adjust[i].adjust = adjust; + ++dso->nadjust; + } + } + + return start ? adjust_dso_nonalloc (dso, 0, 0, adjust) : 0; +} + +int +recompute_nonalloc_offsets (DSO *dso) +{ + int i, first_nonalloc, sec_before_shoff = 0; + GElf_Addr last_offset = 0; + GElf_Addr shdralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + GElf_Addr shdrsize = gelf_fsize (dso->elf, ELF_T_SHDR, 1, EV_CURRENT) + * dso->ehdr.e_shnum; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (RELOCATE_SCN (dso->shdr[i].sh_flags)) + { + if (dso->shdr[i].sh_type == SHT_NOBITS) + last_offset = dso->shdr[i].sh_offset; + else + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + } + else + break; + + first_nonalloc = i; + if (dso->ehdr.e_shoff < dso->shdr[i].sh_offset) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + else + for (; i < dso->ehdr.e_shnum; ++i) + if (dso->shdr[i].sh_offset < dso->ehdr.e_shoff + && (i == dso->ehdr.e_shnum - 1 + || dso->shdr[i + 1].sh_offset > dso->ehdr.e_shoff)) + { + sec_before_shoff = i; + break; + } + + for (i = first_nonalloc; i < dso->ehdr.e_shnum; ++i) + { + assert (!RELOCATE_SCN (dso->shdr[i].sh_flags)); + assert (dso->shdr[i].sh_type != SHT_NOBITS); + dso->shdr[i].sh_offset = (last_offset + dso->shdr[i].sh_addralign - 1) + & ~(dso->shdr[i].sh_addralign - 1); + last_offset = dso->shdr[i].sh_offset + dso->shdr[i].sh_size; + if (i == sec_before_shoff) + { + dso->ehdr.e_shoff = (last_offset + shdralign - 1) & ~(shdralign - 1); + last_offset = dso->ehdr.e_shoff + shdrsize; + } + } + + return 0; +} + +int +strtabfind (DSO *dso, int strndx, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + const char *p, *q, *r; + size_t len = strlen (name); + + if (dso->shdr[strndx].sh_type != SHT_STRTAB) + return 0; + + scn = dso->scn[strndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[strndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + return 0; +} + +int +shstrtabadd (DSO *dso, const char *name) +{ + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr adjust; + const char *p, *q, *r; + size_t len = strlen (name), align; + int ret; + + scn = dso->scn[dso->ehdr.e_shstrndx]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[dso->ehdr.e_shstrndx].sh_size); + q = data->d_buf + data->d_size; + for (p = data->d_buf; p < q; p = r + 1) + { + r = strchr (p, '\0'); + if (r - p >= len && memcmp (r - len, name, len) == 0) + return (r - (const char *) data->d_buf) - len; + } + + data->d_buf = realloc (data->d_buf, data->d_size + len + 1); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "Cannot add new section name %s", name); + return 0; + } + + memcpy (data->d_buf + data->d_size, name, len + 1); + ret = data->d_size; + data->d_size += len + 1; + align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + adjust = (len + 1 + align - 1) & ~(align - 1); + if (adjust_dso_nonalloc (dso, 0, + dso->shdr[dso->ehdr.e_shstrndx].sh_offset + + dso->shdr[dso->ehdr.e_shstrndx].sh_size, + adjust)) + return 0; + dso->shdr[dso->ehdr.e_shstrndx].sh_size += len + 1; + return ret; +} + +int +relocate_dso (DSO *dso, GElf_Addr base) +{ + /* Check if it is already relocated. */ + if (dso->base == base) + return 0; + + if (! dso_is_rdwr (dso)) + { + if (reopen_dso (dso, NULL, NULL)) + return 1; + } + + return adjust_dso (dso, 0, base - dso->base); +} + +static int +close_dso_1 (DSO *dso) +{ + if (dso_is_rdwr (dso)) + { + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + Elf_Scn *scn = dso->scn[i]; + Elf_Data *data = NULL; + + while ((data = elf_getdata (scn, data)) != NULL) + { + free (data->d_buf); + data->d_buf = NULL; + } + } + } + + elf_end (dso->elf); + close (dso->fd); + if (dso->elfro) + { + elf_end (dso->elfro); + close (dso->fdro); + } + if (dso->filename != dso->soname) + free ((char *) dso->soname); + free ((char *) dso->filename); + free ((char *) dso->temp_filename); + free (dso->move); + free (dso->adjust); + free (dso->undo.d_buf); + free (dso); + return 0; +} + +int +close_dso (DSO *dso) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr && dso->temp_filename != NULL) + wrap_unlink (dso->temp_filename); + close_dso_1 (dso); + return 0; +} + +int +prepare_write_dso (DSO *dso) +{ + int i; + + if (check_dso (dso) + || (dso->mdebug_orig_offset && finalize_mdebug (dso))) + return 1; + + gelf_update_ehdr (dso->elf, &dso->ehdr); + for (i = 0; i < dso->ehdr.e_phnum; ++i) + gelf_update_phdr (dso->elf, i, dso->phdr + i); + for (i = 0; i < dso->ehdr.e_shnum; ++i) + { + gelfx_update_shdr (dso->elf, dso->scn[i], dso->shdr + i); + if (dso->shdr[i].sh_type == SHT_SYMTAB + || dso->shdr[i].sh_type == SHT_DYNSYM) + set_stt_section_values (dso, i); + } + return 0; +} + +int +write_dso (DSO *dso) +{ + if (prepare_write_dso (dso)) + return 1; + + if (! dso->permissive && ELF_F_PERMISSIVE) + elf_flagelf (dso->elf, ELF_C_CLR, ELF_F_PERMISSIVE); + + if (elf_update (dso->elf, ELF_C_WRITE) == -1) + return 2; + return 0; +} + +int +set_security_context (DSO *dso, const char *temp_name, const char *name) +{ +#ifdef USE_SELINUX + static int selinux_enabled = -1; + if (selinux_enabled == -1) + selinux_enabled = is_selinux_enabled (); + if (selinux_enabled > 0) + { + security_context_t scontext; + if (getfilecon (name, &scontext) < 0) + { + /* If the filesystem doesn't support extended attributes, + the original had no special security context and the + target cannot have one either. */ + if (errno == EOPNOTSUPP) + return 0; + + error (0, errno, "Could not get security context for %s", + name); + return 1; + } + if (setfilecon (temp_name, scontext) < 0) + { + error (0, errno, "Could not set security context for %s", + name); + freecon (scontext); + return 1; + } + freecon (scontext); + } +#endif + return 0; +} + +int +update_dso (DSO *dso, const char *orig_name) +{ + int rdwr = dso_is_rdwr (dso); + + if (rdwr) + { + char *name1, *name2; + struct utimbuf u; + struct stat64 st; + + switch (write_dso (dso)) + { + case 2: + error (0, 0, "Could not write %s: %s", dso->filename, + elf_errmsg (-1)); + /* FALLTHROUGH */ + case 1: + close_dso (dso); + return 1; + case 0: + break; + } + + name1 = strdupa (dso->filename); + name2 = strdupa (dso->temp_filename); + if (fstat64 (dso->fdro, &st) < 0) + { + error (0, errno, "Could not stat %s", dso->filename); + close_dso (dso); + return 1; + } + if (fchown (dso->fd, st.st_uid, st.st_gid) < 0 + || fchmod (dso->fd, st.st_mode & 07777) < 0) + { + error (0, errno, "Could not set %s owner or mode", dso->filename); + close_dso (dso); + return 1; + } + close_dso_1 (dso); + u.actime = time (NULL); + u.modtime = st.st_mtime; + wrap_utime (name2, &u); + + if (set_security_context (dso, name2, orig_name ? orig_name : name1)) + { + wrap_unlink (name2); + return 1; + } + + if (wrap_rename (name2, name1)) + { + wrap_unlink (name2); + error (0, errno, "Could not rename temporary to %s", name1); + return 1; + } + } + else + close_dso_1 (dso); + + return 0; +} diff --git a/trunk/src/dwarf2.c b/trunk/src/dwarf2.c new file mode 100644 index 0000000..4c27836 --- /dev/null +++ b/trunk/src/dwarf2.c @@ -0,0 +1,1148 @@ +/* Copyright (C) 2001, 2002, 2003, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <byteswap.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <limits.h> +#include <string.h> +#include <sys/types.h> + +#include "dwarf2.h" +#include "hashtab.h" +#include "prelink.h" + +#define read_uleb128(ptr) ({ \ + unsigned int ret = 0; \ + unsigned int c; \ + int shift = 0; \ + do \ + { \ + c = *ptr++; \ + ret |= (c & 0x7f) << shift; \ + shift += 7; \ + } while (c & 0x80); \ + \ + if (shift >= 35) \ + ret = UINT_MAX; \ + ret; \ +}) + +static uint16_t (*do_read_16) (unsigned char *ptr); +static uint32_t (*do_read_32) (unsigned char *ptr); +static uint64_t (*do_read_32_64) (unsigned char *ptr); +static uint64_t (*do_read_64) (unsigned char *ptr); +static uint64_t (*do_read_ptr) (unsigned char *ptr); +static void (*write_32) (unsigned char *ptr, GElf_Addr val); +static void (*write_64) (unsigned char *ptr, GElf_Addr val); +static void (*write_ptr) (unsigned char *ptr, GElf_Addr val); + +static int ptr_size; + +#define read_1(ptr) *ptr++ + +#define read_16(ptr) ({ \ + uint16_t ret = do_read_16 (ptr); \ + ptr += 2; \ + ret; \ +}) + +#define read_32(ptr) ({ \ + uint32_t ret = do_read_32 (ptr); \ + ptr += 4; \ + ret; \ +}) + +#define read_64(ptr) ({ \ + uint64_t ret = do_read_64 (ptr); \ + ptr += 8; \ + ret; \ +}) + +#define read_ptr(ptr) ({ \ + uint64_t ret = do_read_ptr (ptr); \ + ptr += ptr_size; \ + ret; \ +}) + +static uint64_t +buf_read_ule32_64 (unsigned char *p) +{ + return buf_read_ule32 (p); +} + +static uint64_t +buf_read_ube32_64 (unsigned char *p) +{ + return buf_read_ube32 (p); +} + +static void +dwarf2_write_le32 (unsigned char *p, GElf_Addr val) +{ + uint32_t v = (uint32_t) val; + + p[0] = v; + p[1] = v >> 8; + p[2] = v >> 16; + p[3] = v >> 24; +} + +static void +dwarf2_write_le64 (unsigned char *p, GElf_Addr val) +{ + p[0] = val; + p[1] = val >> 8; + p[2] = val >> 16; + p[3] = val >> 24; + p[4] = val >> 32; + p[5] = val >> 40; + p[6] = val >> 48; + p[7] = val >> 58; +} + +static void +dwarf2_write_be32 (unsigned char *p, GElf_Addr val) +{ + uint32_t v = (uint32_t) val; + + p[3] = v; + p[2] = v >> 8; + p[1] = v >> 16; + p[0] = v >> 24; +} + +static void +dwarf2_write_be64 (unsigned char *p, GElf_Addr val) +{ + p[7] = val; + p[6] = val >> 8; + p[5] = val >> 16; + p[4] = val >> 24; + p[3] = val >> 32; + p[2] = val >> 40; + p[1] = val >> 48; + p[0] = val >> 58; +} + +static struct + { + const char *name; + unsigned char *data; + size_t size; + int sec; + } debug_sections[] = + { +#define DEBUG_INFO 0 +#define DEBUG_ABBREV 1 +#define DEBUG_LINE 2 +#define DEBUG_ARANGES 3 +#define DEBUG_PUBNAMES 4 +#define DEBUG_MACINFO 5 +#define DEBUG_LOC 6 +#define DEBUG_STR 7 +#define DEBUG_FRAME 8 +#define DEBUG_RANGES 9 + { ".debug_info", NULL, 0, 0 }, + { ".debug_abbrev", NULL, 0, 0 }, + { ".debug_line", NULL, 0, 0 }, + { ".debug_aranges", NULL, 0, 0 }, + { ".debug_pubnames", NULL, 0, 0 }, + { ".debug_macinfo", NULL, 0, 0 }, + { ".debug_loc", NULL, 0, 0 }, + { ".debug_str", NULL, 0, 0 }, + { ".debug_frame", NULL, 0, 0 }, + { ".debug_ranges", NULL, 0, 0 }, + { NULL, NULL, 0 } + }; + +struct abbrev_attr + { + unsigned int attr; + unsigned int form; + }; + +struct abbrev_tag + { + unsigned int entry; + unsigned int tag; + int nattr; + struct abbrev_attr attr[0]; + }; + +struct cu_data + { + GElf_Addr cu_entry_pc; + GElf_Addr cu_low_pc; + }; + +static hashval_t +abbrev_hash (const void *p) +{ + struct abbrev_tag *t = (struct abbrev_tag *)p; + + return t->entry; +} + +static int +abbrev_eq (const void *p, const void *q) +{ + struct abbrev_tag *t1 = (struct abbrev_tag *)p; + struct abbrev_tag *t2 = (struct abbrev_tag *)q; + + return t1->entry == t2->entry; +} + +static void +abbrev_del (void *p) +{ + free (p); +} + +static htab_t +read_abbrev (DSO *dso, unsigned char *ptr) +{ + htab_t h = htab_try_create (50, abbrev_hash, abbrev_eq, abbrev_del); + unsigned int attr, form; + struct abbrev_tag *t; + int size; + void **slot; + + if (h == NULL) + { +no_memory: + error (0, ENOMEM, "%s: Could not read .debug_abbrev", dso->filename); + if (h) + htab_delete (h); + return NULL; + } + + while ((attr = read_uleb128 (ptr)) != 0) + { + size = 10; + t = malloc (sizeof (*t) + size * sizeof (struct abbrev_attr)); + if (t == NULL) + goto no_memory; + t->entry = attr; + t->nattr = 0; + slot = htab_find_slot (h, t, INSERT); + if (slot == NULL) + { + free (t); + goto no_memory; + } + if (*slot != NULL) + { + error (0, 0, "%s: Duplicate DWARF-2 abbreviation %d", dso->filename, + t->entry); + free (t); + htab_delete (h); + return NULL; + } + t->tag = read_uleb128 (ptr); + ++ptr; /* skip children flag. */ + while ((attr = read_uleb128 (ptr)) != 0) + { + if (t->nattr == size) + { + size += 10; + t = realloc (t, sizeof (*t) + size * sizeof (struct abbrev_attr)); + if (t == NULL) + goto no_memory; + } + form = read_uleb128 (ptr); + if (form == 2 || form > DW_FORM_indirect) + { + error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename, form); + htab_delete (h); + return NULL; + } + + t->attr[t->nattr].attr = attr; + t->attr[t->nattr++].form = form; + } + if (read_uleb128 (ptr) != 0) + { + error (0, 0, "%s: DWARF-2 abbreviation does not end with 2 zeros", + dso->filename); + htab_delete (h); + return NULL; + } + *slot = t; + } + + return h; +} + +static int +adjust_location_list (DSO *dso, unsigned char *ptr, size_t len, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *end = ptr + len; + unsigned char op; + GElf_Addr addr; + + while (ptr < end) + { + op = *ptr++; + switch (op) + { + case DW_OP_addr: + addr = read_ptr (ptr); + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - ptr_size, addr + adjust); + break; + case DW_OP_deref: + case DW_OP_dup: + case DW_OP_drop: + case DW_OP_over: + case DW_OP_swap: + case DW_OP_rot: + case DW_OP_xderef: + case DW_OP_abs: + case DW_OP_and: + case DW_OP_div: + case DW_OP_minus: + case DW_OP_mod: + case DW_OP_mul: + case DW_OP_neg: + case DW_OP_not: + case DW_OP_or: + case DW_OP_plus: + case DW_OP_shl: + case DW_OP_shr: + case DW_OP_shra: + case DW_OP_xor: + case DW_OP_eq: + case DW_OP_ge: + case DW_OP_gt: + case DW_OP_le: + case DW_OP_lt: + case DW_OP_ne: + case DW_OP_lit0 ... DW_OP_lit31: + case DW_OP_reg0 ... DW_OP_reg31: + case DW_OP_nop: + case DW_OP_push_object_address: + case DW_OP_call_ref: + case DW_OP_GNU_push_tls_address: + break; + case DW_OP_const1u: + case DW_OP_pick: + case DW_OP_deref_size: + case DW_OP_xderef_size: + case DW_OP_const1s: + ++ptr; + break; + case DW_OP_const2u: + case DW_OP_const2s: + case DW_OP_skip: + case DW_OP_bra: + case DW_OP_call2: + ptr += 2; + break; + case DW_OP_const4u: + case DW_OP_const4s: + case DW_OP_call4: + ptr += 4; + break; + case DW_OP_const8u: + case DW_OP_const8s: + ptr += 8; + break; + case DW_OP_constu: + case DW_OP_plus_uconst: + case DW_OP_regx: + case DW_OP_piece: + case DW_OP_consts: + case DW_OP_breg0 ... DW_OP_breg31: + case DW_OP_fbreg: + read_uleb128 (ptr); + break; + case DW_OP_bregx: + read_uleb128 (ptr); + read_uleb128 (ptr); + break; + default: + error (0, 0, "%s: Unknown DWARF-2 DW_OP_%d", dso->filename, op); + return 1; + } + } + return 0; +} + +static int +adjust_dwarf2_ranges (DSO *dso, GElf_Addr offset, GElf_Addr base, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *ptr, *endsec; + GElf_Addr low, high; + int adjusted_base; + + ptr = debug_sections[DEBUG_RANGES].data; + if (ptr == NULL) + { + error (0, 0, "%s: DW_AT_ranges attribute, yet no .debug_ranges section", + dso->filename); + return 1; + } + if (offset >= debug_sections[DEBUG_RANGES].size) + { + error (0, 0, + "%s: DW_AT_ranges offset %Ld outside of .debug_ranges section", + dso->filename, (long long) offset); + return 1; + } + endsec = ptr + debug_sections[DEBUG_RANGES].size; + ptr += offset; + adjusted_base = (base && base >= start && addr_to_sec (dso, base) != -1); + while (ptr < endsec) + { + low = read_ptr (ptr); + high = read_ptr (ptr); + if (low == 0 && high == 0) + break; + + if (low == ~ (GElf_Addr) 0 || (ptr_size == 4 && low == 0xffffffff)) + { + base = high; + adjusted_base = (base && base >= start + && addr_to_sec (dso, base) != -1); + if (adjusted_base) + write_ptr (ptr - ptr_size, base + adjust); + } + else if (! adjusted_base) + { + if (base + low >= start && addr_to_sec (dso, base + low) != -1) + { + write_ptr (ptr - 2 * ptr_size, low + adjust); + if (high == low) + write_ptr (ptr - ptr_size, high + adjust); + } + if (low != high && base + high >= start + && addr_to_sec (dso, base + high - 1) != -1) + write_ptr (ptr - ptr_size, high + adjust); + } + } + + elf_flagscn (dso->scn[debug_sections[DEBUG_RANGES].sec], ELF_C_SET, + ELF_F_DIRTY); + return 0; +} + +static int +adjust_dwarf2_loc (DSO *dso, GElf_Addr offset, GElf_Addr base, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *ptr, *endsec; + GElf_Addr low, high; + int adjusted_base; + size_t len; + + ptr = debug_sections[DEBUG_LOC].data; + if (ptr == NULL) + { + error (0, 0, "%s: loclistptr attribute, yet no .debug_loc section", + dso->filename); + return 1; + } + if (offset >= debug_sections[DEBUG_LOC].size) + { + error (0, 0, + "%s: loclistptr offset %Ld outside of .debug_loc section", + dso->filename, (long long) offset); + return 1; + } + endsec = ptr + debug_sections[DEBUG_LOC].size; + ptr += offset; + adjusted_base = (base && base >= start && addr_to_sec (dso, base) != -1); + while (ptr < endsec) + { + low = read_ptr (ptr); + high = read_ptr (ptr); + if (low == 0 && high == 0) + break; + + if (low == ~ (GElf_Addr) 0 || (ptr_size == 4 && low == 0xffffffff)) + { + base = high; + adjusted_base = (base && base >= start + && addr_to_sec (dso, base) != -1); + if (adjusted_base) + write_ptr (ptr - ptr_size, base + adjust); + continue; + } + len = read_16 (ptr); + assert (ptr + len <= endsec); + + if (adjust_location_list (dso, ptr, len, start, adjust)) + return 1; + + ptr += len; + } + + elf_flagscn (dso->scn[debug_sections[DEBUG_LOC].sec], ELF_C_SET, + ELF_F_DIRTY); + return 0; +} + +static unsigned char * +adjust_attributes (DSO *dso, unsigned char *ptr, struct abbrev_tag *t, + struct cu_data *cu, + GElf_Addr start, GElf_Addr adjust) +{ + int i; + GElf_Addr addr; + + for (i = 0; i < t->nattr; ++i) + { + uint32_t form = t->attr[i].form; + uint32_t len = 0; + + while (1) + { + switch (t->attr[i].attr) + { + case DW_AT_location: + case DW_AT_string_length: + case DW_AT_return_addr: + case DW_AT_data_member_location: + case DW_AT_frame_base: + case DW_AT_static_link: + case DW_AT_use_location: + case DW_AT_vtable_elem_location: + case DW_AT_ranges: + if (form == DW_FORM_data4) + addr = read_32 (ptr), ptr -= 4; + else if (form == DW_FORM_data8) + addr = read_64 (ptr), ptr -= 8; + else + break; + { + GElf_Addr base; + + if (cu->cu_entry_pc != ~ (GElf_Addr) 0) + base = cu->cu_entry_pc; + else if (cu->cu_low_pc != ~ (GElf_Addr) 0) + base = cu->cu_low_pc; + else + base = 0; + if (t->attr[i].attr == DW_AT_ranges) + { + if (adjust_dwarf2_ranges (dso, addr, base, start, adjust)) + return NULL; + } + else + { + if (adjust_dwarf2_loc (dso, addr, base, start, adjust)) + return NULL; + } + } + break; + } + switch (form) + { + case DW_FORM_addr: + addr = read_ptr (ptr); + if (t->tag == DW_TAG_compile_unit + || t->tag == DW_TAG_partial_unit) + { + if (t->attr[i].attr == DW_AT_entry_pc) + cu->cu_entry_pc = addr; + else if (t->attr[i].attr == DW_AT_low_pc) + cu->cu_low_pc = addr; + if (addr == 0) + break; + } + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - ptr_size, addr + adjust); + break; + case DW_FORM_ref1: + case DW_FORM_flag: + case DW_FORM_data1: + ++ptr; + break; + case DW_FORM_ref2: + case DW_FORM_data2: + ptr += 2; + break; + case DW_FORM_ref4: + case DW_FORM_data4: + ptr += 4; + break; + case DW_FORM_ref8: + case DW_FORM_data8: + ptr += 8; + break; + case DW_FORM_sdata: + case DW_FORM_ref_udata: + case DW_FORM_udata: + read_uleb128 (ptr); + break; + case DW_FORM_ref_addr: + case DW_FORM_strp: + ptr += 4; + break; + case DW_FORM_string: + ptr = strchr (ptr, '\0') + 1; + break; + case DW_FORM_indirect: + form = read_uleb128 (ptr); + continue; + case DW_FORM_block1: + len = *ptr++; + break; + case DW_FORM_block2: + len = read_16 (ptr); + form = DW_FORM_block1; + break; + case DW_FORM_block4: + len = read_32 (ptr); + form = DW_FORM_block1; + break; + case DW_FORM_block: + len = read_uleb128 (ptr); + form = DW_FORM_block1; + assert (len < UINT_MAX); + break; + default: + error (0, 0, "%s: Unknown DWARF-2 DW_FORM_%d", dso->filename, + form); + return NULL; + } + + if (form == DW_FORM_block1) + { + switch (t->attr[i].attr) + { + case DW_AT_frame_base: + case DW_AT_location: + case DW_AT_data_member_location: + case DW_AT_vtable_elem_location: + if (adjust_location_list (dso, ptr, len, start, adjust)) + return NULL; + break; + default: + if (t->attr[i].attr <= DW_AT_call_line + || (t->attr[i].attr >= DW_AT_MIPS_fde + && t->attr[i].attr <= DW_AT_MIPS_has_inlines) + || (t->attr[i].attr >= DW_AT_sf_names + && t->attr[i].attr <= DW_AT_body_end)) + break; + error (0, 0, "%s: Unknown DWARF-2 DW_AT_%d with block DW_FORM", + dso->filename, t->attr[i].attr); + return NULL; + } + ptr += len; + } + + break; + } + } + + return ptr; +} + +static int +adjust_dwarf2_line (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *ptr = debug_sections[DEBUG_LINE].data; + unsigned char *endsec = ptr + debug_sections[DEBUG_LINE].size; + unsigned char *endcu, *endprol; + unsigned char opcode_base, *opcode_lengths, op; + uint32_t value; + GElf_Addr addr; + int i; + + while (ptr < endsec) + { + endcu = ptr + 4; + endcu += read_32 (ptr); + if (endcu == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); + return 1; + } + + if (endcu > endsec) + { + error (0, 0, "%s: .debug_line CU does not fit into section", + dso->filename); + return 1; + } + + value = read_16 (ptr); + if (value != 2) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + value); + return 1; + } + + endprol = ptr + 4; + endprol += read_32 (ptr); + if (endprol > endcu) + { + error (0, 0, "%s: .debug_line CU prologue does not fit into CU", + dso->filename); + return 1; + } + + opcode_base = ptr[4]; + opcode_lengths = ptr + 4; + + ptr = endprol; + while (ptr < endcu) + { + op = *ptr++; + if (op >= opcode_base) + continue; + if (op == 0) + { + unsigned int len = read_uleb128 (ptr); + + assert (len < UINT_MAX); + op = *ptr++; + switch (op) + { + case DW_LNE_set_address: + addr = read_ptr (ptr); + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - ptr_size, addr + adjust); + break; + case DW_LNE_end_sequence: + case DW_LNE_define_file: + default: + ptr += len - 1; + break; + } + } + else if (op == DW_LNS_fixed_advance_pc) + ptr += 2; + else + for (i = 0; i < opcode_lengths[op]; ++i) + read_uleb128 (ptr); + } + } + + elf_flagscn (dso->scn[debug_sections[DEBUG_LINE].sec], ELF_C_SET, + ELF_F_DIRTY); + return 0; +} + +static int +adjust_dwarf2_aranges (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *ptr = debug_sections[DEBUG_ARANGES].data; + unsigned char *endsec = ptr + debug_sections[DEBUG_ARANGES].size; + unsigned char *endcu; + GElf_Addr addr, len; + uint32_t value; + + while (ptr < endsec) + { + endcu = ptr + 4; + endcu += read_32 (ptr); + if (endcu == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); + return 1; + } + + if (endcu > endsec) + { + error (0, 0, "%s: .debug_line CU does not fit into section", + dso->filename); + return 1; + } + + value = read_16 (ptr); + if (value != 2) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + value); + return 1; + } + + ptr += 4; + if (ptr[0] != ptr_size || ptr[1]) + { + error (0, 0, "%s: Unsupported .debug_aranges address size %d or segment size %d", + dso->filename, ptr[0], ptr[1]); + return 1; + } + + ptr += 6; + while (ptr < endcu) + { + addr = read_ptr (ptr); + len = read_ptr (ptr); + if (addr == 0 && len == 0) + break; + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - 2 * ptr_size, addr + adjust); + } + assert (ptr == endcu); + } + + elf_flagscn (dso->scn[debug_sections[DEBUG_LINE].sec], ELF_C_SET, + ELF_F_DIRTY); + return 0; +} + +static int +adjust_dwarf2_frame (DSO *dso, GElf_Addr start, GElf_Addr adjust) +{ + unsigned char *ptr = debug_sections[DEBUG_FRAME].data; + unsigned char *endsec = ptr + debug_sections[DEBUG_FRAME].size; + unsigned char *endie; + GElf_Addr addr, len; + uint32_t value; + + while (ptr < endsec) + { + endie = ptr + 4; + endie += read_32 (ptr); + if (endie == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); + return 1; + } + + if (endie > endsec) + { + error (0, 0, "%s: .debug_frame CIE/FDE does not fit into section", + dso->filename); + return 1; + } + + value = read_32 (ptr); + if (value == 0xffffffff) + { + /* CIE. */ + ptr++; /* Skip version. */ + if (*ptr != '\0') + { + error (0, 0, "%s: .debug_frame unhandled augmentation \"%s\"", + dso->filename, ptr); + return 1; + } + ptr++; /* Skip augmentation. */ + read_uleb128 (ptr); /* Skip code_alignment factor. */ + read_uleb128 (ptr); /* Skip data_alignment factor. */ + read_uleb128 (ptr); /* Skip return_address_register. */ + } + else + { + addr = read_ptr (ptr); + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - ptr_size, addr + adjust); + read_ptr (ptr); /* Skip address range. */ + } + + while (ptr < endie) + { + unsigned char insn = *ptr++; + + if ((insn & 0xc0) == DW_CFA_advance_loc + || (insn & 0xc0) == DW_CFA_restore) + continue; + else if ((insn & 0xc0) == DW_CFA_offset) + { + read_uleb128 (ptr); + continue; + } + switch (insn) + { + case DW_CFA_nop: + case DW_CFA_remember_state: + case DW_CFA_restore_state: + case DW_CFA_GNU_window_save: + break; + case DW_CFA_offset_extended: + case DW_CFA_register: + case DW_CFA_def_cfa: + case DW_CFA_offset_extended_sf: + case DW_CFA_def_cfa_sf: + case DW_CFA_GNU_negative_offset_extended: + read_uleb128 (ptr); + /* FALLTHROUGH */ + case DW_CFA_restore_extended: + case DW_CFA_undefined: + case DW_CFA_same_value: + case DW_CFA_def_cfa_register: + case DW_CFA_def_cfa_offset: + case DW_CFA_def_cfa_offset_sf: + case DW_CFA_GNU_args_size: + read_uleb128 (ptr); + break; + case DW_CFA_set_loc: + addr = read_ptr (ptr); + if (addr >= start && addr_to_sec (dso, addr) != -1) + write_ptr (ptr - ptr_size, addr + adjust); + break; + case DW_CFA_advance_loc1: + ptr++; + break; + case DW_CFA_advance_loc2: + ptr += 2; + break; + case DW_CFA_advance_loc4: + ptr += 4; + break; + case DW_CFA_expression: + read_uleb128 (ptr); + /* FALLTHROUGH */ + case DW_CFA_def_cfa_expression: + len = read_uleb128 (ptr); + if (adjust_location_list (dso, ptr, len, start, adjust)) + return 1; + ptr += len; + break; + default: + error (0, 0, "%s: Unhandled DW_CFA_%02x operation", + dso->filename, insn); + return 1; + } + } + } + + elf_flagscn (dso->scn[debug_sections[DEBUG_FRAME].sec], ELF_C_SET, + ELF_F_DIRTY); + return 0; +} + +int +adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data; + Elf_Scn *scn; + int i, j; + struct cu_data cu; + + for (i = 0; debug_sections[i].name; ++i) + { + debug_sections[i].data = NULL; + debug_sections[i].size = 0; + debug_sections[i].sec = 0; + } + ptr_size = 0; + + memset (&cu, 0, sizeof(cu)); + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (! (dso->shdr[i].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR)) + && dso->shdr[i].sh_size) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name); + + if (strncmp (name, ".debug_", sizeof (".debug_") - 1) == 0) + { + for (j = 0; debug_sections[j].name; ++j) + if (strcmp (name, debug_sections[j].name) == 0) + { + if (debug_sections[j].data) + { + error (0, 0, "%s: Found two copies of %s section", + dso->filename, name); + return 1; + } + + scn = dso->scn[i]; + data = elf_getdata (scn, NULL); + assert (data != NULL && data->d_buf != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[i].sh_size); + debug_sections[j].data = data->d_buf; + debug_sections[j].size = data->d_size; + debug_sections[j].sec = i; + break; + } + + if (debug_sections[j].name == NULL) + { + error (0, 0, "%s: Unknown debugging section %s", + dso->filename, name); + } + } + } + + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + { + do_read_16 = buf_read_ule16; + do_read_32 = buf_read_ule32; + do_read_32_64 = buf_read_ule32_64; + do_read_64 = buf_read_ule64; + write_32 = dwarf2_write_le32; + write_64 = dwarf2_write_le64; + } + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) + { + do_read_16 = buf_read_ube16; + do_read_32 = buf_read_ube32; + do_read_32_64 = buf_read_ube32_64; + do_read_64 = buf_read_ube64; + write_32 = dwarf2_write_be32; + write_64 = dwarf2_write_be64; + } + else + { + error (0, 0, "%s: Wrong ELF data enconding", dso->filename); + return 1; + } + + if (debug_sections[DEBUG_INFO].data != NULL) + { + unsigned char *ptr, *endcu, *endsec; + uint32_t value; + htab_t abbrev; + struct abbrev_tag tag, *t; + + ptr = debug_sections[DEBUG_INFO].data; + endsec = ptr + debug_sections[DEBUG_INFO].size; + while (ptr < endsec) + { + if (ptr + 11 > endsec) + { + error (0, 0, "%s: .debug_info CU header too small", + dso->filename); + return 1; + } + + endcu = ptr + 4; + endcu += read_32 (ptr); + if (endcu == ptr + 0xffffffff) + { + error (0, 0, "%s: 64-bit DWARF not supported", dso->filename); + return 1; + } + + if (endcu > endsec) + { + error (0, 0, "%s: .debug_info too small", dso->filename); + return 1; + } + + value = read_16 (ptr); + if (value != 2) + { + error (0, 0, "%s: DWARF version %d unhandled", dso->filename, + value); + return 1; + } + + value = read_32 (ptr); + if (value >= debug_sections[DEBUG_ABBREV].size) + { + if (debug_sections[DEBUG_ABBREV].data == NULL) + error (0, 0, "%s: .debug_abbrev not present", dso->filename); + else + error (0, 0, "%s: DWARF-2 CU abbrev offset too large", + dso->filename); + return 1; + } + + if (ptr_size == 0) + { + ptr_size = read_1 (ptr); + if (ptr_size == 4) + { + do_read_ptr = do_read_32_64; + write_ptr = write_32; + } + else if (ptr_size == 8) + { + do_read_ptr = do_read_64; + write_ptr = write_64; + } + else + { + error (0, 0, "%s: Invalid DWARF-2 pointer size %d", + dso->filename, ptr_size); + return 1; + } + } + else if (read_1 (ptr) != ptr_size) + { + error (0, 0, "%s: DWARF-2 pointer size differs between CUs", + dso->filename); + return 1; + } + + abbrev = read_abbrev (dso, + debug_sections[DEBUG_ABBREV].data + value); + if (abbrev == NULL) + return 1; + + cu.cu_entry_pc = ~ (GElf_Addr) 0; + cu.cu_low_pc = ~ (GElf_Addr) 0; + + while (ptr < endcu) + { + tag.entry = read_uleb128 (ptr); + if (tag.entry == 0) + continue; + t = htab_find_with_hash (abbrev, &tag, tag.entry); + if (t == NULL) + { + error (0, 0, "%s: Could not find DWARF-2 abbreviation %d", + dso->filename, tag.entry); + htab_delete (abbrev); + return 1; + } + + ptr = adjust_attributes (dso, ptr, t, &cu, start, adjust); + if (ptr == NULL) + { + htab_delete (abbrev); + return 1; + } + } + + htab_delete (abbrev); + } + } + + if (ptr_size == 0) + /* Should not happen. */ + ptr_size = dso->ehdr.e_ident[EI_CLASS] == ELFCLASS64 ? 8 : 4; + + if (debug_sections[DEBUG_LINE].data != NULL + && adjust_dwarf2_line (dso, start, adjust)) + return 1; + + if (debug_sections[DEBUG_ARANGES].data != NULL + && adjust_dwarf2_aranges (dso, start, adjust)) + return 1; + + if (debug_sections[DEBUG_FRAME].data != NULL + && adjust_dwarf2_frame (dso, start, adjust)) + return 1; + + /* .debug_abbrev requires no adjustement. */ + /* .debug_pubnames requires no adjustement. */ + /* .debug_macinfo requires no adjustement. */ + /* .debug_str requires no adjustement. */ + /* .debug_ranges adjusted for each DW_AT_ranges pointing into it. */ + /* .debug_loc adjusted for each loclistptr pointing into it. */ + + elf_flagscn (dso->scn[n], ELF_C_SET, ELF_F_DIRTY); + return 0; +} diff --git a/trunk/src/dwarf2.h b/trunk/src/dwarf2.h new file mode 100644 index 0000000..1f938f5 --- /dev/null +++ b/trunk/src/dwarf2.h @@ -0,0 +1,479 @@ +/* Copyright (C) 2001, 2002 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define DW_TAG_padding 0x00 +#define DW_TAG_array_type 0x01 +#define DW_TAG_class_type 0x02 +#define DW_TAG_entry_point 0x03 +#define DW_TAG_enumeration_type 0x04 +#define DW_TAG_formal_parameter 0x05 +#define DW_TAG_imported_declaration 0x08 +#define DW_TAG_label 0x0a +#define DW_TAG_lexical_block 0x0b +#define DW_TAG_member 0x0d +#define DW_TAG_pointer_type 0x0f +#define DW_TAG_reference_type 0x10 +#define DW_TAG_compile_unit 0x11 +#define DW_TAG_string_type 0x12 +#define DW_TAG_structure_type 0x13 +#define DW_TAG_subroutine_type 0x15 +#define DW_TAG_typedef 0x16 +#define DW_TAG_union_type 0x17 +#define DW_TAG_unspecified_parameters 0x18 +#define DW_TAG_variant 0x19 +#define DW_TAG_common_block 0x1a +#define DW_TAG_common_inclusion 0x1b +#define DW_TAG_inheritance 0x1c +#define DW_TAG_inlined_subroutine 0x1d +#define DW_TAG_module 0x1e +#define DW_TAG_ptr_to_member_type 0x1f +#define DW_TAG_set_type 0x20 +#define DW_TAG_subrange_type 0x21 +#define DW_TAG_with_stmt 0x22 +#define DW_TAG_access_declaration 0x23 +#define DW_TAG_base_type 0x24 +#define DW_TAG_catch_block 0x25 +#define DW_TAG_const_type 0x26 +#define DW_TAG_constant 0x27 +#define DW_TAG_enumerator 0x28 +#define DW_TAG_file_type 0x29 +#define DW_TAG_friend 0x2a +#define DW_TAG_namelist 0x2b +#define DW_TAG_namelist_item 0x2c +#define DW_TAG_packed_type 0x2d +#define DW_TAG_subprogram 0x2e +#define DW_TAG_template_type_param 0x2f +#define DW_TAG_template_value_param 0x30 +#define DW_TAG_thrown_type 0x31 +#define DW_TAG_try_block 0x32 +#define DW_TAG_variant_part 0x33 +#define DW_TAG_variable 0x34 +#define DW_TAG_volatile_type 0x35 +#define DW_TAG_dwarf_procedure 0x36 +#define DW_TAG_restrict_type 0x37 +#define DW_TAG_interface_type 0x38 +#define DW_TAG_namespace 0x39 +#define DW_TAG_imported_module 0x3a +#define DW_TAG_unspecified_type 0x3b +#define DW_TAG_partial_unit 0x3c +#define DW_TAG_imported_unit 0x3d +#define DW_TAG_MIPS_loop 0x4081 +#define DW_TAG_format_label 0x4101 +#define DW_TAG_function_template 0x4102 +#define DW_TAG_class_template 0x4103 +#define DW_TAG_GNU_BINCL 0x4104 +#define DW_TAG_GNU_EINCL 0x4105 +#define DW_TAG_lo_user 0x4080 +#define DW_TAG_hi_user 0xffff + +#define DW_children_no 0x0 +#define DW_children_yes 0x1 + +#define DW_FORM_addr 0x01 +#define DW_FORM_block2 0x03 +#define DW_FORM_block4 0x04 +#define DW_FORM_data2 0x05 +#define DW_FORM_data4 0x06 +#define DW_FORM_data8 0x07 +#define DW_FORM_string 0x08 +#define DW_FORM_block 0x09 +#define DW_FORM_block1 0x0a +#define DW_FORM_data1 0x0b +#define DW_FORM_flag 0x0c +#define DW_FORM_sdata 0x0d +#define DW_FORM_strp 0x0e +#define DW_FORM_udata 0x0f +#define DW_FORM_ref_addr 0x10 +#define DW_FORM_ref1 0x11 +#define DW_FORM_ref2 0x12 +#define DW_FORM_ref4 0x13 +#define DW_FORM_ref8 0x14 +#define DW_FORM_ref_udata 0x15 +#define DW_FORM_indirect 0x16 + +#define DW_AT_sibling 0x01 +#define DW_AT_location 0x02 +#define DW_AT_name 0x03 +#define DW_AT_ordering 0x09 +#define DW_AT_subscr_data 0x0a +#define DW_AT_byte_size 0x0b +#define DW_AT_bit_offset 0x0c +#define DW_AT_bit_size 0x0d +#define DW_AT_element_list 0x0f +#define DW_AT_stmt_list 0x10 +#define DW_AT_low_pc 0x11 +#define DW_AT_high_pc 0x12 +#define DW_AT_language 0x13 +#define DW_AT_member 0x14 +#define DW_AT_discr 0x15 +#define DW_AT_discr_value 0x16 +#define DW_AT_visibility 0x17 +#define DW_AT_import 0x18 +#define DW_AT_string_length 0x19 +#define DW_AT_common_reference 0x1a +#define DW_AT_comp_dir 0x1b +#define DW_AT_const_value 0x1c +#define DW_AT_containing_type 0x1d +#define DW_AT_default_value 0x1e +#define DW_AT_inline 0x20 +#define DW_AT_is_optional 0x21 +#define DW_AT_lower_bound 0x22 +#define DW_AT_producer 0x25 +#define DW_AT_prototyped 0x27 +#define DW_AT_return_addr 0x2a +#define DW_AT_start_scope 0x2c +#define DW_AT_stride_size 0x2e +#define DW_AT_upper_bound 0x2f +#define DW_AT_abstract_origin 0x31 +#define DW_AT_accessibility 0x32 +#define DW_AT_address_class 0x33 +#define DW_AT_artificial 0x34 +#define DW_AT_base_types 0x35 +#define DW_AT_calling_convention 0x36 +#define DW_AT_count 0x37 +#define DW_AT_data_member_location 0x38 +#define DW_AT_decl_column 0x39 +#define DW_AT_decl_file 0x3a +#define DW_AT_decl_line 0x3b +#define DW_AT_declaration 0x3c +#define DW_AT_discr_list 0x3d +#define DW_AT_encoding 0x3e +#define DW_AT_external 0x3f +#define DW_AT_frame_base 0x40 +#define DW_AT_friend 0x41 +#define DW_AT_identifier_case 0x42 +#define DW_AT_macro_info 0x43 +#define DW_AT_namelist_items 0x44 +#define DW_AT_priority 0x45 +#define DW_AT_segment 0x46 +#define DW_AT_specification 0x47 +#define DW_AT_static_link 0x48 +#define DW_AT_type 0x49 +#define DW_AT_use_location 0x4a +#define DW_AT_variable_parameter 0x4b +#define DW_AT_virtuality 0x4c +#define DW_AT_vtable_elem_location 0x4d +#define DW_AT_allocated 0x4e +#define DW_AT_associated 0x4f +#define DW_AT_data_location 0x50 +#define DW_AT_stride 0x51 +#define DW_AT_entry_pc 0x52 +#define DW_AT_use_UTF8 0x53 +#define DW_AT_extension 0x54 +#define DW_AT_ranges 0x55 +#define DW_AT_trampoline 0x56 +#define DW_AT_call_column 0x57 +#define DW_AT_call_file 0x58 +#define DW_AT_call_line 0x59 +#define DW_AT_MIPS_fde 0x2001 +#define DW_AT_MIPS_loop_begin 0x2002 +#define DW_AT_MIPS_tail_loop_begin 0x2003 +#define DW_AT_MIPS_epilog_begin 0x2004 +#define DW_AT_MIPS_loop_unroll_factor 0x2005 +#define DW_AT_MIPS_software_pipeline_depth 0x2006 +#define DW_AT_MIPS_linkage_name 0x2007 +#define DW_AT_MIPS_stride 0x2008 +#define DW_AT_MIPS_abstract_name 0x2009 +#define DW_AT_MIPS_clone_origin 0x200a +#define DW_AT_MIPS_has_inlines 0x200b +#define DW_AT_sf_names 0x2101 +#define DW_AT_src_info 0x2102 +#define DW_AT_mac_info 0x2103 +#define DW_AT_src_coords 0x2104 +#define DW_AT_body_begin 0x2105 +#define DW_AT_body_end 0x2106 +#define DW_AT_lo_user 0x2000 +#define DW_AT_hi_user 0x3ff0 + +#define DW_OP_addr 0x03 +#define DW_OP_deref 0x06 +#define DW_OP_const1u 0x08 +#define DW_OP_const1s 0x09 +#define DW_OP_const2u 0x0a +#define DW_OP_const2s 0x0b +#define DW_OP_const4u 0x0c +#define DW_OP_const4s 0x0d +#define DW_OP_const8u 0x0e +#define DW_OP_const8s 0x0f +#define DW_OP_constu 0x10 +#define DW_OP_consts 0x11 +#define DW_OP_dup 0x12 +#define DW_OP_drop 0x13 +#define DW_OP_over 0x14 +#define DW_OP_pick 0x15 +#define DW_OP_swap 0x16 +#define DW_OP_rot 0x17 +#define DW_OP_xderef 0x18 +#define DW_OP_abs 0x19 +#define DW_OP_and 0x1a +#define DW_OP_div 0x1b +#define DW_OP_minus 0x1c +#define DW_OP_mod 0x1d +#define DW_OP_mul 0x1e +#define DW_OP_neg 0x1f +#define DW_OP_not 0x20 +#define DW_OP_or 0x21 +#define DW_OP_plus 0x22 +#define DW_OP_plus_uconst 0x23 +#define DW_OP_shl 0x24 +#define DW_OP_shr 0x25 +#define DW_OP_shra 0x26 +#define DW_OP_xor 0x27 +#define DW_OP_bra 0x28 +#define DW_OP_eq 0x29 +#define DW_OP_ge 0x2a +#define DW_OP_gt 0x2b +#define DW_OP_le 0x2c +#define DW_OP_lt 0x2d +#define DW_OP_ne 0x2e +#define DW_OP_skip 0x2f +#define DW_OP_lit0 0x30 +#define DW_OP_lit1 0x31 +#define DW_OP_lit2 0x32 +#define DW_OP_lit3 0x33 +#define DW_OP_lit4 0x34 +#define DW_OP_lit5 0x35 +#define DW_OP_lit6 0x36 +#define DW_OP_lit7 0x37 +#define DW_OP_lit8 0x38 +#define DW_OP_lit9 0x39 +#define DW_OP_lit10 0x3a +#define DW_OP_lit11 0x3b +#define DW_OP_lit12 0x3c +#define DW_OP_lit13 0x3d +#define DW_OP_lit14 0x3e +#define DW_OP_lit15 0x3f +#define DW_OP_lit16 0x40 +#define DW_OP_lit17 0x41 +#define DW_OP_lit18 0x42 +#define DW_OP_lit19 0x43 +#define DW_OP_lit20 0x44 +#define DW_OP_lit21 0x45 +#define DW_OP_lit22 0x46 +#define DW_OP_lit23 0x47 +#define DW_OP_lit24 0x48 +#define DW_OP_lit25 0x49 +#define DW_OP_lit26 0x4a +#define DW_OP_lit27 0x4b +#define DW_OP_lit28 0x4c +#define DW_OP_lit29 0x4d +#define DW_OP_lit30 0x4e +#define DW_OP_lit31 0x4f +#define DW_OP_reg0 0x50 +#define DW_OP_reg1 0x51 +#define DW_OP_reg2 0x52 +#define DW_OP_reg3 0x53 +#define DW_OP_reg4 0x54 +#define DW_OP_reg5 0x55 +#define DW_OP_reg6 0x56 +#define DW_OP_reg7 0x57 +#define DW_OP_reg8 0x58 +#define DW_OP_reg9 0x59 +#define DW_OP_reg10 0x5a +#define DW_OP_reg11 0x5b +#define DW_OP_reg12 0x5c +#define DW_OP_reg13 0x5d +#define DW_OP_reg14 0x5e +#define DW_OP_reg15 0x5f +#define DW_OP_reg16 0x60 +#define DW_OP_reg17 0x61 +#define DW_OP_reg18 0x62 +#define DW_OP_reg19 0x63 +#define DW_OP_reg20 0x64 +#define DW_OP_reg21 0x65 +#define DW_OP_reg22 0x66 +#define DW_OP_reg23 0x67 +#define DW_OP_reg24 0x68 +#define DW_OP_reg25 0x69 +#define DW_OP_reg26 0x6a +#define DW_OP_reg27 0x6b +#define DW_OP_reg28 0x6c +#define DW_OP_reg29 0x6d +#define DW_OP_reg30 0x6e +#define DW_OP_reg31 0x6f +#define DW_OP_breg0 0x70 +#define DW_OP_breg1 0x71 +#define DW_OP_breg2 0x72 +#define DW_OP_breg3 0x73 +#define DW_OP_breg4 0x74 +#define DW_OP_breg5 0x75 +#define DW_OP_breg6 0x76 +#define DW_OP_breg7 0x77 +#define DW_OP_breg8 0x78 +#define DW_OP_breg9 0x79 +#define DW_OP_breg10 0x7a +#define DW_OP_breg11 0x7b +#define DW_OP_breg12 0x7c +#define DW_OP_breg13 0x7d +#define DW_OP_breg14 0x7e +#define DW_OP_breg15 0x7f +#define DW_OP_breg16 0x80 +#define DW_OP_breg17 0x81 +#define DW_OP_breg18 0x82 +#define DW_OP_breg19 0x83 +#define DW_OP_breg20 0x84 +#define DW_OP_breg21 0x85 +#define DW_OP_breg22 0x86 +#define DW_OP_breg23 0x87 +#define DW_OP_breg24 0x88 +#define DW_OP_breg25 0x89 +#define DW_OP_breg26 0x8a +#define DW_OP_breg27 0x8b +#define DW_OP_breg28 0x8c +#define DW_OP_breg29 0x8d +#define DW_OP_breg30 0x8e +#define DW_OP_breg31 0x8f +#define DW_OP_regx 0x90 +#define DW_OP_fbreg 0x91 +#define DW_OP_bregx 0x92 +#define DW_OP_piece 0x93 +#define DW_OP_deref_size 0x94 +#define DW_OP_xderef_size 0x95 +#define DW_OP_nop 0x96 +#define DW_OP_push_object_address 0x97 +#define DW_OP_call2 0x98 +#define DW_OP_call4 0x99 +#define DW_OP_call_ref 0x9a +#define DW_OP_GNU_push_tls_address 0xe0 +#define DW_OP_lo_user 0xe0 +#define DW_OP_hi_user 0xff + +#define DW_ATE_void 0x0 +#define DW_ATE_address 0x1 +#define DW_ATE_boolean 0x2 +#define DW_ATE_complex_float 0x3 +#define DW_ATE_float 0x4 +#define DW_ATE_signed 0x5 +#define DW_ATE_signed_char 0x6 +#define DW_ATE_unsigned 0x7 +#define DW_ATE_unsigned_char 0x8 +#define DW_ATE_imaginary_float 0x9 +#define DW_ATE_lo_user 0x80 +#define DW_ATE_hi_user 0xff + +#define DW_ORD_row_major 0x0 +#define DW_ORD_col_major 0x1 + +#define DW_ACCESS_public 0x1 +#define DW_ACCESS_protected 0x2 +#define DW_ACCESS_private 0x3 + +#define DW_VIS_local 0x1 +#define DW_VIS_exported 0x2 +#define DW_VIS_qualified 0x3 + +#define DW_VIRTUALITY_none 0x0 +#define DW_VIRTUALITY_virtual 0x1 +#define DW_VIRTUALITY_pure_virtual 0x2 + +#define DW_ID_case_sensitive 0x0 +#define DW_ID_up_case 0x1 +#define DW_ID_down_case 0x2 +#define DW_ID_case_insensitive 0x3 + +#define DW_CC_normal 0x1 +#define DW_CC_program 0x2 +#define DW_CC_nocall 0x3 +#define DW_CC_lo_user 0x40 +#define DW_CC_hi_user 0xff + +#define DW_INL_not_inlined 0x0 +#define DW_INL_inlined 0x1 +#define DW_INL_declared_not_inlined 0x2 +#define DW_INL_declared_inlined 0x3 + +#define DW_DSC_label 0x0 +#define DW_DSC_range 0x1 + +#define DW_LNS_extended_op 0x0 +#define DW_LNS_copy 0x1 +#define DW_LNS_advance_pc 0x2 +#define DW_LNS_advance_line 0x3 +#define DW_LNS_set_file 0x4 +#define DW_LNS_set_column 0x5 +#define DW_LNS_negate_stmt 0x6 +#define DW_LNS_set_basic_block 0x7 +#define DW_LNS_const_add_pc 0x8 +#define DW_LNS_fixed_advance_pc 0x9 + +#define DW_LNE_end_sequence 0x1 +#define DW_LNE_set_address 0x2 +#define DW_LNE_define_file 0x3 + +#define DW_CFA_advance_loc 0x40 +#define DW_CFA_offset 0x80 +#define DW_CFA_restore 0xc0 +#define DW_CFA_nop 0x00 +#define DW_CFA_set_loc 0x01 +#define DW_CFA_advance_loc1 0x02 +#define DW_CFA_advance_loc2 0x03 +#define DW_CFA_advance_loc4 0x04 +#define DW_CFA_offset_extended 0x05 +#define DW_CFA_restore_extended 0x06 +#define DW_CFA_undefined 0x07 +#define DW_CFA_same_value 0x08 +#define DW_CFA_register 0x09 +#define DW_CFA_remember_state 0x0a +#define DW_CFA_restore_state 0x0b +#define DW_CFA_def_cfa 0x0c +#define DW_CFA_def_cfa_register 0x0d +#define DW_CFA_def_cfa_offset 0x0e +#define DW_CFA_def_cfa_expression 0x0f +#define DW_CFA_expression 0x10 +#define DW_CFA_offset_extended_sf 0x11 +#define DW_CFA_def_cfa_sf 0x12 +#define DW_CFA_def_cfa_offset_sf 0x13 +#define DW_CFA_MIPS_advance_loc8 0x1d +#define DW_CFA_GNU_window_save 0x2d +#define DW_CFA_GNU_args_size 0x2e +#define 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_low_user 0x1c +#define DW_CFA_high_user 0x3f + +#define DW_CHILDREN_no 0x00 +#define DW_CHILDREN_yes 0x01 + +#define DW_ADDR_none 0 + +#define DW_LANG_C89 0x0001 +#define DW_LANG_C 0x0002 +#define DW_LANG_Ada83 0x0003 +#define DW_LANG_C_plus_plus 0x0004 +#define DW_LANG_Cobol74 0x0005 +#define DW_LANG_Cobol85 0x0006 +#define DW_LANG_Fortran77 0x0007 +#define DW_LANG_Fortran90 0x0008 +#define DW_LANG_Pascal83 0x0009 +#define DW_LANG_Modula2 0x000a +#define DW_LANG_Java 0x000b +#define DW_LANG_C99 0x000c +#define DW_LANG_Ada95 0x000d +#define DW_LANG_Fortran95 0x000e +#define DW_LANG_Mips_Assembler 0x8001 +#define DW_LANG_lo_user 0x8000 +#define DW_LANG_hi_user 0xffff + +#define DW_MACINFO_define 1 +#define DW_MACINFO_undef 2 +#define DW_MACINFO_start_file 3 +#define DW_MACINFO_end_file 4 +#define DW_MACINFO_vendor_ext 255 diff --git a/trunk/src/elf.h b/trunk/src/elf.h new file mode 100644 index 0000000..0daff76 --- /dev/null +++ b/trunk/src/elf.h @@ -0,0 +1,2558 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003, 2004 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ELF_H +#define _ELF_H 1 + +#include <features.h> + +__BEGIN_DECLS + +/* Standard ELF types. */ + +#include <stdint.h> + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef int32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef int64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef int64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 10 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard <elf.h> file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + long int a_type; /* Entry type */ + union + { + long int a_val; /* Integer value */ + void *a_ptr; /* Pointer value */ + void (*a_fcn) (void); /* Function pointer value */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Motorola 68k specific definitions. */ + +/* Values for Elf32_Ehdr.e_flags. */ +#define EF_CPU32 0x00810000 + +/* m68k relocs. */ + +#define R_68K_NONE 0 /* No reloc */ +#define R_68K_32 1 /* Direct 32 bit */ +#define R_68K_16 2 /* Direct 16 bit */ +#define R_68K_8 3 /* Direct 8 bit */ +#define R_68K_PC32 4 /* PC relative 32 bit */ +#define R_68K_PC16 5 /* PC relative 16 bit */ +#define R_68K_PC8 6 /* PC relative 8 bit */ +#define R_68K_GOT32 7 /* 32 bit PC relative GOT entry */ +#define R_68K_GOT16 8 /* 16 bit PC relative GOT entry */ +#define R_68K_GOT8 9 /* 8 bit PC relative GOT entry */ +#define R_68K_GOT32O 10 /* 32 bit GOT offset */ +#define R_68K_GOT16O 11 /* 16 bit GOT offset */ +#define R_68K_GOT8O 12 /* 8 bit GOT offset */ +#define R_68K_PLT32 13 /* 32 bit PC relative PLT address */ +#define R_68K_PLT16 14 /* 16 bit PC relative PLT address */ +#define R_68K_PLT8 15 /* 8 bit PC relative PLT address */ +#define R_68K_PLT32O 16 /* 32 bit PLT offset */ +#define R_68K_PLT16O 17 /* 16 bit PLT offset */ +#define R_68K_PLT8O 18 /* 8 bit PLT offset */ +#define R_68K_COPY 19 /* Copy symbol at runtime */ +#define R_68K_GLOB_DAT 20 /* Create GOT entry */ +#define R_68K_JMP_SLOT 21 /* Create PLT entry */ +#define R_68K_RELATIVE 22 /* Adjust by program base */ +/* Keep this the last entry. */ +#define R_68K_NUM 23 + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + +/* SUN SPARC specific definitions. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_SPARC_REGISTER 13 /* Global register reserved to app. */ + +/* Values for Elf64_Ehdr.e_flags. */ + +#define EF_SPARCV9_MM 3 +#define EF_SPARCV9_TSO 0 +#define EF_SPARCV9_PSO 1 +#define EF_SPARCV9_RMO 2 +#define EF_SPARC_LEDATA 0x800000 /* little endian data */ +#define EF_SPARC_EXT_MASK 0xFFFF00 +#define EF_SPARC_32PLUS 0x000100 /* generic V8+ features */ +#define EF_SPARC_SUN_US1 0x000200 /* Sun UltraSPARC1 extensions */ +#define EF_SPARC_HAL_R1 0x000400 /* HAL R1 extensions */ +#define EF_SPARC_SUN_US3 0x000800 /* Sun UltraSPARCIII extensions */ + +/* SPARC relocs. */ + +#define R_SPARC_NONE 0 /* No reloc */ +#define R_SPARC_8 1 /* Direct 8 bit */ +#define R_SPARC_16 2 /* Direct 16 bit */ +#define R_SPARC_32 3 /* Direct 32 bit */ +#define R_SPARC_DISP8 4 /* PC relative 8 bit */ +#define R_SPARC_DISP16 5 /* PC relative 16 bit */ +#define R_SPARC_DISP32 6 /* PC relative 32 bit */ +#define R_SPARC_WDISP30 7 /* PC relative 30 bit shifted */ +#define R_SPARC_WDISP22 8 /* PC relative 22 bit shifted */ +#define R_SPARC_HI22 9 /* High 22 bit */ +#define R_SPARC_22 10 /* Direct 22 bit */ +#define R_SPARC_13 11 /* Direct 13 bit */ +#define R_SPARC_LO10 12 /* Truncated 10 bit */ +#define R_SPARC_GOT10 13 /* Truncated 10 bit GOT entry */ +#define R_SPARC_GOT13 14 /* 13 bit GOT entry */ +#define R_SPARC_GOT22 15 /* 22 bit GOT entry shifted */ +#define R_SPARC_PC10 16 /* PC relative 10 bit truncated */ +#define R_SPARC_PC22 17 /* PC relative 22 bit shifted */ +#define R_SPARC_WPLT30 18 /* 30 bit PC relative PLT address */ +#define R_SPARC_COPY 19 /* Copy symbol at runtime */ +#define R_SPARC_GLOB_DAT 20 /* Create GOT entry */ +#define R_SPARC_JMP_SLOT 21 /* Create PLT entry */ +#define R_SPARC_RELATIVE 22 /* Adjust by program base */ +#define R_SPARC_UA32 23 /* Direct 32 bit unaligned */ + +/* Additional Sparc64 relocs. */ + +#define R_SPARC_PLT32 24 /* Direct 32 bit ref to PLT entry */ +#define R_SPARC_HIPLT22 25 /* High 22 bit PLT entry */ +#define R_SPARC_LOPLT10 26 /* Truncated 10 bit PLT entry */ +#define R_SPARC_PCPLT32 27 /* PC rel 32 bit ref to PLT entry */ +#define R_SPARC_PCPLT22 28 /* PC rel high 22 bit PLT entry */ +#define R_SPARC_PCPLT10 29 /* PC rel trunc 10 bit PLT entry */ +#define R_SPARC_10 30 /* Direct 10 bit */ +#define R_SPARC_11 31 /* Direct 11 bit */ +#define R_SPARC_64 32 /* Direct 64 bit */ +#define R_SPARC_OLO10 33 /* 10bit with secondary 13bit addend */ +#define R_SPARC_HH22 34 /* Top 22 bits of direct 64 bit */ +#define R_SPARC_HM10 35 /* High middle 10 bits of ... */ +#define R_SPARC_LM22 36 /* Low middle 22 bits of ... */ +#define R_SPARC_PC_HH22 37 /* Top 22 bits of pc rel 64 bit */ +#define R_SPARC_PC_HM10 38 /* High middle 10 bit of ... */ +#define R_SPARC_PC_LM22 39 /* Low miggle 22 bits of ... */ +#define R_SPARC_WDISP16 40 /* PC relative 16 bit shifted */ +#define R_SPARC_WDISP19 41 /* PC relative 19 bit shifted */ +#define R_SPARC_7 43 /* Direct 7 bit */ +#define R_SPARC_5 44 /* Direct 5 bit */ +#define R_SPARC_6 45 /* Direct 6 bit */ +#define R_SPARC_DISP64 46 /* PC relative 64 bit */ +#define R_SPARC_PLT64 47 /* Direct 64 bit ref to PLT entry */ +#define R_SPARC_HIX22 48 /* High 22 bit complemented */ +#define R_SPARC_LOX10 49 /* Truncated 11 bit complemented */ +#define R_SPARC_H44 50 /* Direct high 12 of 44 bit */ +#define R_SPARC_M44 51 /* Direct mid 22 of 44 bit */ +#define R_SPARC_L44 52 /* Direct low 10 of 44 bit */ +#define R_SPARC_REGISTER 53 /* Global register usage */ +#define R_SPARC_UA64 54 /* Direct 64 bit unaligned */ +#define R_SPARC_UA16 55 /* Direct 16 bit unaligned */ +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 +/* Keep this the last entry. */ +#define R_SPARC_NUM 80 + +/* For Sparc64, legal values for d_tag of Elf64_Dyn. */ + +#define DT_SPARC_REGISTER 0x70000001 +#define DT_SPARC_NUM 2 + +/* Bits present in AT_HWCAP, primarily for Sparc32. */ + +#define HWCAP_SPARC_FLUSH 1 /* The cpu supports flush insn. */ +#define HWCAP_SPARC_STBAR 2 +#define HWCAP_SPARC_SWAP 4 +#define HWCAP_SPARC_MULDIV 8 +#define HWCAP_SPARC_V9 16 /* The cpu is v9, so v8plus is ok. */ +#define HWCAP_SPARC_ULTRA3 32 + +/* MIPS R3000 specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used */ +#define EF_MIPS_PIC 2 /* Contains PIC code */ +#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence */ +#define EF_MIPS_XGOT 8 +#define EF_MIPS_64BIT_WHIRL 16 +#define EF_MIPS_ABI2 32 +#define EF_MIPS_ABI_ON32 64 +#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level */ + +/* Legal values for MIPS architecture level. */ + +#define EF_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define EF_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define EF_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define EF_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define EF_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define EF_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define EF_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* The following are non-official names and should not be used. */ + +#define E_MIPS_ARCH_1 0x00000000 /* -mips1 code. */ +#define E_MIPS_ARCH_2 0x10000000 /* -mips2 code. */ +#define E_MIPS_ARCH_3 0x20000000 /* -mips3 code. */ +#define E_MIPS_ARCH_4 0x30000000 /* -mips4 code. */ +#define E_MIPS_ARCH_5 0x40000000 /* -mips5 code. */ +#define E_MIPS_ARCH_32 0x60000000 /* MIPS32 code. */ +#define E_MIPS_ARCH_64 0x70000000 /* MIPS64 code. */ + +/* Special section indices. */ + +#define SHN_MIPS_ACOMMON 0xff00 /* Allocated common symbols */ +#define SHN_MIPS_TEXT 0xff01 /* Allocated test symbols. */ +#define SHN_MIPS_DATA 0xff02 /* Allocated data symbols. */ +#define SHN_MIPS_SCOMMON 0xff03 /* Small common symbols */ +#define SHN_MIPS_SUNDEFINED 0xff04 /* Small undefined symbols */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_MIPS_LIBLIST 0x70000000 /* Shared objects used in link */ +#define SHT_MIPS_MSYM 0x70000001 +#define SHT_MIPS_CONFLICT 0x70000002 /* Conflicting symbols */ +#define SHT_MIPS_GPTAB 0x70000003 /* Global data area sizes */ +#define SHT_MIPS_UCODE 0x70000004 /* Reserved for SGI/MIPS compilers */ +#define SHT_MIPS_DEBUG 0x70000005 /* MIPS ECOFF debugging information*/ +#define SHT_MIPS_REGINFO 0x70000006 /* Register usage information */ +#define SHT_MIPS_PACKAGE 0x70000007 +#define SHT_MIPS_PACKSYM 0x70000008 +#define SHT_MIPS_RELD 0x70000009 +#define SHT_MIPS_IFACE 0x7000000b +#define SHT_MIPS_CONTENT 0x7000000c +#define SHT_MIPS_OPTIONS 0x7000000d /* Miscellaneous options. */ +#define SHT_MIPS_SHDR 0x70000010 +#define SHT_MIPS_FDESC 0x70000011 +#define SHT_MIPS_EXTSYM 0x70000012 +#define SHT_MIPS_DENSE 0x70000013 +#define SHT_MIPS_PDESC 0x70000014 +#define SHT_MIPS_LOCSYM 0x70000015 +#define SHT_MIPS_AUXSYM 0x70000016 +#define SHT_MIPS_OPTSYM 0x70000017 +#define SHT_MIPS_LOCSTR 0x70000018 +#define SHT_MIPS_LINE 0x70000019 +#define SHT_MIPS_RFDESC 0x7000001a +#define SHT_MIPS_DELTASYM 0x7000001b +#define SHT_MIPS_DELTAINST 0x7000001c +#define SHT_MIPS_DELTACLASS 0x7000001d +#define SHT_MIPS_DWARF 0x7000001e /* DWARF debugging information. */ +#define SHT_MIPS_DELTADECL 0x7000001f +#define SHT_MIPS_SYMBOL_LIB 0x70000020 +#define SHT_MIPS_EVENTS 0x70000021 /* Event section. */ +#define SHT_MIPS_TRANSLATE 0x70000022 +#define SHT_MIPS_PIXIE 0x70000023 +#define SHT_MIPS_XLATE 0x70000024 +#define SHT_MIPS_XLATE_DEBUG 0x70000025 +#define SHT_MIPS_WHIRL 0x70000026 +#define SHT_MIPS_EH_REGION 0x70000027 +#define SHT_MIPS_XLATE_OLD 0x70000028 +#define SHT_MIPS_PDR_EXCEPTION 0x70000029 + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_MIPS_GPREL 0x10000000 /* Must be part of global data area */ +#define SHF_MIPS_MERGE 0x20000000 +#define SHF_MIPS_ADDR 0x40000000 +#define SHF_MIPS_STRINGS 0x80000000 +#define SHF_MIPS_NOSTRIP 0x08000000 +#define SHF_MIPS_LOCAL 0x04000000 +#define SHF_MIPS_NAMES 0x02000000 +#define SHF_MIPS_NODUPE 0x01000000 + + +/* Symbol tables. */ + +/* MIPS specific values for `st_other'. */ +#define STO_MIPS_DEFAULT 0x0 +#define STO_MIPS_INTERNAL 0x1 +#define STO_MIPS_HIDDEN 0x2 +#define STO_MIPS_PROTECTED 0x3 +#define STO_MIPS_SC_ALIGN_UNUSED 0xff + +/* MIPS specific values for `st_info'. */ +#define STB_MIPS_SPLIT_COMMON 13 + +/* Entries found in sections of type SHT_MIPS_GPTAB. */ + +typedef union +{ + struct + { + Elf32_Word gt_current_g_value; /* -G value used for compilation */ + Elf32_Word gt_unused; /* Not used */ + } gt_header; /* First entry in section */ + struct + { + Elf32_Word gt_g_value; /* If this value were used for -G */ + Elf32_Word gt_bytes; /* This many bytes would be used */ + } gt_entry; /* Subsequent entries in section */ +} Elf32_gptab; + +/* Entry found in sections of type SHT_MIPS_REGINFO. */ + +typedef struct +{ + Elf32_Word ri_gprmask; /* General registers used */ + Elf32_Word ri_cprmask[4]; /* Coprocessor registers used */ + Elf32_Sword ri_gp_value; /* $gp register value */ +} Elf32_RegInfo; + +/* Entries found in sections of type SHT_MIPS_OPTIONS. */ + +typedef struct +{ + unsigned char kind; /* Determines interpretation of the + variable part of descriptor. */ + unsigned char size; /* Size of descriptor, including header. */ + Elf32_Section section; /* Section header index of section affected, + 0 for global options. */ + Elf32_Word info; /* Kind-specific information. */ +} Elf_Options; + +/* Values for `kind' field in Elf_Options. */ + +#define ODK_NULL 0 /* Undefined. */ +#define ODK_REGINFO 1 /* Register usage information. */ +#define ODK_EXCEPTIONS 2 /* Exception processing options. */ +#define ODK_PAD 3 /* Section padding options. */ +#define ODK_HWPATCH 4 /* Hardware workarounds performed */ +#define ODK_FILL 5 /* record the fill value used by the linker. */ +#define ODK_TAGS 6 /* reserve space for desktop tools to write. */ +#define ODK_HWAND 7 /* HW workarounds. 'AND' bits when merging. */ +#define ODK_HWOR 8 /* HW workarounds. 'OR' bits when merging. */ + +/* Values for `info' in Elf_Options for ODK_EXCEPTIONS entries. */ + +#define OEX_FPU_MIN 0x1f /* FPE's which MUST be enabled. */ +#define OEX_FPU_MAX 0x1f00 /* FPE's which MAY be enabled. */ +#define OEX_PAGE0 0x10000 /* page zero must be mapped. */ +#define OEX_SMM 0x20000 /* Force sequential memory mode? */ +#define OEX_FPDBUG 0x40000 /* Force floating point debug mode? */ +#define OEX_PRECISEFP OEX_FPDBUG +#define OEX_DISMISS 0x80000 /* Dismiss invalid address faults? */ + +#define OEX_FPU_INVAL 0x10 +#define OEX_FPU_DIV0 0x08 +#define OEX_FPU_OFLO 0x04 +#define OEX_FPU_UFLO 0x02 +#define OEX_FPU_INEX 0x01 + +/* Masks for `info' in Elf_Options for an ODK_HWPATCH entry. */ + +#define OHW_R4KEOP 0x1 /* R4000 end-of-page patch. */ +#define OHW_R8KPFETCH 0x2 /* may need R8000 prefetch patch. */ +#define OHW_R5KEOP 0x4 /* R5000 end-of-page patch. */ +#define OHW_R5KCVTL 0x8 /* R5000 cvt.[ds].l bug. clean=1. */ + +#define OPAD_PREFIX 0x1 +#define OPAD_POSTFIX 0x2 +#define OPAD_SYMBOL 0x4 + +/* Entry found in `.options' section. */ + +typedef struct +{ + Elf32_Word hwp_flags1; /* Extra flags. */ + Elf32_Word hwp_flags2; /* Extra flags. */ +} Elf_Options_Hw; + +/* Masks for `info' in ElfOptions for ODK_HWAND and ODK_HWOR entries. */ + +#define OHWA0_R4KEOP_CHECKED 0x00000001 +#define OHWA1_R4KEOP_CLEAN 0x00000002 + +/* MIPS relocs. */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ + +#define R_MIPS_SHIFT5 16 +#define R_MIPS_SHIFT6 17 +#define R_MIPS_64 18 +#define R_MIPS_GOT_DISP 19 +#define R_MIPS_GOT_PAGE 20 +#define R_MIPS_GOT_OFST 21 +#define R_MIPS_GOT_HI16 22 +#define R_MIPS_GOT_LO16 23 +#define R_MIPS_SUB 24 +#define R_MIPS_INSERT_A 25 +#define R_MIPS_INSERT_B 26 +#define R_MIPS_DELETE 27 +#define R_MIPS_HIGHER 28 +#define R_MIPS_HIGHEST 29 +#define R_MIPS_CALL_HI16 30 +#define R_MIPS_CALL_LO16 31 +#define R_MIPS_SCN_DISP 32 +#define R_MIPS_REL16 33 +#define R_MIPS_ADD_IMMEDIATE 34 +#define R_MIPS_PJUMP 35 +#define R_MIPS_RELGOT 36 +#define R_MIPS_JALR 37 +/* Keep this the last entry. */ +#define R_MIPS_NUM 38 + +/* Legal values for p_type field of Elf32_Phdr. */ + +#define PT_MIPS_REGINFO 0x70000000 /* Register usage information */ +#define PT_MIPS_RTPROC 0x70000001 /* Runtime procedure table. */ +#define PT_MIPS_OPTIONS 0x70000002 + +/* Special program header types. */ + +#define PF_MIPS_LOCAL 0x10000000 + +/* Legal values for d_tag field of Elf32_Dyn. */ + +#define DT_MIPS_RLD_VERSION 0x70000001 /* Runtime linker interface version */ +#define DT_MIPS_TIME_STAMP 0x70000002 /* Timestamp */ +#define DT_MIPS_ICHECKSUM 0x70000003 /* Checksum */ +#define DT_MIPS_IVERSION 0x70000004 /* Version string (string tbl index) */ +#define DT_MIPS_FLAGS 0x70000005 /* Flags */ +#define DT_MIPS_BASE_ADDRESS 0x70000006 /* Base address */ +#define DT_MIPS_MSYM 0x70000007 +#define DT_MIPS_CONFLICT 0x70000008 /* Address of CONFLICT section */ +#define DT_MIPS_LIBLIST 0x70000009 /* Address of LIBLIST section */ +#define DT_MIPS_LOCAL_GOTNO 0x7000000a /* Number of local GOT entries */ +#define DT_MIPS_CONFLICTNO 0x7000000b /* Number of CONFLICT entries */ +#define DT_MIPS_LIBLISTNO 0x70000010 /* Number of LIBLIST entries */ +#define DT_MIPS_SYMTABNO 0x70000011 /* Number of DYNSYM entries */ +#define DT_MIPS_UNREFEXTNO 0x70000012 /* First external DYNSYM */ +#define DT_MIPS_GOTSYM 0x70000013 /* First GOT entry in DYNSYM */ +#define DT_MIPS_HIPAGENO 0x70000014 /* Number of GOT page table entries */ +#define DT_MIPS_RLD_MAP 0x70000016 /* Address of run time loader map. */ +#define DT_MIPS_DELTA_CLASS 0x70000017 /* Delta C++ class definition. */ +#define DT_MIPS_DELTA_CLASS_NO 0x70000018 /* Number of entries in + DT_MIPS_DELTA_CLASS. */ +#define DT_MIPS_DELTA_INSTANCE 0x70000019 /* Delta C++ class instances. */ +#define DT_MIPS_DELTA_INSTANCE_NO 0x7000001a /* Number of entries in + DT_MIPS_DELTA_INSTANCE. */ +#define DT_MIPS_DELTA_RELOC 0x7000001b /* Delta relocations. */ +#define DT_MIPS_DELTA_RELOC_NO 0x7000001c /* Number of entries in + DT_MIPS_DELTA_RELOC. */ +#define DT_MIPS_DELTA_SYM 0x7000001d /* Delta symbols that Delta + relocations refer to. */ +#define DT_MIPS_DELTA_SYM_NO 0x7000001e /* Number of entries in + DT_MIPS_DELTA_SYM. */ +#define DT_MIPS_DELTA_CLASSSYM 0x70000020 /* Delta symbols that hold the + class declaration. */ +#define DT_MIPS_DELTA_CLASSSYM_NO 0x70000021 /* Number of entries in + DT_MIPS_DELTA_CLASSSYM. */ +#define DT_MIPS_CXX_FLAGS 0x70000022 /* Flags indicating for C++ flavor. */ +#define DT_MIPS_PIXIE_INIT 0x70000023 +#define DT_MIPS_SYMBOL_LIB 0x70000024 +#define DT_MIPS_LOCALPAGE_GOTIDX 0x70000025 +#define DT_MIPS_LOCAL_GOTIDX 0x70000026 +#define DT_MIPS_HIDDEN_GOTIDX 0x70000027 +#define DT_MIPS_PROTECTED_GOTIDX 0x70000028 +#define DT_MIPS_OPTIONS 0x70000029 /* Address of .options. */ +#define DT_MIPS_INTERFACE 0x7000002a /* Address of .interface. */ +#define DT_MIPS_DYNSTR_ALIGN 0x7000002b +#define DT_MIPS_INTERFACE_SIZE 0x7000002c /* Size of the .interface section. */ +#define DT_MIPS_RLD_TEXT_RESOLVE_ADDR 0x7000002d /* Address of rld_text_rsolve + function stored in GOT. */ +#define DT_MIPS_PERF_SUFFIX 0x7000002e /* Default suffix of dso to be added + by rld on dlopen() calls. */ +#define DT_MIPS_COMPACT_SIZE 0x7000002f /* (O32)Size of compact rel section. */ +#define DT_MIPS_GP_VALUE 0x70000030 /* GP value for aux GOTs. */ +#define DT_MIPS_AUX_DYNAMIC 0x70000031 /* Address of aux .dynamic. */ +#define DT_MIPS_NUM 0x32 + +/* Legal values for DT_MIPS_FLAGS Elf32_Dyn entry. */ + +#define RHF_NONE 0 /* No flags */ +#define RHF_QUICKSTART (1 << 0) /* Use quickstart */ +#define RHF_NOTPOT (1 << 1) /* Hash size not power of 2 */ +#define RHF_NO_LIBRARY_REPLACEMENT (1 << 2) /* Ignore LD_LIBRARY_PATH */ +#define RHF_NO_MOVE (1 << 3) +#define RHF_SGI_ONLY (1 << 4) +#define RHF_GUARANTEE_INIT (1 << 5) +#define RHF_DELTA_C_PLUS_PLUS (1 << 6) +#define RHF_GUARANTEE_START_INIT (1 << 7) +#define RHF_PIXIE (1 << 8) +#define RHF_DEFAULT_DELAY_LOAD (1 << 9) +#define RHF_REQUICKSTART (1 << 10) +#define RHF_REQUICKSTARTED (1 << 11) +#define RHF_CORD (1 << 12) +#define RHF_NO_UNRES_UNDEF (1 << 13) +#define RHF_RLD_ORDER_SAFE (1 << 14) + +/* Entries found in sections of type SHT_MIPS_LIBLIST. */ + +typedef struct +{ + Elf32_Word l_name; /* Name (string table index) */ + Elf32_Word l_time_stamp; /* Timestamp */ + Elf32_Word l_checksum; /* Checksum */ + Elf32_Word l_version; /* Interface version */ + Elf32_Word l_flags; /* Flags */ +} Elf32_Lib; + +typedef struct +{ + Elf64_Word l_name; /* Name (string table index) */ + Elf64_Word l_time_stamp; /* Timestamp */ + Elf64_Word l_checksum; /* Checksum */ + Elf64_Word l_version; /* Interface version */ + Elf64_Word l_flags; /* Flags */ +} Elf64_Lib; + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* HPPA specific definitions. */ + +/* Legal values for e_flags field of Elf32_Ehdr. */ + +#define EF_PARISC_TRAPNIL 0x00010000 /* Trap nil pointer dereference. */ +#define EF_PARISC_EXT 0x00020000 /* Program uses arch. extensions. */ +#define EF_PARISC_LSB 0x00040000 /* Program expects little endian. */ +#define EF_PARISC_WIDE 0x00080000 /* Program expects wide mode. */ +#define EF_PARISC_NO_KABP 0x00100000 /* No kernel assisted branch + prediction. */ +#define EF_PARISC_LAZYSWAP 0x00400000 /* Allow lazy swapping. */ +#define EF_PARISC_ARCH 0x0000ffff /* Architecture version. */ + +/* Defined values for `e_flags & EF_PARISC_ARCH' are: */ + +#define EFA_PARISC_1_0 0x020b /* PA-RISC 1.0 big-endian. */ +#define EFA_PARISC_1_1 0x0210 /* PA-RISC 1.1 big-endian. */ +#define EFA_PARISC_2_0 0x0214 /* PA-RISC 2.0 big-endian. */ + +/* Additional section indeces. */ + +#define SHN_PARISC_ANSI_COMMON 0xff00 /* Section for tenatively declared + symbols in ANSI C. */ +#define SHN_PARISC_HUGE_COMMON 0xff01 /* Common blocks in huge model. */ + +/* Legal values for sh_type field of Elf32_Shdr. */ + +#define SHT_PARISC_EXT 0x70000000 /* Contains product specific ext. */ +#define SHT_PARISC_UNWIND 0x70000001 /* Unwind information. */ +#define SHT_PARISC_DOC 0x70000002 /* Debug info for optimized code. */ + +/* Legal values for sh_flags field of Elf32_Shdr. */ + +#define SHF_PARISC_SHORT 0x20000000 /* Section with short addressing. */ +#define SHF_PARISC_HUGE 0x40000000 /* Section far from gp. */ +#define SHF_PARISC_SBP 0x80000000 /* Static branch prediction code. */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_PARISC_MILLICODE 13 /* Millicode function entry point. */ + +#define STT_HP_OPAQUE (STT_LOOS + 0x1) +#define STT_HP_STUB (STT_LOOS + 0x2) + +/* HPPA relocs. */ + +#define R_PARISC_NONE 0 /* No reloc. */ +#define R_PARISC_DIR32 1 /* Direct 32-bit reference. */ +#define R_PARISC_DIR21L 2 /* Left 21 bits of eff. address. */ +#define R_PARISC_DIR17R 3 /* Right 17 bits of eff. address. */ +#define R_PARISC_DIR17F 4 /* 17 bits of eff. address. */ +#define R_PARISC_DIR14R 6 /* Right 14 bits of eff. address. */ +#define R_PARISC_PCREL32 9 /* 32-bit rel. address. */ +#define R_PARISC_PCREL21L 10 /* Left 21 bits of rel. address. */ +#define R_PARISC_PCREL17R 11 /* Right 17 bits of rel. address. */ +#define R_PARISC_PCREL17F 12 /* 17 bits of rel. address. */ +#define R_PARISC_PCREL14R 14 /* Right 14 bits of rel. address. */ +#define R_PARISC_DPREL21L 18 /* Left 21 bits of rel. address. */ +#define R_PARISC_DPREL14R 22 /* Right 14 bits of rel. address. */ +#define R_PARISC_GPREL21L 26 /* GP-relative, left 21 bits. */ +#define R_PARISC_GPREL14R 30 /* GP-relative, right 14 bits. */ +#define R_PARISC_LTOFF21L 34 /* LT-relative, left 21 bits. */ +#define R_PARISC_LTOFF14R 38 /* LT-relative, right 14 bits. */ +#define R_PARISC_SECREL32 41 /* 32 bits section rel. address. */ +#define R_PARISC_SEGBASE 48 /* No relocation, set segment base. */ +#define R_PARISC_SEGREL32 49 /* 32 bits segment rel. address. */ +#define R_PARISC_PLTOFF21L 50 /* PLT rel. address, left 21 bits. */ +#define R_PARISC_PLTOFF14R 54 /* PLT rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_FPTR32 57 /* 32 bits LT-rel. function pointer. */ +#define R_PARISC_LTOFF_FPTR21L 58 /* LT-rel. fct ptr, left 21 bits. */ +#define R_PARISC_LTOFF_FPTR14R 62 /* LT-rel. fct ptr, right 14 bits. */ +#define R_PARISC_FPTR64 64 /* 64 bits function address. */ +#define R_PARISC_PLABEL32 65 /* 32 bits function address. */ +#define R_PARISC_PCREL64 72 /* 64 bits PC-rel. address. */ +#define R_PARISC_PCREL22F 74 /* 22 bits PC-rel. address. */ +#define R_PARISC_PCREL14WR 75 /* PC-rel. address, right 14 bits. */ +#define R_PARISC_PCREL14DR 76 /* PC rel. address, right 14 bits. */ +#define R_PARISC_PCREL16F 77 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16WF 78 /* 16 bits PC-rel. address. */ +#define R_PARISC_PCREL16DF 79 /* 16 bits PC-rel. address. */ +#define R_PARISC_DIR64 80 /* 64 bits of eff. address. */ +#define R_PARISC_DIR14WR 83 /* 14 bits of eff. address. */ +#define R_PARISC_DIR14DR 84 /* 14 bits of eff. address. */ +#define R_PARISC_DIR16F 85 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16WF 86 /* 16 bits of eff. address. */ +#define R_PARISC_DIR16DF 87 /* 16 bits of eff. address. */ +#define R_PARISC_GPREL64 88 /* 64 bits of GP-rel. address. */ +#define R_PARISC_GPREL14WR 91 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL14DR 92 /* GP-rel. address, right 14 bits. */ +#define R_PARISC_GPREL16F 93 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16WF 94 /* 16 bits GP-rel. address. */ +#define R_PARISC_GPREL16DF 95 /* 16 bits GP-rel. address. */ +#define R_PARISC_LTOFF64 96 /* 64 bits LT-rel. address. */ +#define R_PARISC_LTOFF14WR 99 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF14DR 100 /* LT-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF16F 101 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16WF 102 /* 16 bits LT-rel. address. */ +#define R_PARISC_LTOFF16DF 103 /* 16 bits LT-rel. address. */ +#define R_PARISC_SECREL64 104 /* 64 bits section rel. address. */ +#define R_PARISC_SEGREL64 112 /* 64 bits segment rel. address. */ +#define R_PARISC_PLTOFF14WR 115 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF14DR 116 /* PLT-rel. address, right 14 bits. */ +#define R_PARISC_PLTOFF16F 117 /* 16 bits LT-rel. address. */ +#define R_PARISC_PLTOFF16WF 118 /* 16 bits PLT-rel. address. */ +#define R_PARISC_PLTOFF16DF 119 /* 16 bits PLT-rel. address. */ +#define R_PARISC_LTOFF_FPTR64 120 /* 64 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR14WR 123 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR14DR 124 /* LT-rel. fct. ptr., right 14 bits. */ +#define R_PARISC_LTOFF_FPTR16F 125 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16WF 126 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LTOFF_FPTR16DF 127 /* 16 bits LT-rel. function ptr. */ +#define R_PARISC_LORESERVE 128 +#define R_PARISC_COPY 128 /* Copy relocation. */ +#define R_PARISC_IPLT 129 /* Dynamic reloc, imported PLT */ +#define R_PARISC_EPLT 130 /* Dynamic reloc, exported PLT */ +#define R_PARISC_TPREL32 153 /* 32 bits TP-rel. address. */ +#define R_PARISC_TPREL21L 154 /* TP-rel. address, left 21 bits. */ +#define R_PARISC_TPREL14R 158 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_LTOFF_TP21L 162 /* LT-TP-rel. address, left 21 bits. */ +#define R_PARISC_LTOFF_TP14R 166 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14F 167 /* 14 bits LT-TP-rel. address. */ +#define R_PARISC_TPREL64 216 /* 64 bits TP-rel. address. */ +#define R_PARISC_TPREL14WR 219 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL14DR 220 /* TP-rel. address, right 14 bits. */ +#define R_PARISC_TPREL16F 221 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16WF 222 /* 16 bits TP-rel. address. */ +#define R_PARISC_TPREL16DF 223 /* 16 bits TP-rel. address. */ +#define R_PARISC_LTOFF_TP64 224 /* 64 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP14WR 227 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP14DR 228 /* LT-TP-rel. address, right 14 bits.*/ +#define R_PARISC_LTOFF_TP16F 229 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16WF 230 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_LTOFF_TP16DF 231 /* 16 bits LT-TP-rel. address. */ +#define R_PARISC_HIRESERVE 255 + +/* Legal values for p_type field of Elf32_Phdr/Elf64_Phdr. */ + +#define PT_HP_TLS (PT_LOOS + 0x0) +#define PT_HP_CORE_NONE (PT_LOOS + 0x1) +#define PT_HP_CORE_VERSION (PT_LOOS + 0x2) +#define PT_HP_CORE_KERNEL (PT_LOOS + 0x3) +#define PT_HP_CORE_COMM (PT_LOOS + 0x4) +#define PT_HP_CORE_PROC (PT_LOOS + 0x5) +#define PT_HP_CORE_LOADABLE (PT_LOOS + 0x6) +#define PT_HP_CORE_STACK (PT_LOOS + 0x7) +#define PT_HP_CORE_SHM (PT_LOOS + 0x8) +#define PT_HP_CORE_MMF (PT_LOOS + 0x9) +#define PT_HP_PARALLEL (PT_LOOS + 0x10) +#define PT_HP_FASTBIND (PT_LOOS + 0x11) +#define PT_HP_OPT_ANNOT (PT_LOOS + 0x12) +#define PT_HP_HSL_ANNOT (PT_LOOS + 0x13) +#define PT_HP_STACK (PT_LOOS + 0x14) + +#define PT_PARISC_ARCHEXT 0x70000000 +#define PT_PARISC_UNWIND 0x70000001 + +/* Legal values for p_flags field of Elf32_Phdr/Elf64_Phdr. */ + +#define PF_PARISC_SBP 0x08000000 + +#define PF_HP_PAGE_SIZE 0x00100000 +#define PF_HP_FAR_SHARED 0x00200000 +#define PF_HP_NEAR_SHARED 0x00400000 +#define PF_HP_CODE 0x01000000 +#define PF_HP_MODIFY 0x02000000 +#define PF_HP_LAZYSWAP 0x04000000 +#define PF_HP_SBP 0x08000000 + + +/* Alpha specific definitions. */ + +/* Legal values for e_flags field of Elf64_Ehdr. */ + +#define EF_ALPHA_32BIT 1 /* All addresses must be < 2GB. */ +#define EF_ALPHA_CANRELAX 2 /* Relocations for relaxing exist. */ + +/* Legal values for sh_type field of Elf64_Shdr. */ + +/* These two are primerily concerned with ECOFF debugging info. */ +#define SHT_ALPHA_DEBUG 0x70000001 +#define SHT_ALPHA_REGINFO 0x70000002 + +/* Legal values for sh_flags field of Elf64_Shdr. */ + +#define SHF_ALPHA_GPREL 0x10000000 + +/* Legal values for st_other field of Elf64_Sym. */ +#define STO_ALPHA_NOPV 0x80 /* No PV required. */ +#define STO_ALPHA_STD_GPLOAD 0x88 /* PV only used for initial ldgp. */ + +/* Alpha relocs. */ + +#define R_ALPHA_NONE 0 /* No reloc */ +#define R_ALPHA_REFLONG 1 /* Direct 32 bit */ +#define R_ALPHA_REFQUAD 2 /* Direct 64 bit */ +#define R_ALPHA_GPREL32 3 /* GP relative 32 bit */ +#define R_ALPHA_LITERAL 4 /* GP relative 16 bit w/optimization */ +#define R_ALPHA_LITUSE 5 /* Optimization hint for LITERAL */ +#define R_ALPHA_GPDISP 6 /* Add displacement to GP */ +#define R_ALPHA_BRADDR 7 /* PC+4 relative 23 bit shifted */ +#define R_ALPHA_HINT 8 /* PC+4 relative 16 bit shifted */ +#define R_ALPHA_SREL16 9 /* PC relative 16 bit */ +#define R_ALPHA_SREL32 10 /* PC relative 32 bit */ +#define R_ALPHA_SREL64 11 /* PC relative 64 bit */ +#define R_ALPHA_GPRELHIGH 17 /* GP relative 32 bit, high 16 bits */ +#define R_ALPHA_GPRELLOW 18 /* GP relative 32 bit, low 16 bits */ +#define R_ALPHA_GPREL16 19 /* GP relative 16 bit */ +#define R_ALPHA_COPY 24 /* Copy symbol at runtime */ +#define R_ALPHA_GLOB_DAT 25 /* Create GOT entry */ +#define R_ALPHA_JMP_SLOT 26 /* Create PLT entry */ +#define R_ALPHA_RELATIVE 27 /* Adjust by program base */ +#define R_ALPHA_TLS_GD_HI 28 +#define R_ALPHA_TLSGD 29 +#define R_ALPHA_TLS_LDM 30 +#define R_ALPHA_DTPMOD64 31 +#define R_ALPHA_GOTDTPREL 32 +#define R_ALPHA_DTPREL64 33 +#define R_ALPHA_DTPRELHI 34 +#define R_ALPHA_DTPRELLO 35 +#define R_ALPHA_DTPREL16 36 +#define R_ALPHA_GOTTPREL 37 +#define R_ALPHA_TPREL64 38 +#define R_ALPHA_TPRELHI 39 +#define R_ALPHA_TPRELLO 40 +#define R_ALPHA_TPREL16 41 +/* Keep this the last entry. */ +#define R_ALPHA_NUM 46 + +/* Magic values of the LITUSE relocation addend. */ +#define LITUSE_ALPHA_ADDR 0 +#define LITUSE_ALPHA_BASE 1 +#define LITUSE_ALPHA_BYTOFF 2 +#define LITUSE_ALPHA_JSR 3 +#define LITUSE_ALPHA_TLS_GD 4 +#define LITUSE_ALPHA_TLS_LDM 5 + + +/* PowerPC specific declarations */ + +/* Values for Elf32/64_Ehdr.e_flags. */ +#define EF_PPC_EMB 0x80000000 /* PowerPC embedded flag */ + +/* Cygnus local bits below */ +#define EF_PPC_RELOCATABLE 0x00010000 /* PowerPC -mrelocatable flag*/ +#define EF_PPC_RELOCATABLE_LIB 0x00008000 /* PowerPC -mrelocatable-lib + flag */ + +/* PowerPC relocations defined by the ABIs */ +#define R_PPC_NONE 0 +#define R_PPC_ADDR32 1 /* 32bit absolute address */ +#define R_PPC_ADDR24 2 /* 26bit address, 2 bits ignored. */ +#define R_PPC_ADDR16 3 /* 16bit absolute address */ +#define R_PPC_ADDR16_LO 4 /* lower 16bit of absolute address */ +#define R_PPC_ADDR16_HI 5 /* high 16bit of absolute address */ +#define R_PPC_ADDR16_HA 6 /* adjusted high 16bit */ +#define R_PPC_ADDR14 7 /* 16bit address, 2 bits ignored */ +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 /* PC relative 26 bit */ +#define R_PPC_REL14 11 /* PC relative 16 bit */ +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* PowerPC relocations defined for the TLS access ABI. */ +#define R_PPC_TLS 67 /* none (sym+add)@tls */ +#define R_PPC_DTPMOD32 68 /* word32 (sym+add)@dtpmod */ +#define R_PPC_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC_TPREL32 73 /* word32 (sym+add)@tprel */ +#define R_PPC_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC_DTPREL32 78 /* word32 (sym+add)@dtprel */ +#define R_PPC_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC_GOT_TPREL16 87 /* half16* (sym+add)@got@tprel */ +#define R_PPC_GOT_TPREL16_LO 88 /* half16 (sym+add)@got@tprel@l */ +#define R_PPC_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC_GOT_DTPREL16 91 /* half16* (sym+add)@got@dtprel */ +#define R_PPC_GOT_DTPREL16_LO 92 /* half16* (sym+add)@got@dtprel@l */ +#define R_PPC_GOT_DTPREL16_HI 93 /* half16* (sym+add)@got@dtprel@h */ +#define R_PPC_GOT_DTPREL16_HA 94 /* half16* (sym+add)@got@dtprel@ha */ + +/* Keep this the last entry. */ +#define R_PPC_NUM 95 + +/* The remaining relocs are from the Embedded ELF ABI, and are not + in the SVR4 ELF ABI. */ +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 /* 16 bit offset in SDA */ +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 /* 16 bit relative offset in SDA */ + +/* Diab tool relocations. */ +#define R_PPC_DIAB_SDA21_LO 180 /* like EMB_SDA21, but lower 16 bit */ +#define R_PPC_DIAB_SDA21_HI 181 /* like EMB_SDA21, but high 16 bit */ +#define R_PPC_DIAB_SDA21_HA 182 /* like EMB_SDA21, adjusted high 16 */ +#define R_PPC_DIAB_RELSDA_LO 183 /* like EMB_RELSDA, but lower 16 bit */ +#define R_PPC_DIAB_RELSDA_HI 184 /* like EMB_RELSDA, but high 16 bit */ +#define R_PPC_DIAB_RELSDA_HA 185 /* like EMB_RELSDA, adjusted high 16 */ + +/* This is a phony reloc to handle any old fashioned TOC16 references + that may still be in object files. */ +#define R_PPC_TOC16 255 + + +/* PowerPC64 relocations defined by the ABIs */ +#define R_PPC64_NONE R_PPC_NONE +#define R_PPC64_ADDR32 R_PPC_ADDR32 /* 32bit absolute address */ +#define R_PPC64_ADDR24 R_PPC_ADDR24 /* 26bit address, word aligned */ +#define R_PPC64_ADDR16 R_PPC_ADDR16 /* 16bit absolute address */ +#define R_PPC64_ADDR16_LO R_PPC_ADDR16_LO /* lower 16bits of address */ +#define R_PPC64_ADDR16_HI R_PPC_ADDR16_HI /* high 16bits of address. */ +#define R_PPC64_ADDR16_HA R_PPC_ADDR16_HA /* adjusted high 16bits. */ +#define R_PPC64_ADDR14 R_PPC_ADDR14 /* 16bit address, word aligned */ +#define R_PPC64_ADDR14_BRTAKEN R_PPC_ADDR14_BRTAKEN +#define R_PPC64_ADDR14_BRNTAKEN R_PPC_ADDR14_BRNTAKEN +#define R_PPC64_REL24 R_PPC_REL24 /* PC-rel. 26 bit, word aligned */ +#define R_PPC64_REL14 R_PPC_REL14 /* PC relative 16 bit */ +#define R_PPC64_REL14_BRTAKEN R_PPC_REL14_BRTAKEN +#define R_PPC64_REL14_BRNTAKEN R_PPC_REL14_BRNTAKEN +#define R_PPC64_GOT16 R_PPC_GOT16 +#define R_PPC64_GOT16_LO R_PPC_GOT16_LO +#define R_PPC64_GOT16_HI R_PPC_GOT16_HI +#define R_PPC64_GOT16_HA R_PPC_GOT16_HA + +#define R_PPC64_COPY R_PPC_COPY +#define R_PPC64_GLOB_DAT R_PPC_GLOB_DAT +#define R_PPC64_JMP_SLOT R_PPC_JMP_SLOT +#define R_PPC64_RELATIVE R_PPC_RELATIVE + +#define R_PPC64_UADDR32 R_PPC_UADDR32 +#define R_PPC64_UADDR16 R_PPC_UADDR16 +#define R_PPC64_REL32 R_PPC_REL32 +#define R_PPC64_PLT32 R_PPC_PLT32 +#define R_PPC64_PLTREL32 R_PPC_PLTREL32 +#define R_PPC64_PLT16_LO R_PPC_PLT16_LO +#define R_PPC64_PLT16_HI R_PPC_PLT16_HI +#define R_PPC64_PLT16_HA R_PPC_PLT16_HA + +#define R_PPC64_SECTOFF R_PPC_SECTOFF +#define R_PPC64_SECTOFF_LO R_PPC_SECTOFF_LO +#define R_PPC64_SECTOFF_HI R_PPC_SECTOFF_HI +#define R_PPC64_SECTOFF_HA R_PPC_SECTOFF_HA +#define R_PPC64_ADDR30 37 /* word30 (S + A - P) >> 2 */ +#define R_PPC64_ADDR64 38 /* doubleword64 S + A */ +#define R_PPC64_ADDR16_HIGHER 39 /* half16 #higher(S + A) */ +#define R_PPC64_ADDR16_HIGHERA 40 /* half16 #highera(S + A) */ +#define R_PPC64_ADDR16_HIGHEST 41 /* half16 #highest(S + A) */ +#define R_PPC64_ADDR16_HIGHESTA 42 /* half16 #highesta(S + A) */ +#define R_PPC64_UADDR64 43 /* doubleword64 S + A */ +#define R_PPC64_REL64 44 /* doubleword64 S + A - P */ +#define R_PPC64_PLT64 45 /* doubleword64 L + A */ +#define R_PPC64_PLTREL64 46 /* doubleword64 L + A - P */ +#define R_PPC64_TOC16 47 /* half16* S + A - .TOC */ +#define R_PPC64_TOC16_LO 48 /* half16 #lo(S + A - .TOC.) */ +#define R_PPC64_TOC16_HI 49 /* half16 #hi(S + A - .TOC.) */ +#define R_PPC64_TOC16_HA 50 /* half16 #ha(S + A - .TOC.) */ +#define R_PPC64_TOC 51 /* doubleword64 .TOC */ +#define R_PPC64_PLTGOT16 52 /* half16* M + A */ +#define R_PPC64_PLTGOT16_LO 53 /* half16 #lo(M + A) */ +#define R_PPC64_PLTGOT16_HI 54 /* half16 #hi(M + A) */ +#define R_PPC64_PLTGOT16_HA 55 /* half16 #ha(M + A) */ + +#define R_PPC64_ADDR16_DS 56 /* half16ds* (S + A) >> 2 */ +#define R_PPC64_ADDR16_LO_DS 57 /* half16ds #lo(S + A) >> 2 */ +#define R_PPC64_GOT16_DS 58 /* half16ds* (G + A) >> 2 */ +#define R_PPC64_GOT16_LO_DS 59 /* half16ds #lo(G + A) >> 2 */ +#define R_PPC64_PLT16_LO_DS 60 /* half16ds #lo(L + A) >> 2 */ +#define R_PPC64_SECTOFF_DS 61 /* half16ds* (R + A) >> 2 */ +#define R_PPC64_SECTOFF_LO_DS 62 /* half16ds #lo(R + A) >> 2 */ +#define R_PPC64_TOC16_DS 63 /* half16ds* (S + A - .TOC.) >> 2 */ +#define R_PPC64_TOC16_LO_DS 64 /* half16ds #lo(S + A - .TOC.) >> 2 */ +#define R_PPC64_PLTGOT16_DS 65 /* half16ds* (M + A) >> 2 */ +#define R_PPC64_PLTGOT16_LO_DS 66 /* half16ds #lo(M + A) >> 2 */ + +/* PowerPC64 relocations defined for the TLS access ABI. */ +#define R_PPC64_TLS 67 /* none (sym+add)@tls */ +#define R_PPC64_DTPMOD64 68 /* doubleword64 (sym+add)@dtpmod */ +#define R_PPC64_TPREL16 69 /* half16* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO 70 /* half16 (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HI 71 /* half16 (sym+add)@tprel@h */ +#define R_PPC64_TPREL16_HA 72 /* half16 (sym+add)@tprel@ha */ +#define R_PPC64_TPREL64 73 /* doubleword64 (sym+add)@tprel */ +#define R_PPC64_DTPREL16 74 /* half16* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO 75 /* half16 (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HI 76 /* half16 (sym+add)@dtprel@h */ +#define R_PPC64_DTPREL16_HA 77 /* half16 (sym+add)@dtprel@ha */ +#define R_PPC64_DTPREL64 78 /* doubleword64 (sym+add)@dtprel */ +#define R_PPC64_GOT_TLSGD16 79 /* half16* (sym+add)@got@tlsgd */ +#define R_PPC64_GOT_TLSGD16_LO 80 /* half16 (sym+add)@got@tlsgd@l */ +#define R_PPC64_GOT_TLSGD16_HI 81 /* half16 (sym+add)@got@tlsgd@h */ +#define R_PPC64_GOT_TLSGD16_HA 82 /* half16 (sym+add)@got@tlsgd@ha */ +#define R_PPC64_GOT_TLSLD16 83 /* half16* (sym+add)@got@tlsld */ +#define R_PPC64_GOT_TLSLD16_LO 84 /* half16 (sym+add)@got@tlsld@l */ +#define R_PPC64_GOT_TLSLD16_HI 85 /* half16 (sym+add)@got@tlsld@h */ +#define R_PPC64_GOT_TLSLD16_HA 86 /* half16 (sym+add)@got@tlsld@ha */ +#define R_PPC64_GOT_TPREL16_DS 87 /* half16ds* (sym+add)@got@tprel */ +#define R_PPC64_GOT_TPREL16_LO_DS 88 /* half16ds (sym+add)@got@tprel@l */ +#define R_PPC64_GOT_TPREL16_HI 89 /* half16 (sym+add)@got@tprel@h */ +#define R_PPC64_GOT_TPREL16_HA 90 /* half16 (sym+add)@got@tprel@ha */ +#define R_PPC64_GOT_DTPREL16_DS 91 /* half16ds* (sym+add)@got@dtprel */ +#define R_PPC64_GOT_DTPREL16_LO_DS 92 /* half16ds (sym+add)@got@dtprel@l */ +#define R_PPC64_GOT_DTPREL16_HI 93 /* half16 (sym+add)@got@dtprel@h */ +#define R_PPC64_GOT_DTPREL16_HA 94 /* half16 (sym+add)@got@dtprel@ha */ +#define R_PPC64_TPREL16_DS 95 /* half16ds* (sym+add)@tprel */ +#define R_PPC64_TPREL16_LO_DS 96 /* half16ds (sym+add)@tprel@l */ +#define R_PPC64_TPREL16_HIGHER 97 /* half16 (sym+add)@tprel@higher */ +#define R_PPC64_TPREL16_HIGHERA 98 /* half16 (sym+add)@tprel@highera */ +#define R_PPC64_TPREL16_HIGHEST 99 /* half16 (sym+add)@tprel@highest */ +#define R_PPC64_TPREL16_HIGHESTA 100 /* half16 (sym+add)@tprel@highesta */ +#define R_PPC64_DTPREL16_DS 101 /* half16ds* (sym+add)@dtprel */ +#define R_PPC64_DTPREL16_LO_DS 102 /* half16ds (sym+add)@dtprel@l */ +#define R_PPC64_DTPREL16_HIGHER 103 /* half16 (sym+add)@dtprel@higher */ +#define R_PPC64_DTPREL16_HIGHERA 104 /* half16 (sym+add)@dtprel@highera */ +#define R_PPC64_DTPREL16_HIGHEST 105 /* half16 (sym+add)@dtprel@highest */ +#define R_PPC64_DTPREL16_HIGHESTA 106 /* half16 (sym+add)@dtprel@highesta */ + +/* Keep this the last entry. */ +#define R_PPC64_NUM 107 + +/* PowerPC64 specific values for the Dyn d_tag field. */ +#define DT_PPC64_GLINK (DT_LOPROC + 0) +#define DT_PPC64_OPD (DT_LOPROC + 1) +#define DT_PPC64_OPDSZ (DT_LOPROC + 2) +#define DT_PPC64_NUM 3 + + +/* ARM specific declarations */ + +/* Processor specific flags for the ELF header e_flags field. */ +#define EF_ARM_RELEXEC 0x01 +#define EF_ARM_HASENTRY 0x02 +#define EF_ARM_INTERWORK 0x04 +#define EF_ARM_APCS_26 0x08 +#define EF_ARM_APCS_FLOAT 0x10 +#define EF_ARM_PIC 0x20 +#define EF_ARM_ALIGN8 0x40 /* 8-bit structure alignment is in use */ +#define EF_ARM_NEW_ABI 0x80 +#define EF_ARM_OLD_ABI 0x100 + +/* Other constants defined in the ARM ELF spec. version B-01. */ +/* NB. These conflict with values defined above. */ +#define EF_ARM_SYMSARESORTED 0x04 +#define EF_ARM_DYNSYMSUSESEGIDX 0x08 +#define EF_ARM_MAPSYMSFIRST 0x10 +#define EF_ARM_EABIMASK 0XFF000000 + +#define EF_ARM_EABI_VERSION(flags) ((flags) & EF_ARM_EABIMASK) +#define EF_ARM_EABI_UNKNOWN 0x00000000 +#define EF_ARM_EABI_VER1 0x01000000 +#define EF_ARM_EABI_VER2 0x02000000 + +/* Additional symbol types for Thumb */ +#define STT_ARM_TFUNC 0xd + +/* ARM-specific values for sh_flags */ +#define SHF_ARM_ENTRYSECT 0x10000000 /* Section contains an entry point */ +#define SHF_ARM_COMDEF 0x80000000 /* Section may be multiply defined + in the input to a link step */ + +/* ARM-specific program header flags */ +#define PF_ARM_SB 0x10000000 /* Segment contains the location + addressed by the static base */ + +/* ARM relocs. */ +#define R_ARM_NONE 0 /* No reloc */ +#define R_ARM_PC24 1 /* PC relative 26 bit branch */ +#define R_ARM_ABS32 2 /* Direct 32 bit */ +#define R_ARM_REL32 3 /* PC relative 32 bit */ +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 /* Direct 16 bit */ +#define R_ARM_ABS12 6 /* Direct 12 bit */ +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 /* Direct 8 bit */ +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +#define R_ARM_COPY 20 /* Copy symbol at runtime */ +#define R_ARM_GLOB_DAT 21 /* Create GOT entry */ +#define R_ARM_JUMP_SLOT 22 /* Create PLT entry */ +#define R_ARM_RELATIVE 23 /* Adjust by program base */ +#define R_ARM_GOTOFF 24 /* 32 bit offset to GOT */ +#define R_ARM_GOTPC 25 /* 32 bit PC relative offset to GOT */ +#define R_ARM_GOT32 26 /* 32 bit GOT entry */ +#define R_ARM_PLT32 27 /* 32 bit PLT address */ +#define R_ARM_ALU_PCREL_7_0 32 +#define R_ARM_ALU_PCREL_15_8 33 +#define R_ARM_ALU_PCREL_23_15 34 +#define R_ARM_LDR_SBREL_11_0 35 +#define R_ARM_ALU_SBREL_19_12 36 +#define R_ARM_ALU_SBREL_27_20 37 +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_THM_PC11 102 /* thumb unconditional branch */ +#define R_ARM_THM_PC9 103 /* thumb conditional branch */ +#define R_ARM_RXPC25 249 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS22 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 +/* Keep this the last entry. */ +#define R_ARM_NUM 256 + +/* IA-64 specific declarations. */ + +/* Processor specific flags for the Ehdr e_flags field. */ +#define EF_IA_64_MASKOS 0x0000000f /* os-specific flags */ +#define EF_IA_64_ABI64 0x00000010 /* 64-bit ABI */ +#define EF_IA_64_ARCH 0xff000000 /* arch. version mask */ + +/* Processor specific values for the Phdr p_type field. */ +#define PT_IA_64_ARCHEXT (PT_LOPROC + 0) /* arch extension bits */ +#define PT_IA_64_UNWIND (PT_LOPROC + 1) /* ia64 unwind bits */ +#define PT_IA_64_HP_OPT_ANOT (PT_LOOS + 0x12) +#define PT_IA_64_HP_HSL_ANOT (PT_LOOS + 0x13) +#define PT_IA_64_HP_STACK (PT_LOOS + 0x14) + +/* Processor specific flags for the Phdr p_flags field. */ +#define PF_IA_64_NORECOV 0x80000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Shdr sh_type field. */ +#define SHT_IA_64_EXT (SHT_LOPROC + 0) /* extension bits */ +#define SHT_IA_64_UNWIND (SHT_LOPROC + 1) /* unwind bits */ + +/* Processor specific flags for the Shdr sh_flags field. */ +#define SHF_IA_64_SHORT 0x10000000 /* section near gp */ +#define SHF_IA_64_NORECOV 0x20000000 /* spec insns w/o recovery */ + +/* Processor specific values for the Dyn d_tag field. */ +#define DT_IA_64_PLT_RESERVE (DT_LOPROC + 0) +#define DT_IA_64_NUM 1 + +/* IA-64 relocations. */ +#define R_IA64_NONE 0x00 /* none */ +#define R_IA64_IMM14 0x21 /* symbol + addend, add imm14 */ +#define R_IA64_IMM22 0x22 /* symbol + addend, add imm22 */ +#define R_IA64_IMM64 0x23 /* symbol + addend, mov imm64 */ +#define R_IA64_DIR32MSB 0x24 /* symbol + addend, data4 MSB */ +#define R_IA64_DIR32LSB 0x25 /* symbol + addend, data4 LSB */ +#define R_IA64_DIR64MSB 0x26 /* symbol + addend, data8 MSB */ +#define R_IA64_DIR64LSB 0x27 /* symbol + addend, data8 LSB */ +#define R_IA64_GPREL22 0x2a /* @gprel(sym + add), add imm22 */ +#define R_IA64_GPREL64I 0x2b /* @gprel(sym + add), mov imm64 */ +#define R_IA64_GPREL32MSB 0x2c /* @gprel(sym + add), data4 MSB */ +#define R_IA64_GPREL32LSB 0x2d /* @gprel(sym + add), data4 LSB */ +#define R_IA64_GPREL64MSB 0x2e /* @gprel(sym + add), data8 MSB */ +#define R_IA64_GPREL64LSB 0x2f /* @gprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF22 0x32 /* @ltoff(sym + add), add imm22 */ +#define R_IA64_LTOFF64I 0x33 /* @ltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF22 0x3a /* @pltoff(sym + add), add imm22 */ +#define R_IA64_PLTOFF64I 0x3b /* @pltoff(sym + add), mov imm64 */ +#define R_IA64_PLTOFF64MSB 0x3e /* @pltoff(sym + add), data8 MSB */ +#define R_IA64_PLTOFF64LSB 0x3f /* @pltoff(sym + add), data8 LSB */ +#define R_IA64_FPTR64I 0x43 /* @fptr(sym + add), mov imm64 */ +#define R_IA64_FPTR32MSB 0x44 /* @fptr(sym + add), data4 MSB */ +#define R_IA64_FPTR32LSB 0x45 /* @fptr(sym + add), data4 LSB */ +#define R_IA64_FPTR64MSB 0x46 /* @fptr(sym + add), data8 MSB */ +#define R_IA64_FPTR64LSB 0x47 /* @fptr(sym + add), data8 LSB */ +#define R_IA64_PCREL60B 0x48 /* @pcrel(sym + add), brl */ +#define R_IA64_PCREL21B 0x49 /* @pcrel(sym + add), ptb, call */ +#define R_IA64_PCREL21M 0x4a /* @pcrel(sym + add), chk.s */ +#define R_IA64_PCREL21F 0x4b /* @pcrel(sym + add), fchkf */ +#define R_IA64_PCREL32MSB 0x4c /* @pcrel(sym + add), data4 MSB */ +#define R_IA64_PCREL32LSB 0x4d /* @pcrel(sym + add), data4 LSB */ +#define R_IA64_PCREL64MSB 0x4e /* @pcrel(sym + add), data8 MSB */ +#define R_IA64_PCREL64LSB 0x4f /* @pcrel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_FPTR22 0x52 /* @ltoff(@fptr(s+a)), imm22 */ +#define R_IA64_LTOFF_FPTR64I 0x53 /* @ltoff(@fptr(s+a)), imm64 */ +#define R_IA64_LTOFF_FPTR32MSB 0x54 /* @ltoff(@fptr(s+a)), data4 MSB */ +#define R_IA64_LTOFF_FPTR32LSB 0x55 /* @ltoff(@fptr(s+a)), data4 LSB */ +#define R_IA64_LTOFF_FPTR64MSB 0x56 /* @ltoff(@fptr(s+a)), data8 MSB */ +#define R_IA64_LTOFF_FPTR64LSB 0x57 /* @ltoff(@fptr(s+a)), data8 LSB */ +#define R_IA64_SEGREL32MSB 0x5c /* @segrel(sym + add), data4 MSB */ +#define R_IA64_SEGREL32LSB 0x5d /* @segrel(sym + add), data4 LSB */ +#define R_IA64_SEGREL64MSB 0x5e /* @segrel(sym + add), data8 MSB */ +#define R_IA64_SEGREL64LSB 0x5f /* @segrel(sym + add), data8 LSB */ +#define R_IA64_SECREL32MSB 0x64 /* @secrel(sym + add), data4 MSB */ +#define R_IA64_SECREL32LSB 0x65 /* @secrel(sym + add), data4 LSB */ +#define R_IA64_SECREL64MSB 0x66 /* @secrel(sym + add), data8 MSB */ +#define R_IA64_SECREL64LSB 0x67 /* @secrel(sym + add), data8 LSB */ +#define R_IA64_REL32MSB 0x6c /* data 4 + REL */ +#define R_IA64_REL32LSB 0x6d /* data 4 + REL */ +#define R_IA64_REL64MSB 0x6e /* data 8 + REL */ +#define R_IA64_REL64LSB 0x6f /* data 8 + REL */ +#define R_IA64_LTV32MSB 0x74 /* symbol + addend, data4 MSB */ +#define R_IA64_LTV32LSB 0x75 /* symbol + addend, data4 LSB */ +#define R_IA64_LTV64MSB 0x76 /* symbol + addend, data8 MSB */ +#define R_IA64_LTV64LSB 0x77 /* symbol + addend, data8 LSB */ +#define R_IA64_PCREL21BI 0x79 /* @pcrel(sym + add), 21bit inst */ +#define R_IA64_PCREL22 0x7a /* @pcrel(sym + add), 22bit inst */ +#define R_IA64_PCREL64I 0x7b /* @pcrel(sym + add), 64bit inst */ +#define R_IA64_IPLTMSB 0x80 /* dynamic reloc, imported PLT, MSB */ +#define R_IA64_IPLTLSB 0x81 /* dynamic reloc, imported PLT, LSB */ +#define R_IA64_COPY 0x84 /* copy relocation */ +#define R_IA64_SUB 0x85 /* Addend and symbol difference */ +#define R_IA64_LTOFF22X 0x86 /* LTOFF22, relaxable. */ +#define R_IA64_LDXMOV 0x87 /* Use of LTOFF22X. */ +#define R_IA64_TPREL14 0x91 /* @tprel(sym + add), imm14 */ +#define R_IA64_TPREL22 0x92 /* @tprel(sym + add), imm22 */ +#define R_IA64_TPREL64I 0x93 /* @tprel(sym + add), imm64 */ +#define R_IA64_TPREL64MSB 0x96 /* @tprel(sym + add), data8 MSB */ +#define R_IA64_TPREL64LSB 0x97 /* @tprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_TPREL22 0x9a /* @ltoff(@tprel(s+a)), imm2 */ +#define R_IA64_DTPMOD64MSB 0xa6 /* @dtpmod(sym + add), data8 MSB */ +#define R_IA64_DTPMOD64LSB 0xa7 /* @dtpmod(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPMOD22 0xaa /* @ltoff(@dtpmod(sym + add)), imm22 */ +#define R_IA64_DTPREL14 0xb1 /* @dtprel(sym + add), imm14 */ +#define R_IA64_DTPREL22 0xb2 /* @dtprel(sym + add), imm22 */ +#define R_IA64_DTPREL64I 0xb3 /* @dtprel(sym + add), imm64 */ +#define R_IA64_DTPREL32MSB 0xb4 /* @dtprel(sym + add), data4 MSB */ +#define R_IA64_DTPREL32LSB 0xb5 /* @dtprel(sym + add), data4 LSB */ +#define R_IA64_DTPREL64MSB 0xb6 /* @dtprel(sym + add), data8 MSB */ +#define R_IA64_DTPREL64LSB 0xb7 /* @dtprel(sym + add), data8 LSB */ +#define R_IA64_LTOFF_DTPREL22 0xba /* @ltoff(@dtprel(s+a)), imm22 */ + +/* SH specific declarations */ + +/* SH relocs. */ +#define R_SH_NONE 0 +#define R_SH_DIR32 1 +#define R_SH_REL32 2 +#define R_SH_DIR8WPN 3 +#define R_SH_IND12W 4 +#define R_SH_DIR8WPL 5 +#define R_SH_DIR8WPZ 6 +#define R_SH_DIR8BP 7 +#define R_SH_DIR8W 8 +#define R_SH_DIR8L 9 +#define R_SH_SWITCH16 25 +#define R_SH_SWITCH32 26 +#define R_SH_USES 27 +#define R_SH_COUNT 28 +#define R_SH_ALIGN 29 +#define R_SH_CODE 30 +#define R_SH_DATA 31 +#define R_SH_LABEL 32 +#define R_SH_SWITCH8 33 +#define R_SH_GNU_VTINHERIT 34 +#define R_SH_GNU_VTENTRY 35 +#define R_SH_TLS_GD_32 144 +#define R_SH_TLS_LD_32 145 +#define R_SH_TLS_LDO_32 146 +#define R_SH_TLS_IE_32 147 +#define R_SH_TLS_LE_32 148 +#define R_SH_TLS_DTPMOD32 149 +#define R_SH_TLS_DTPOFF32 150 +#define R_SH_TLS_TPOFF32 151 +#define R_SH_GOT32 160 +#define R_SH_PLT32 161 +#define R_SH_COPY 162 +#define R_SH_GLOB_DAT 163 +#define R_SH_JMP_SLOT 164 +#define R_SH_RELATIVE 165 +#define R_SH_GOTOFF 166 +#define R_SH_GOTPC 167 +/* Keep this the last entry. */ +#define R_SH_NUM 256 + +/* Additional s390 relocs */ + +#define R_390_NONE 0 /* No reloc. */ +#define R_390_8 1 /* Direct 8 bit. */ +#define R_390_12 2 /* Direct 12 bit. */ +#define R_390_16 3 /* Direct 16 bit. */ +#define R_390_32 4 /* Direct 32 bit. */ +#define R_390_PC32 5 /* PC relative 32 bit. */ +#define R_390_GOT12 6 /* 12 bit GOT offset. */ +#define R_390_GOT32 7 /* 32 bit GOT offset. */ +#define R_390_PLT32 8 /* 32 bit PC relative PLT address. */ +#define R_390_COPY 9 /* Copy symbol at runtime. */ +#define R_390_GLOB_DAT 10 /* Create GOT entry. */ +#define R_390_JMP_SLOT 11 /* Create PLT entry. */ +#define R_390_RELATIVE 12 /* Adjust by program base. */ +#define R_390_GOTOFF32 13 /* 32 bit offset to GOT. */ +#define R_390_GOTPC 14 /* 32 bit PC relative offset to GOT. */ +#define R_390_GOT16 15 /* 16 bit GOT offset. */ +#define R_390_PC16 16 /* PC relative 16 bit. */ +#define R_390_PC16DBL 17 /* PC relative 16 bit shifted by 1. */ +#define R_390_PLT16DBL 18 /* 16 bit PC rel. PLT shifted by 1. */ +#define R_390_PC32DBL 19 /* PC relative 32 bit shifted by 1. */ +#define R_390_PLT32DBL 20 /* 32 bit PC rel. PLT shifted by 1. */ +#define R_390_GOTPCDBL 21 /* 32 bit PC rel. GOT shifted by 1. */ +#define R_390_64 22 /* Direct 64 bit. */ +#define R_390_PC64 23 /* PC relative 64 bit. */ +#define R_390_GOT64 24 /* 64 bit GOT offset. */ +#define R_390_PLT64 25 /* 64 bit PC relative PLT address. */ +#define R_390_GOTENT 26 /* 32 bit PC rel. to GOT entry >> 1. */ +#define R_390_GOTOFF16 27 /* 16 bit offset to GOT. */ +#define R_390_GOTOFF64 28 /* 64 bit offset to GOT. */ +#define R_390_GOTPLT12 29 /* 12 bit offset to jump slot. */ +#define R_390_GOTPLT16 30 /* 16 bit offset to jump slot. */ +#define R_390_GOTPLT32 31 /* 32 bit offset to jump slot. */ +#define R_390_GOTPLT64 32 /* 64 bit offset to jump slot. */ +#define R_390_GOTPLTENT 33 /* 32 bit rel. offset to jump slot. */ +#define R_390_PLTOFF16 34 /* 16 bit offset from GOT to PLT. */ +#define R_390_PLTOFF32 35 /* 32 bit offset from GOT to PLT. */ +#define R_390_PLTOFF64 36 /* 16 bit offset from GOT to PLT. */ +#define R_390_TLS_LOAD 37 /* Tag for load insn in TLS code. */ +#define R_390_TLS_GDCALL 38 /* Tag for function call in general + dynamic TLS code. */ +#define R_390_TLS_LDCALL 39 /* Tag for function call in local + dynamic TLS code. */ +#define R_390_TLS_GD32 40 /* Direct 32 bit for general dynamic + thread local data. */ +#define R_390_TLS_GD64 41 /* Direct 64 bit for general dynamic + thread local data. */ +#define R_390_TLS_GOTIE12 42 /* 12 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE32 43 /* 32 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_GOTIE64 44 /* 64 bit GOT offset for static TLS + block offset. */ +#define R_390_TLS_LDM32 45 /* Direct 32 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_LDM64 46 /* Direct 64 bit for local dynamic + thread local data in LE code. */ +#define R_390_TLS_IE32 47 /* 32 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IE64 48 /* 64 bit address of GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_IEENT 49 /* 32 bit rel. offset to GOT entry for + negated static TLS block offset. */ +#define R_390_TLS_LE32 50 /* 32 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LE64 51 /* 64 bit negated offset relative to + static TLS block. */ +#define R_390_TLS_LDO32 52 /* 32 bit offset relative to TLS + block. */ +#define R_390_TLS_LDO64 53 /* 64 bit offset relative to TLS + block. */ +#define R_390_TLS_DTPMOD 54 /* ID of module containing symbol. */ +#define R_390_TLS_DTPOFF 55 /* Offset in TLS block. */ +#define R_390_TLS_TPOFF 56 /* Negated offset in static TLS + block. */ +#define R_390_20 57 /* Direct 20 bit. */ +#define R_390_GOT20 58 /* 20 bit GOT offset. */ +#define R_390_GOTPLT20 59 /* 20 bit offset to jump slot. */ +#define R_390_TLS_GOTIE20 60 /* 20 bit GOT offset for static TLS + block offset. */ +/* Keep this the last entry. */ +#define R_390_NUM 61 + + +/* CRIS relocations. */ +#define R_CRIS_NONE 0 +#define R_CRIS_8 1 +#define R_CRIS_16 2 +#define R_CRIS_32 3 +#define R_CRIS_8_PCREL 4 +#define R_CRIS_16_PCREL 5 +#define R_CRIS_32_PCREL 6 +#define R_CRIS_GNU_VTINHERIT 7 +#define R_CRIS_GNU_VTENTRY 8 +#define R_CRIS_COPY 9 +#define R_CRIS_GLOB_DAT 10 +#define R_CRIS_JUMP_SLOT 11 +#define R_CRIS_RELATIVE 12 +#define R_CRIS_16_GOT 13 +#define R_CRIS_32_GOT 14 +#define R_CRIS_16_GOTPLT 15 +#define R_CRIS_32_GOTPLT 16 +#define R_CRIS_32_GOTREL 17 +#define R_CRIS_32_PLT_GOTREL 18 +#define R_CRIS_32_PLT_PCREL 19 + +#define R_CRIS_NUM 20 + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + + +/* AM33 relocations. */ +#define R_MN10300_NONE 0 /* No reloc. */ +#define R_MN10300_32 1 /* Direct 32 bit. */ +#define R_MN10300_16 2 /* Direct 16 bit. */ +#define R_MN10300_8 3 /* Direct 8 bit. */ +#define R_MN10300_PCREL32 4 /* PC-relative 32-bit. */ +#define R_MN10300_PCREL16 5 /* PC-relative 16-bit signed. */ +#define R_MN10300_PCREL8 6 /* PC-relative 8-bit signed. */ +#define R_MN10300_GNU_VTINHERIT 7 /* Ancient C++ vtable garbage... */ +#define R_MN10300_GNU_VTENTRY 8 /* ... collection annotation. */ +#define R_MN10300_24 9 /* Direct 24 bit. */ +#define R_MN10300_GOTPC32 10 /* 32-bit PCrel offset to GOT. */ +#define R_MN10300_GOTPC16 11 /* 16-bit PCrel offset to GOT. */ +#define R_MN10300_GOTOFF32 12 /* 32-bit offset from GOT. */ +#define R_MN10300_GOTOFF24 13 /* 24-bit offset from GOT. */ +#define R_MN10300_GOTOFF16 14 /* 16-bit offset from GOT. */ +#define R_MN10300_PLT32 15 /* 32-bit PCrel to PLT entry. */ +#define R_MN10300_PLT16 16 /* 16-bit PCrel to PLT entry. */ +#define R_MN10300_GOT32 17 /* 32-bit offset to GOT entry. */ +#define R_MN10300_GOT24 18 /* 24-bit offset to GOT entry. */ +#define R_MN10300_GOT16 19 /* 16-bit offset to GOT entry. */ +#define R_MN10300_COPY 20 /* Copy symbol at runtime. */ +#define R_MN10300_GLOB_DAT 21 /* Create GOT entry. */ +#define R_MN10300_JMP_SLOT 22 /* Create PLT entry. */ +#define R_MN10300_RELATIVE 23 /* Adjust by program base. */ + +#define R_MN10300_NUM 24 + + +/* M32R relocs. */ +#define R_M32R_NONE 0 /* No reloc. */ +#define R_M32R_16 1 /* Direct 16 bit. */ +#define R_M32R_32 2 /* Direct 32 bit. */ +#define R_M32R_24 3 /* Direct 24 bit. */ +#define R_M32R_10_PCREL 4 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL 5 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL 6 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO 7 /* High 16 bit with unsigned low. */ +#define R_M32R_HI16_SLO 8 /* High 16 bit with signed low. */ +#define R_M32R_LO16 9 /* Low 16 bit. */ +#define R_M32R_SDA16 10 /* 16 bit offset in SDA. */ +#define R_M32R_GNU_VTINHERIT 11 +#define R_M32R_GNU_VTENTRY 12 +/* M32R relocs use SHT_RELA. */ +#define R_M32R_16_RELA 33 /* Direct 16 bit. */ +#define R_M32R_32_RELA 34 /* Direct 32 bit. */ +#define R_M32R_24_RELA 35 /* Direct 24 bit. */ +#define R_M32R_10_PCREL_RELA 36 /* PC relative 10 bit shifted. */ +#define R_M32R_18_PCREL_RELA 37 /* PC relative 18 bit shifted. */ +#define R_M32R_26_PCREL_RELA 38 /* PC relative 26 bit shifted. */ +#define R_M32R_HI16_ULO_RELA 39 /* High 16 bit with unsigned low */ +#define R_M32R_HI16_SLO_RELA 40 /* High 16 bit with signed low */ +#define R_M32R_LO16_RELA 41 /* Low 16 bit */ +#define R_M32R_SDA16_RELA 42 /* 16 bit offset in SDA */ +#define R_M32R_RELA_GNU_VTINHERIT 43 +#define R_M32R_RELA_GNU_VTENTRY 44 + +#define R_M32R_GOT24 48 /* 24 bit GOT entry */ +#define R_M32R_26_PLTREL 49 /* 26 bit PC relative to PLT shifted */ +#define R_M32R_COPY 50 /* Copy symbol at runtime */ +#define R_M32R_GLOB_DAT 51 /* Create GOT entry */ +#define R_M32R_JMP_SLOT 52 /* Create PLT entry */ +#define R_M32R_RELATIVE 53 /* Adjust by program base */ +#define R_M32R_GOTOFF 54 /* 24 bit offset to GOT */ +#define R_M32R_GOTPC24 55 /* 24 bit PC relative offset to GOT */ +#define R_M32R_GOT16_HI_ULO 56 /* High 16 bit GOT entry with unsigned + low */ +#define R_M32R_GOT16_HI_SLO 57 /* High 16 bit GOT entry with signed + low */ +#define R_M32R_GOT16_LO 58 /* Low 16 bit GOT entry */ +#define R_M32R_GOTPC_HI_ULO 59 /* High 16 bit PC relative offset to + GOT with unsigned low */ +#define R_M32R_GOTPC_HI_SLO 60 /* High 16 bit PC relative offset to + GOT with signed low */ +#define R_M32R_GOTPC_LO 61 /* Low 16 bit PC relative offset to + GOT */ +#define R_M32R_GOTOFF_HI_ULO 62 /* High 16 bit offset to GOT + with unsigned low */ +#define R_M32R_GOTOFF_HI_SLO 63 /* High 16 bit offset to GOT + with signed low */ +#define R_M32R_GOTOFF_LO 64 /* Low 16 bit offset to GOT */ +#define R_M32R_NUM 256 /* Keep this the last entry. */ + + +__END_DECLS + +#endif /* elf.h */ diff --git a/trunk/src/exec.c b/trunk/src/exec.c new file mode 100644 index 0000000..7c8f38f --- /dev/null +++ b/trunk/src/exec.c @@ -0,0 +1,1068 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" +#include "space.h" + +int +update_dynamic_tags (DSO *dso, GElf_Shdr *shdr, GElf_Shdr *old_shdr, + struct section_move *move) +{ + int i, j; + + for (i = 1; i < move->new_shnum; ++i) + { + j = move->new_to_old[i]; + if (j == -1) + continue; + if ((dynamic_info_is_set (dso, DT_HASH) + && dso->info[DT_HASH] == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_HASH + && set_dynamic (dso, DT_HASH, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_SYMTAB) + && dso->info[DT_SYMTAB] == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_DYNSYM + && set_dynamic (dso, DT_SYMTAB, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_STRTAB) + && dso->info[DT_STRTAB] == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_STRTAB + && set_dynamic (dso, DT_STRTAB, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_VERDEF_BIT) + && dso->info_DT_VERDEF == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_GNU_verdef + && set_dynamic (dso, DT_VERDEF, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_VERNEED_BIT) + && dso->info_DT_VERNEED == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_GNU_verneed + && set_dynamic (dso, DT_VERNEED, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_VERSYM_BIT) + && dso->info_DT_VERSYM == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_GNU_versym + && set_dynamic (dso, DT_VERSYM, shdr[i].sh_addr, 1)) + || (dynamic_info_is_set (dso, DT_GNU_HASH_BIT) + && dso->info_DT_GNU_HASH == old_shdr[j].sh_addr + && old_shdr[j].sh_type == SHT_GNU_HASH + && set_dynamic (dso, DT_GNU_HASH, shdr[i].sh_addr, 1))) + return 1; + } + + return 0; +} + +int +prelink_exec (struct prelink_info *info) +{ + int i, j, ndeps = info->ent->ndepends + 1; + int dynstrndx, dynstrndxnew, growdynstr = 0, shstrndxnew; + int old_conflict = 0, old_liblist = 0; + int new_conflict = -1, new_liblist = -1; + int new_reloc = -1, new_plt = -1, new_dynstr = -1; + int old_dynbss = -1, old_bss = -1, new_dynbss = -1; + int old_sdynbss = -1, old_sbss = -1, new_sdynbss = -1; + int addcnt, undo, shnum_after_undo; + struct reloc_info rinfo, rinfonew; + DSO *dso = info->dso; + GElf_Ehdr ehdr; + GElf_Phdr phdr[dso->ehdr.e_phnum + 1]; + GElf_Shdr old_shdr[dso->ehdr.e_shnum], new_shdr[dso->ehdr.e_shnum + 20]; + GElf_Shdr shdr_after_undo[dso->ehdr.e_shnum + 20]; + GElf_Shdr *shdr; + Elf32_Lib *liblist = NULL; + struct readonly_adjust adjust; + struct section_move *move = NULL; + + if (prelink_build_conflicts (info)) + return 1; + + if (find_reloc_sections (dso, &rinfo)) + return 1; + + move = init_section_move (dso); + if (move == NULL) + return 1; + + ehdr = dso->ehdr; + memcpy (phdr, dso->phdr, dso->ehdr.e_phnum * sizeof (GElf_Phdr)); + memcpy (old_shdr, dso->shdr, dso->ehdr.e_shnum * sizeof (GElf_Shdr)); + shdr = new_shdr; + memcpy (shdr, dso->shdr, dso->ehdr.e_shnum * sizeof (GElf_Shdr)); + + for (undo = 1; undo < dso->ehdr.e_shnum; ++undo) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[undo].sh_name), + ".gnu.prelink_undo")) + break; + + if (undo < dso->ehdr.e_shnum) + { + Elf_Data *data; + + if (undo_sections (dso, undo, move, &rinfo, &ehdr, phdr, shdr)) + { +error_out: + free (liblist); + free (move); + return 1; + } + + data = elf_getdata (dso->scn[undo], NULL); + assert (data->d_buf != NULL); + assert (data->d_off == 0); + assert (data->d_size == dso->shdr[undo].sh_size); + dso->undo = *data; + dso->undo.d_buf = malloc (dso->undo.d_size); + if (dso->undo.d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not create .gnu.prelink_undo section", + dso->filename); + goto error_out; + } + memcpy (dso->undo.d_buf, data->d_buf, data->d_size); + ehdr.e_shstrndx = dso->ehdr.e_shstrndx; + } + undo = 0; + + memcpy (shdr_after_undo, shdr, ehdr.e_shnum * sizeof (GElf_Shdr)); + + for (dynstrndx = 1; dynstrndx < dso->ehdr.e_shnum; ++dynstrndx) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[dynstrndx].sh_name), + ".dynstr")) + break; + + if (dynstrndx == dso->ehdr.e_shnum) + { + error (0, 0, "%s: Could not find .dynstr section", dso->filename); + goto error_out; + } + + dynstrndxnew = move->old_to_new[dynstrndx]; + shstrndxnew = move->old_to_new[dso->ehdr.e_shstrndx]; + shnum_after_undo = move->new_shnum; + + if (ndeps > 1) + { + liblist = calloc (ndeps - 1, sizeof (Elf32_Lib)); + if (liblist == NULL) + { + error (0, ENOMEM, "%s: Cannot build .gnu.liblist section", + dso->filename); + goto error_out; + } + } + else + liblist = NULL; + + for (i = 0; i < ndeps - 1; ++i) + { + struct prelink_entry *ent = info->ent->depends[i]; + + liblist[i].l_name = strtabfind (dso, dynstrndx, info->sonames[i + 1]); + if (liblist[i].l_name >= shdr[dynstrndxnew].sh_size) + liblist[i].l_name = 0; + if (liblist[i].l_name == 0) + growdynstr += strlen (info->sonames[i + 1]) + 1; + liblist[i].l_time_stamp = ent->timestamp; + liblist[i].l_checksum = ent->checksum; + } + + if (info->dynbss) + { + old_bss = addr_to_sec (dso, info->dynbss_base); + assert (old_bss != -1); + if (move->old_to_new[old_bss] == -1) + ++old_bss; + assert (move->old_to_new[old_bss] != -1); + assert (shdr[move->old_to_new[old_bss]].sh_addr <= info->dynbss_base); + assert (shdr[move->old_to_new[old_bss]].sh_addr + + shdr[move->old_to_new[old_bss]].sh_size > info->dynbss_base); + } + if (info->sdynbss) + { + old_sbss = addr_to_sec (dso, info->sdynbss_base); + assert (old_sbss != -1); + if (move->old_to_new[old_sbss] == -1) + ++old_sbss; + assert (move->old_to_new[old_sbss] != -1); + assert (shdr[move->old_to_new[old_sbss]].sh_addr <= info->sdynbss_base); + assert (shdr[move->old_to_new[old_sbss]].sh_addr + + shdr[move->old_to_new[old_sbss]].sh_size > info->sdynbss_base); + } + + rinfonew = rinfo; + if (rinfo.first != -1) + { + rinfonew.first = move->old_to_new[rinfo.first]; + rinfonew.last = move->old_to_new[rinfo.last]; + if (shdr[rinfonew.first].sh_type == SHT_REL + && dso->shdr[rinfo.first].sh_type == SHT_RELA) + { + rinfonew.rel_to_rela = 1; + rinfonew.reldyn_rela = 0; + } + } + if (rinfo.plt != -1) + { + rinfonew.plt = move->old_to_new[rinfo.plt]; + if (shdr[rinfonew.plt].sh_type == SHT_REL + && dso->shdr[rinfo.plt].sh_type == SHT_RELA) + { + rinfonew.rel_to_rela_plt = 1; + rinfonew.plt_rela = 0; + } + } + + for (i = 1, j = 1; i < ehdr.e_shnum; ++i) + { + const char *name; + name = strptr (dso, dso->ehdr.e_shstrndx, shdr[i].sh_name); + if (! strcmp (name, ".dynbss")) + old_dynbss = move->new_to_old[j]; + else if (! strcmp (name, ".sdynbss")) + old_sdynbss = move->new_to_old[j]; + else if (! strcmp (name, ".gnu.prelink_undo")) + undo = -1; + if (! strcmp (name, ".gnu.conflict")) + { + old_conflict = move->new_to_old[j]; + remove_section (move, j); + } + else if (! strcmp (name, ".gnu.liblist")) + { + old_liblist = move->new_to_old[j]; + remove_section (move, j); + } + else if (rinfonew.rel_to_rela + && i >= rinfonew.first && i <= rinfonew.last) + remove_section (move, j); + else if (i == rinfonew.plt + && (rinfonew.rel_to_rela || rinfonew.rel_to_rela_plt)) + remove_section (move, j); + else if (i == dynstrndxnew && growdynstr) + remove_section (move, j); + else + shdr[j++] = shdr[i]; + } + assert (j == move->new_shnum); + ehdr.e_shnum = j; + + if (old_sdynbss != -1 && old_dynbss == -1) + { + old_dynbss = old_sdynbss; + old_sdynbss = -1; + } + + GElf_Shdr add[rinfo.last - rinfo.first + 5]; + int old[rinfo.last - rinfo.first + 5]; + int new[rinfo.last - rinfo.first + 5]; + memset (add, 0, sizeof (add)); + memset (old, 0, sizeof (old)); + memset (new, 0, sizeof (new)); + + i = 0; + if (rinfonew.rel_to_rela) + { + add[i] = shdr_after_undo[rinfonew.first]; + add[i].sh_size = shdr_after_undo[rinfonew.last].sh_addr + + shdr_after_undo[rinfonew.last].sh_size + - add[i].sh_addr; + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + add[i].sh_size = add[i].sh_size / 2 * 3; + old[i] = rinfo.first; + new_reloc = i++; + for (j = rinfo.first + 1; j <= rinfo.last; ++j) + { + add[i] = shdr_after_undo[rinfonew.first - rinfo.first + j]; + add[i].sh_size = add[i].sh_size / 2 * 3; + old[i++] = j; + } + if (rinfonew.plt) + { + add[i] = shdr_after_undo[rinfonew.plt]; + if (rinfonew.rel_to_rela_plt) + add[i].sh_size = add[i].sh_size / 2 * 3; + /* Temporarily merge them, so that they are allocated adjacently. */ + add[new_reloc].sh_size += add[i].sh_size; + old[i] = rinfo.plt; + new_plt = i++; + } + } + else if (rinfonew.rel_to_rela_plt) + { + add[i] = shdr_after_undo[rinfonew.plt]; + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + add[i].sh_size = add[i].sh_size / 2 * 3; + old[i] = rinfo.plt; + new_plt = i++; + } + if (growdynstr) + { + add[i] = shdr_after_undo[dynstrndxnew]; + add[i].sh_size += growdynstr; + old[i] = dynstrndx; + new_dynstr = i++; + } + add[i].sh_flags = SHF_ALLOC; + add[i].sh_type = SHT_GNU_LIBLIST; + add[i].sh_size = (ndeps - 1) * sizeof (Elf32_Lib); + add[i].sh_addralign = sizeof (GElf_Word); + add[i].sh_entsize = sizeof (Elf32_Lib); + old[i] = old_liblist; + new_liblist = i++; + if (info->conflict_rela_size) + { + add[i].sh_flags = SHF_ALLOC; + add[i].sh_type = SHT_RELA; + add[i].sh_entsize = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + add[i].sh_size = info->conflict_rela_size * add[i].sh_entsize; + add[i].sh_addralign = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + old[i] = old_conflict; + new_conflict = i++; + } + addcnt = i; + memset (&adjust, 0, sizeof (adjust)); + adjust.new = new; + adjust.move = move; + + for (i = 0; i < addcnt; ++i) + { + new[i] = find_readonly_space (dso, add + i, &ehdr, phdr, shdr, &adjust); + if (new[i] == 0) + goto error_out; + add_section (move, new[i]); + ++adjust.newcount; + if (old[i]) + { + move->old_to_new[old[i]] = new[i]; + move->new_to_old[new[i]] = old[i]; + } + if (i == new_reloc) + { + int k, l = new[new_reloc]; + + j = rinfo.last - rinfo.first + (new_plt != -1); + shdr[l].sh_size = shdr_after_undo[rinfonew.first].sh_size / 2 * 3; + for (k = 1; k <= j; ++k) + { + insert_readonly_section (&ehdr, shdr, l + k, &adjust); + shdr[l + k] = add[new_reloc + k]; + shdr[l + k].sh_addr = shdr[l + k - 1].sh_addr + + shdr[l + k - 1].sh_size; + shdr[l + k].sh_offset = shdr[l + k - 1].sh_offset + + shdr[l + k - 1].sh_size; + new[++i] = l + k; + add_section (move, l + k); + move->old_to_new[rinfo.first + k] = l + k; + move->new_to_old[l + k] = rinfo.first + k; + ++adjust.newcount; + } + } + } + + if (info->sdynbss) + { + if (old_sdynbss == -1) + { + new_sdynbss = move->old_to_new[old_sbss]; + memmove (&shdr[new_sdynbss + 1], &shdr[new_sdynbss], + (ehdr.e_shnum - new_sdynbss) * sizeof (GElf_Shdr)); + shdr[new_sdynbss].sh_size = 0; + ++ehdr.e_shnum; + add_section (move, new_sdynbss); + for (i = 0; i < addcnt; ++i) + if (new[i] >= new_sdynbss) + ++new[i]; + } + else + new_sdynbss = move->old_to_new[old_sdynbss]; + } + + if (info->dynbss) + { + if (old_dynbss == -1) + { + new_dynbss = move->old_to_new[old_bss]; + memmove (&shdr[new_dynbss + 1], &shdr[new_dynbss], + (ehdr.e_shnum - new_dynbss) * sizeof (GElf_Shdr)); + shdr[new_dynbss].sh_size = 0; + ++ehdr.e_shnum; + add_section (move, new_dynbss); + for (i = 0; i < addcnt; ++i) + if (new[i] >= new_dynbss) + ++new[i]; + } + else + new_dynbss = move->old_to_new[old_dynbss]; + } + + if (undo != -1) + { + undo = move->old_to_new[dso->ehdr.e_shstrndx]; + memmove (&shdr[undo + 1], &shdr[undo], + (ehdr.e_shnum - undo) * sizeof (GElf_Shdr)); + memset (&shdr[undo], 0, sizeof (shdr[undo])); + shdr[undo].sh_type = SHT_PROGBITS; + shdr[undo].sh_addralign = dso->undo.d_align; + ++ehdr.e_shnum; + for (i = 0; i < addcnt; ++i) + if (new[i] >= undo) + ++new[i]; + add_section (move, undo); + } + + i = ehdr.e_shnum; + ehdr.e_shnum = dso->ehdr.e_shnum; + dso->ehdr = ehdr; + memcpy (dso->phdr, phdr, ehdr.e_phnum * sizeof (GElf_Phdr)); + if (reopen_dso (dso, move, NULL)) + goto error_out; + + assert (i == dso->ehdr.e_shnum); + + if (shnum_after_undo != move->new_shnum) + adjust_nonalloc (dso, &dso->ehdr, shdr, 0, + dso->ehdr.e_shoff + 1, + ((long) move->new_shnum - (long) shnum_after_undo) + * gelf_fsize (dso->elf, ELF_T_SHDR, 1, EV_CURRENT)); + + if (shdr_after_undo[shstrndxnew].sh_size + < dso->shdr[dso->ehdr.e_shstrndx].sh_size) + { + Elf_Data *data = elf_getdata (dso->scn[dso->ehdr.e_shstrndx], NULL); + + assert (elf_getdata (dso->scn[dso->ehdr.e_shstrndx], data) == NULL); + assert (data->d_off == 0); + assert (shdr_after_undo[shstrndxnew].sh_size + == shdr[dso->ehdr.e_shstrndx].sh_size); + assert (data->d_size == dso->shdr[dso->ehdr.e_shstrndx].sh_size); + data->d_size = shdr_after_undo[shstrndxnew].sh_size; + } + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (move->new_to_old[i] == -1) + dso->shdr[i] = shdr[i]; + else + { + if (shdr[i].sh_type == SHT_PROGBITS + && dso->shdr[i].sh_type == SHT_NOBITS) + { + Elf_Data *data = elf_getdata (dso->scn[i], NULL); + + assert (data->d_buf == NULL); + data->d_size = shdr[i].sh_size; + if (data->d_size) + { + data->d_buf = calloc (shdr[i].sh_size, 1); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS", + dso->filename); + goto error_out; + } + } + data->d_type = ELF_T_BYTE; + } + dso->shdr[i].sh_type = shdr[i].sh_type; + dso->shdr[i].sh_addr = shdr[i].sh_addr; + dso->shdr[i].sh_size = shdr[i].sh_size; + dso->shdr[i].sh_offset = shdr[i].sh_offset; + } + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD) + { + GElf_Addr last_offset = dso->phdr[i].p_offset; + GElf_Addr adj = 0; + int sfirst = 0, slast = 0, last = 0; + + for (j = 1; j < dso->ehdr.e_shnum; ++j) + if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr + && dso->shdr[j].sh_addr + dso->shdr[j].sh_size + <= dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + { + if (dso->shdr[j].sh_type != SHT_NOBITS + || (dso->shdr[j].sh_flags & SHF_TLS)) + { + if (sfirst) + { + error (0, 0, "%s: NOBITS section followed by non-NOBITS section in the same segment", + dso->filename); + goto error_out; + } + continue; + } + + if (!sfirst) + sfirst = j; + if (strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[j].sh_name), ".plt") == 0) + slast = j + 1; + else if (j == new_dynbss || j == new_sdynbss) + slast = j; + } + + if (sfirst && slast) + { + for (j = sfirst; j < slast; ++j) + { + Elf_Data *data = elf_getdata (dso->scn[j], NULL); + + assert (data->d_size == dso->shdr[j].sh_size + || j == new_dynbss + 1 + || j == new_sdynbss + 1); + if (data->d_size) + { + data->d_buf = realloc (data->d_buf, data->d_size); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS", + dso->filename); + goto error_out; + } + } + memset (data->d_buf, 0, data->d_size); + data->d_type = ELF_T_BYTE; + dso->shdr[j].sh_type = SHT_PROGBITS; + } + + adj = dso->shdr[slast - 1].sh_addr + dso->shdr[slast - 1].sh_size + - dso->phdr[i].p_vaddr; + + if (adj > dso->phdr[i].p_filesz) + { + adj -= dso->phdr[i].p_filesz; + for (j = slast; + j < dso->ehdr.e_shnum + && (dso->shdr[j].sh_flags + & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)); + ++j) + if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr + + dso->phdr[i].p_memsz) + adj = (adj + dso->shdr[j].sh_addralign - 1) + & ~(dso->shdr[j].sh_addralign - 1); + + dso->phdr[i].p_filesz += adj; + } + else + adj = 0; + } + + for (j = 1; j < dso->ehdr.e_shnum; ++j) + if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr + && dso->shdr[j].sh_addr + dso->shdr[j].sh_size + <= dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + { + last = j; + if (dso->shdr[j].sh_type == SHT_NOBITS) + { + last_offset += dso->shdr[j].sh_addralign - 1; + last_offset &= ~(dso->shdr[j].sh_addralign - 1); + if (last_offset > dso->phdr[i].p_offset + + dso->phdr[i].p_filesz) + last_offset = dso->phdr[i].p_offset + + dso->phdr[i].p_filesz; + dso->shdr[j].sh_offset = last_offset; + } + else if (dso->shdr[j].sh_addr + dso->shdr[j].sh_size + > dso->phdr[i].p_vaddr + dso->phdr[i].p_filesz) + { + error (0, 0, "%s: section spans beyond end of segment", + dso->filename); + goto error_out; + } + else + { + dso->shdr[j].sh_offset + = dso->phdr[i].p_offset + dso->shdr[j].sh_addr + - dso->phdr[i].p_vaddr; + last_offset = dso->shdr[j].sh_offset + dso->shdr[j].sh_size; + } + } + + if (adj) + { + for (j = i + 1; j < dso->ehdr.e_phnum; ++j) + if (dso->phdr[j].p_type == PT_LOAD + && dso->phdr[j].p_vaddr >= dso->shdr[slast - 1].sh_addr) + { + dso->phdr[j].p_vaddr += adj; + dso->phdr[j].p_paddr += adj; + dso->phdr[j].p_offset += adj; + } + + j = last + 1; + while (j < dso->ehdr.e_shnum + && (dso->shdr[j].sh_flags + & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR))) + { + dso->shdr[j].sh_offset += adj; + dso->shdr[j++].sh_addr += adj; + } + + if (adjust_dso_nonalloc (dso, last + 1, + dso->shdr[sfirst].sh_offset, + adj)) + goto error_out; + } + } + + /* Adjust .rel*.dyn (or .rel*.*) if necessary. */ + assert (new_reloc == -1 + || (rinfo.last - rinfo.first + == (move->old_to_new[rinfo.last] + - move->old_to_new[rinfo.first]))); + rinfo.first = move->old_to_new[rinfo.first]; + rinfo.last = move->old_to_new[rinfo.last]; + assert (new_reloc == -1 || rinfo.first == new[new_reloc]); + + if (rinfo.rel_to_rela) + { + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + assert (new_reloc != -1); + for (j = rinfo.first; j <= rinfo.last; ++j) + { + dso->shdr[j].sh_size + = dso->shdr[j].sh_size / 3 * 2; + if (convert_rel_to_rela (dso, j)) + goto error_out; + dso->shdr[j].sh_size = shdr[j].sh_size; + } + } + else if (rinfonew.rel_to_rela) + { + assert (new_reloc != -1); + for (j = rinfo.first; j <= rinfo.last; ++j) + { + dso->shdr[j].sh_entsize + = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + dso->shdr[j].sh_type = SHT_RELA; + } + } + + /* Adjust .rel*.plt if necessary. */ + rinfo.plt = move->old_to_new[rinfo.plt]; + if (new_plt != -1) + { + assert (rinfo.plt == new[new_plt]); + if (rinfo.rel_to_rela_plt) + { + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + dso->shdr[rinfo.first].sh_size + = dso->shdr[rinfo.first].sh_size / 3 * 2; + if (convert_rel_to_rela (dso, rinfo.plt)) + goto error_out; + dso->shdr[rinfo.plt].sh_size = shdr[rinfo.plt].sh_size; + } + else if (rinfonew.rel_to_rela_plt) + { + dso->shdr[rinfo.plt].sh_entsize + = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + dso->shdr[rinfo.plt].sh_type = SHT_RELA; + } + } + + /* Add new strings into .dynstr if necessary. */ + if (new_dynstr != -1) + { + Elf_Data *data; + char *ptr; + + i = new[new_dynstr]; + data = elf_getdata (dso->scn[i], NULL); + assert (data->d_off == 0); + data->d_buf = realloc (data->d_buf, dso->shdr[i].sh_size); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not append names needed for .gnu.liblist to .dynstr", + dso->filename); + goto error_out; + } + ptr = data->d_buf + shdr_after_undo[dynstrndxnew].sh_size; + data->d_size = dso->shdr[i].sh_size; + for (j = 0; j < ndeps - 1; ++j) + if (liblist[j].l_name == 0) + { + liblist[j].l_name = ptr - (char *) data->d_buf; + ptr = stpcpy (ptr, info->sonames[j + 1]) + 1; + } + assert (ptr == (char *) data->d_buf + data->d_size); + } + + /* Create or update .sdynbss if necessary. */ + if (new_sdynbss != -1) + { + Elf_Data *data; + + if (old_sdynbss == -1) + { + dso->shdr[new_sdynbss] = dso->shdr[new_sdynbss + 1]; + + dso->shdr[new_sdynbss].sh_name = shstrtabadd (dso, ".sdynbss"); + if (dso->shdr[new_sdynbss].sh_name == 0) + goto error_out; + + dso->shdr[new_sdynbss].sh_size = + info->sdynbss_base + info->sdynbss_size + - dso->shdr[new_sdynbss].sh_addr; + + dso->shdr[new_sdynbss + 1].sh_size + -= dso->shdr[new_sdynbss].sh_size; + dso->shdr[new_sdynbss + 1].sh_addr + += dso->shdr[new_sdynbss].sh_size; + dso->shdr[new_sdynbss + 1].sh_offset + += dso->shdr[new_sdynbss].sh_size; + dso->shdr[new_sdynbss].sh_type = SHT_PROGBITS; + } + else + { + if (dso->shdr[new_sdynbss].sh_type != SHT_PROGBITS + || dso->shdr[new_sdynbss].sh_addr > info->sdynbss_base + || dso->shdr[new_sdynbss].sh_addr + + dso->shdr[new_sdynbss].sh_size + < info->sdynbss_base + info->sdynbss_size) + { + error (0, 0, "%s: Copy relocs don't point into .sdynbss section", + dso->filename); + goto error_out; + } + } + data = elf_getdata (dso->scn[new_sdynbss], NULL); + free (data->d_buf); + data->d_buf = info->sdynbss; + info->sdynbss = NULL; + data->d_off = info->sdynbss_base - dso->shdr[new_sdynbss].sh_addr; + data->d_size = info->sdynbss_size; + data->d_type = ELF_T_BYTE; + if (old_sdynbss == -1) + { + data = elf_getdata (dso->scn[new_sdynbss + 1], NULL); + assert (dso->shdr[new_sdynbss + 1].sh_type != SHT_NOBITS + || data->d_buf == NULL); + if (data->d_size != dso->shdr[new_sdynbss + 1].sh_size) + { + assert (data->d_size == dso->shdr[new_sdynbss].sh_size + + dso->shdr[new_sdynbss + 1].sh_size); + data->d_size -= dso->shdr[new_sdynbss].sh_size; + } + } + } + + /* Create or update .dynbss if necessary. */ + if (new_dynbss != -1) + { + Elf_Data *data; + + if (old_dynbss == -1) + { + GElf_Addr adj; + + dso->shdr[new_dynbss] = dso->shdr[new_dynbss + 1]; + + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[new_dynbss + 1].sh_name), + ".sbss") + && new_sdynbss == -1) + dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".sdynbss"); + else + dso->shdr[new_dynbss].sh_name = shstrtabadd (dso, ".dynbss"); + if (dso->shdr[new_dynbss].sh_name == 0) + goto error_out; + + dso->shdr[new_dynbss].sh_size = + info->dynbss_base + info->dynbss_size + - dso->shdr[new_dynbss].sh_addr; + + dso->shdr[new_dynbss + 1].sh_size + -= dso->shdr[new_dynbss].sh_size; + dso->shdr[new_dynbss + 1].sh_addr + += dso->shdr[new_dynbss].sh_size; + dso->shdr[new_dynbss + 1].sh_offset + += dso->shdr[new_dynbss].sh_size; + dso->shdr[new_dynbss].sh_type = SHT_PROGBITS; + + if (dso->shdr[new_dynbss + 1].sh_type == SHT_NOBITS) + { + GElf_Addr last_offset; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->phdr[i].p_vaddr <= dso->shdr[new_dynbss].sh_addr + && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz + >= info->dynbss_base + info->dynbss_size) + break; + assert (i < dso->ehdr.e_phnum); + + for (j = new_dynbss - 1; j; --j) + { + if (dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr) + break; + if (dso->shdr[j].sh_type == SHT_NOBITS + && (dso->shdr[j].sh_flags & SHF_TLS) == 0) + { + error (0, 0, "%s: COPY relocs not present at start of first SHT_NOBITS section", + dso->filename); + goto error_out; + } + } + + if (dso->phdr[i].p_filesz + < info->dynbss_base + info->dynbss_size + - dso->phdr[i].p_vaddr) + { + dso->phdr[i].p_filesz = + info->dynbss_base + info->dynbss_size + - dso->phdr[i].p_vaddr; + assert (dso->phdr[i].p_filesz <= dso->phdr[i].p_memsz); + } + + adj = dso->phdr[i].p_offset + dso->shdr[new_dynbss].sh_addr + - dso->phdr[i].p_vaddr - dso->shdr[new_dynbss].sh_offset; + + dso->shdr[new_dynbss].sh_offset += adj; + dso->shdr[new_dynbss + 1].sh_offset += adj; + + adj += dso->shdr[new_dynbss].sh_size; + + for (j = new_dynbss + 2; + j < dso->ehdr.e_shnum + && (dso->shdr[j].sh_flags + & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)); + ++j) + if (dso->shdr[j].sh_addr >= dso->phdr[i].p_vaddr + + dso->phdr[i].p_memsz) + adj = (adj + dso->shdr[j].sh_addralign - 1) + & ~(dso->shdr[j].sh_addralign - 1); + + for (j = i + 1; j < dso->ehdr.e_phnum; ++j) + if (dso->phdr[j].p_type == PT_LOAD + && dso->phdr[j].p_vaddr >= dso->shdr[new_dynbss].sh_addr) + { + dso->phdr[j].p_vaddr += adj; + dso->phdr[j].p_paddr += adj; + dso->phdr[j].p_offset += adj; + } + + last_offset = dso->shdr[new_dynbss + 1].sh_offset; + for (j = new_dynbss + 2; j < dso->ehdr.e_shnum; ++j) + if (dso->shdr[j].sh_type != SHT_NOBITS + || dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr + || dso->shdr[j].sh_addr + dso->shdr[j].sh_size + > dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz) + break; + else + { + last_offset += dso->shdr[j].sh_addralign - 1; + last_offset &= ~(dso->shdr[j].sh_addralign - 1); + if (last_offset > dso->phdr[i].p_offset + + dso->phdr[i].p_filesz) + last_offset = dso->phdr[i].p_offset + + dso->phdr[i].p_filesz; + dso->shdr[j].sh_offset = last_offset; + } + + while (j < dso->ehdr.e_shnum + && (dso->shdr[j].sh_flags + & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR))) + { + dso->shdr[j].sh_offset += adj; + dso->shdr[j++].sh_addr += adj; + } + + if (adjust_dso_nonalloc (dso, new_dynbss + 2, + dso->shdr[new_dynbss].sh_offset, + adj)) + goto error_out; + } + } + else + { + if (dso->shdr[new_dynbss].sh_type != SHT_PROGBITS + || dso->shdr[new_dynbss].sh_addr > info->dynbss_base + || dso->shdr[new_dynbss].sh_addr + + dso->shdr[new_dynbss].sh_size + < info->dynbss_base + info->dynbss_size) + { + error (0, 0, "%s: Copy relocs don't point into .dynbss section", + dso->filename); + goto error_out; + } + } + data = elf_getdata (dso->scn[new_dynbss], NULL); + free (data->d_buf); + data->d_buf = info->dynbss; + info->dynbss = NULL; + data->d_off = info->dynbss_base - dso->shdr[new_dynbss].sh_addr; + data->d_size = info->dynbss_size; + data->d_type = ELF_T_BYTE; + if (old_dynbss == -1) + { + data = elf_getdata (dso->scn[new_dynbss + 1], NULL); + if (dso->shdr[new_dynbss + 1].sh_type == SHT_NOBITS + && data->d_buf != NULL) + { +#ifndef NDEBUG + char *buf_start = data->d_buf; + char *buf_end = buf_start + data->d_size; + + while (buf_start < buf_end) + if (*buf_start++) + break; + assert (buf_start == buf_end); +#endif + free (data->d_buf); + data->d_buf = NULL; + } + if (data->d_size != dso->shdr[new_dynbss + 1].sh_size) + { + assert (data->d_size == dso->shdr[new_dynbss].sh_size + + dso->shdr[new_dynbss + 1].sh_size); + data->d_size -= dso->shdr[new_dynbss].sh_size; + } + } + } + + /* Create the liblist. */ + i = new[new_liblist]; + dso->shdr[i].sh_flags = shdr[i].sh_flags; + dso->shdr[i].sh_addralign = shdr[i].sh_addralign; + dso->shdr[i].sh_entsize = shdr[i].sh_entsize; + dso->shdr[i].sh_name = shstrtabadd (dso, ".gnu.liblist"); + if (dso->shdr[i].sh_name == 0) + goto error_out; + else + { + Elf_Data *data; + + dso->shdr[i].sh_link + = new_dynstr != -1 ? new[new_dynstr] : move->old_to_new[dynstrndx]; + data = elf_getdata (dso->scn[i], NULL); + data->d_type = ELF_T_WORD; + data->d_size = (ndeps - 1) * sizeof (Elf32_Lib); + free (data->d_buf); + data->d_buf = liblist; + liblist = NULL; + data->d_off = 0; + data->d_align = sizeof (GElf_Word); + data->d_version = EV_CURRENT; + if (set_dynamic (dso, DT_GNU_LIBLIST, dso->shdr[i].sh_addr, 1)) + goto error_out; + if (set_dynamic (dso, DT_GNU_LIBLISTSZ, dso->shdr[i].sh_size, 1)) + goto error_out; + } + + /* Create the conflict list if necessary. */ + if (new_conflict != -1) + { + Elf_Data *data; + + i = new[new_conflict]; + data = elf_getdata (dso->scn[i], NULL); + data->d_type = ELF_T_RELA; + data->d_size = info->conflict_rela_size + * gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + data->d_off = 0; + data->d_align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + data->d_version = EV_CURRENT; + if (data->d_size) + { + data->d_buf = realloc (data->d_buf, data->d_size); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not build .gnu.conflict section", + dso->filename); + goto error_out; + } + } + else + { + free (data->d_buf); + data->d_buf = NULL; + } + for (j = 0; j < info->conflict_rela_size; ++j) + gelfx_update_rela (dso->elf, data, j, info->conflict_rela + j); + free (info->conflict_rela); + info->conflict_rela = NULL; + + dso->shdr[i].sh_flags = shdr[i].sh_flags; + dso->shdr[i].sh_addralign = shdr[i].sh_addralign; + dso->shdr[i].sh_entsize = shdr[i].sh_entsize; + for (j = 1; j < dso->ehdr.e_shnum; ++j) + if (dso->shdr[j].sh_type == SHT_DYNSYM) + break; + assert (j < dso->ehdr.e_shnum); + dso->shdr[i].sh_link = j; + dso->shdr[i].sh_name = shstrtabadd (dso, ".gnu.conflict"); + if (dso->shdr[i].sh_name == 0) + goto error_out; + if (set_dynamic (dso, DT_GNU_CONFLICT, dso->shdr[i].sh_addr, 1)) + goto error_out; + if (set_dynamic (dso, DT_GNU_CONFLICTSZ, dso->shdr[i].sh_size, 1)) + goto error_out; + } + + if (undo != -1) + { + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr newoffset; + + dso->shdr[undo].sh_name = shstrtabadd (dso, ".gnu.prelink_undo"); + if (dso->shdr[undo].sh_name == 0) + return 1; + dso->shdr[undo].sh_offset = dso->shdr[undo - 1].sh_offset; + if (dso->shdr[undo - 1].sh_type != SHT_NOBITS) + dso->shdr[undo].sh_offset += dso->shdr[undo - 1].sh_size; + dso->shdr[undo].sh_entsize = 1; + dso->shdr[undo].sh_size = dso->undo.d_size; + newoffset = dso->shdr[undo].sh_offset + dso->undo.d_align - 1; + newoffset &= ~(dso->shdr[undo].sh_addralign - 1); + if (adjust_dso_nonalloc (dso, undo + 1, dso->shdr[undo].sh_offset, + dso->undo.d_size + newoffset + - dso->shdr[undo].sh_offset)) + return 1; + dso->shdr[undo].sh_offset = newoffset; + scn = dso->scn[undo]; + data = elf_getdata (scn, NULL); + assert (data != NULL && elf_getdata (scn, data) == NULL); + free (data->d_buf); + *data = dso->undo; + dso->undo.d_buf = NULL; + } + + recompute_nonalloc_offsets (dso); + + if (update_dynamic_tags (dso, dso->shdr, old_shdr, move)) + goto error_out; + + if (update_dynamic_rel (dso, &rinfo)) + goto error_out; + + free (move); + return 0; +} diff --git a/trunk/src/execle_open.c b/trunk/src/execle_open.c new file mode 100644 index 0000000..52872aa --- /dev/null +++ b/trunk/src/execle_open.c @@ -0,0 +1,80 @@ +/* Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <errno.h> +#include <error.h> +#include <stdio.h> +#include <sys/wait.h> +#include <unistd.h> + +static pid_t pid; + +int +execve_close (FILE *f) +{ + pid_t p; + int status; + + if (f != NULL) + fclose (f); + while ((p = waitpid (pid, &status, 0)) == -1 && errno == EINTR); + if (p == -1 || ! WIFEXITED (status)) + return -1; + return WEXITSTATUS (status); +} + +FILE * +execve_open (const char *path, char *const argv[], char *const envp[]) +{ + int p[2]; + FILE *f; + + if (pipe (p) < 0) + { + error (0, errno, "Could not run %s", path); + return NULL; + } + + switch (vfork ()) + { + case -1: + error (0, errno, "Could not run %s", path); + return NULL; + case 0: + close (p[0]); + if (p[1] != 1) + { + dup2 (p[1], 1); + close (p[1]); + } + dup2 (1, 2); + execve (path, argv, envp); + _exit (127); + } + + close (p[1]); + + f = fdopen (p[0], "r"); + if (f == NULL) + { + close (p[0]); + execve_close (NULL); + } + + return f; +} diff --git a/trunk/src/execstack.c b/trunk/src/execstack.c new file mode 100644 index 0000000..f38fead --- /dev/null +++ b/trunk/src/execstack.c @@ -0,0 +1,459 @@ +/* Copyright (C) 2003, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2003. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/wait.h> + +#include "prelink.h" + +int set; +int execflag; + +const char *argp_program_version = "execstack 1.0 (20061201) Wind River"; + +const char *argp_program_bug_address = "<support@windriver.com>"; + +static char argp_doc[] = "execstack -- program to query or set executable stack flag"; + +static struct argp_option options[] = { + {"set-execstack", 's', 0, 0, "Set executable stack flag bit" }, + {"execstack", 's', 0, OPTION_HIDDEN, "" }, + {"clear-execstack", 'c', 0, 0, "Clear executable stack flag bit" }, + {"noexecstack", 'c', 0, OPTION_HIDDEN, "" }, + {"query", 'q', 0, 0, "Query executable stack flag bit" }, + { 0 } +}; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case 's': + set = 1; + execflag = 1; + break; + case 'c': + set = 1; + execflag = 0; + break; + case 'q': + set = 0; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +static struct argp argp = { options, parse_opt, 0, argp_doc }; + +static int execstack_set (DSO *dso, int flag); + +static void +execstack_fill_phdr (DSO *dso, int i, int flag) +{ + memset (&dso->phdr[i], 0, sizeof (dso->phdr[i])); + dso->phdr[i].p_type = PT_GNU_STACK; + dso->phdr[i].p_flags = PF_W | PF_R | (flag ? PF_X : 0); + dso->phdr[i].p_align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); +} + +static int +execstack_make_rdwr (DSO *dso, int flag) +{ + int i, fd = -1, status; + pid_t pid; + DSO *ndso = NULL; + char *p = NULL; + char filename[strlen (dso->filename) + sizeof ".#execstack#.XXXXXX"]; + + for (i = 0; i < dso->ehdr.e_shnum; ++i) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name); + if (strcmp (name, ".gnu.prelink_undo") == 0) + break; + } + + if (i == dso->ehdr.e_shnum) + return reopen_dso (dso, NULL, NULL) ? 1 : -1; + + /* We need to unprelink the file first, so that prelink --undo + or reprelinking it doesn't destroy the PT_GNU_STACK segment + header we've created. */ + sprintf (filename, "%s.#execstack#.XXXXXX", dso->filename); + + fd = wrap_mkstemp (filename); + if (fd == -1) + { + error (0, 0, "%s: Cannot create temporary file", + dso->filename); + goto error_out; + } + + p = strdup (dso->filename); + if (p == NULL) + { + error (0, ENOMEM, "%s: Cannot create temporary file", + dso->filename); + goto error_out; + } + + pid = vfork (); + if (pid == 0) + { + close (fd); + execlp ("prelink", "prelink", "-u", "-o", filename, + dso->filename, NULL); + execl (SBINDIR "/prelink", "prelink", "-u", "-o", filename, + dso->filename, NULL); + _exit (-1); + } + + if (pid < 0) + { + error (0, errno, "%s: Cannot run prelink --undo", + dso->filename); + goto error_out; + } + + if (waitpid (pid, &status, 0) < 0 + || !WIFEXITED (status) + || WEXITSTATUS (status)) + { + error (0, 0, "%s: prelink --undo failed", dso->filename); + goto error_out; + } + + ndso = open_dso (filename); + if (ndso == NULL) + { + error (0, 0, "%s: Couldn't open prelink --undo output", + dso->filename); + goto error_out; + } + + for (i = 0; i < ndso->ehdr.e_shnum; ++i) + { + const char *name = strptr (ndso, ndso->ehdr.e_shstrndx, + ndso->shdr[i].sh_name); + if (strcmp (name, ".gnu.prelink_undo") == 0) + break; + } + + if (i != ndso->ehdr.e_shnum) + { + error (0, 0, "%s: prelink --undo output contains .gnu.prelink_undo section", + dso->filename); + goto error_out; + } + + if (ndso->ehdr.e_type != dso->ehdr.e_type) + { + error (0, 0, "%s: Object type changed during prelink --undo operation", + dso->filename); + } + + if (ndso->filename != ndso->soname) + free ((char *) ndso->filename); + ndso->filename = p; + p = NULL; + + wrap_unlink (filename); + close (fd); + fd = -1; + close_dso (dso); + return execstack_set (ndso, flag); + +error_out: + free (p); + if (ndso != NULL) + close_dso (ndso); + if (fd != -1) + { + wrap_unlink (filename); + close (fd); + } + close_dso (dso); + return 1; +} + +static int +execstack_set (DSO *dso, int flag) +{ + int i, null = -1, last, ret; + GElf_Addr lowoff = ~(GElf_Addr) 0, start = 0, align = 0; + GElf_Addr adjust; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_GNU_STACK) + { + /* Found PT_GNU_STACK. Check if we need any change or not. */ + if (flag ^ ((dso->phdr[i].p_flags & PF_X) != 0)) + { + ret = execstack_make_rdwr (dso, flag); + if (ret != -1) + return ret; + dso->phdr[i].p_flags ^= PF_X; + goto out_write; + } + else + goto out_close; + } + else if (dso->phdr[i].p_type == PT_NULL) + null = i; + + if (null != -1) + { + /* Overwrite PT_NULL segment with PT_GNU_STACK. */ + ret = execstack_make_rdwr (dso, flag); + if (ret != -1) + return ret; + execstack_fill_phdr (dso, i, flag); + goto out_write; + } + + if (dso->ehdr.e_shnum == 0) + { + error (0, 0, "%s: Section header table missing", dso->filename); + goto error_out; + } + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + if (lowoff > dso->shdr[i].sh_offset) + { + if (dso->shdr[i].sh_flags & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + { + lowoff = dso->shdr[i].sh_offset; + start = dso->shdr[i].sh_addr; + } + else + { + error (0, 0, "%s: Non-alloced sections before alloced ones", + dso->filename); + goto error_out; + } + } + + if (dso->shdr[i].sh_addralign > align) + align = dso->shdr[i].sh_addralign; + } + + if (dso->ehdr.e_phoff >= lowoff) + { + error (0, 0, "%s: Program header table not before all sections", + dso->filename); + goto error_out; + } + + if (dso->ehdr.e_shoff <= lowoff) + { + error (0, 0, "%s: Section header table before first section", + dso->filename); + goto error_out; + } + + if (dso->ehdr.e_phoff + (dso->ehdr.e_phnum + 1) * dso->ehdr.e_phentsize + <= lowoff) + { + /* There is enough space for the headers even without reshuffling + anything. */ + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_PHDR) + { + if (dso->phdr[i].p_filesz + == dso->ehdr.e_phnum * dso->ehdr.e_phentsize) + dso->phdr[i].p_filesz += dso->ehdr.e_phentsize; + if (dso->phdr[i].p_memsz + == dso->ehdr.e_phnum * dso->ehdr.e_phentsize) + dso->phdr[i].p_memsz += dso->ehdr.e_phentsize; + } + i = dso->ehdr.e_phnum++; + ret = execstack_make_rdwr (dso, flag); + if (ret != -1) + return ret; + execstack_fill_phdr (dso, i, flag); + goto out_write; + } + + if (dso->ehdr.e_type != ET_DYN) + { + error (0, 0, "%s: Reshuffling of objects to make room for\n" + "program header entry only supported for shared libraries", + dso->filename); + goto error_out; + } + + adjust = dso->ehdr.e_phoff + (dso->ehdr.e_phnum + 1) * dso->ehdr.e_phentsize + - lowoff; + if (align) + adjust = (adjust + align - 1) & ~(align - 1); + + /* Need to make sure adjust doesn't cause different Phdr segments + to overlap on the same page. */ + last = -1; + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz >= start) + { + if (last != -1 + && (((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz - 1) + ^ dso->phdr[i].p_vaddr) + & ~(dso->arch->max_page_size - 1)) + && !(((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz + + adjust - 1) + ^ (dso->phdr[i].p_vaddr + adjust)) + & ~(dso->arch->max_page_size - 1))) + { + if (align >= dso->arch->max_page_size) + { + error (0, 0, "%s: Cannot grow reloc sections", dso->filename); + goto error_out; + } + adjust = (adjust + dso->arch->max_page_size - 1) + & ~(dso->arch->max_page_size - 1); + } + last = i; + } + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_PHDR) + { + if (dso->phdr[i].p_filesz == dso->ehdr.e_phnum * dso->ehdr.e_phentsize) + dso->phdr[i].p_filesz += dso->ehdr.e_phentsize; + if (dso->phdr[i].p_memsz == dso->ehdr.e_phnum * dso->ehdr.e_phentsize) + dso->phdr[i].p_memsz += dso->ehdr.e_phentsize; + } + + i = dso->ehdr.e_phnum++; + ret = execstack_make_rdwr (dso, flag); + if (ret != -1) + return ret; + + if (adjust_dso (dso, start, adjust)) + goto error_out; + + execstack_fill_phdr (dso, i, flag); + +out_write: + if (dynamic_info_is_set (dso, DT_CHECKSUM_BIT) + && dso_is_rdwr (dso) + && prelink_set_checksum (dso)) + goto error_out; + + dso->permissive = 1; + + return update_dso (dso, NULL); + +out_close: + close_dso (dso); + return 0; + +error_out: + close_dso (dso); + return 1; +} + +static int +execstack_query (DSO *dso) +{ + int stack = '?', i; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_GNU_STACK) + { + stack = (dso->phdr[i].p_flags & PF_X) ? 'X' : '-'; + break; + } + printf ("%c %s\n", stack, dso->filename); + close_dso (dso); + return 0; +} + +int +main (int argc, char *argv[]) +{ + int remaining, failures = 0; + + setlocale (LC_ALL, ""); + + argp_parse (&argp, argc, argv, 0, &remaining, 0); + + elf_version (EV_CURRENT); + + if (remaining == argc) + error (EXIT_FAILURE, 0, "no files given"); + + while (remaining < argc) + { + DSO *dso = open_dso (argv[remaining++]); + int ret; + + if (dso == NULL) + { + ++failures; + continue; + } + + if (dso->ehdr.e_type != ET_DYN + && dso->ehdr.e_type != ET_EXEC) + { + ++failures; + error (0, 0, "%s is not a shared library nor executable", dso->filename); + continue; + } + + if (set) + ret = execstack_set (dso, execflag); + else + ret = execstack_query (dso); + + if (ret) + ++failures; + } + + return failures; +} + +/* FIXME: Dummy. When arch dependent files are split into adjust and prelink + parts, this can go away. */ +struct prelink_conflict * +prelink_conflict (struct prelink_info *info, GElf_Word r_sym, int reloc_type) +{ + abort (); +} + +GElf_Rela * +prelink_conflict_add_rela (struct prelink_info *info) +{ + abort (); +} + +GElf_Addr mmap_reg_start; +GElf_Addr mmap_reg_end; +int exec_shield; diff --git a/trunk/src/fptr.c b/trunk/src/fptr.c new file mode 100644 index 0000000..7602d5e --- /dev/null +++ b/trunk/src/fptr.c @@ -0,0 +1,458 @@ +/* Copyright (C) 2001, 2002, 2003 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include "fptr.h" + +struct opd_refent; + +struct opd_tabent +{ + struct opd_ent *ent; + struct opd_refent *ref; +}; + +struct opd_refent +{ + GElf_Addr val; + GElf_Addr gp; + struct opd_refent *first; + struct opd_tabent *tabent; + struct opd_refent *next, *nextref; + GElf_Word refcnt; +}; + +struct opd_fptr +{ + /* The first 2 fields have to match opd_refent. */ + GElf_Addr val; + GElf_Addr gp; + struct opd_ent *ent; +}; + +static void +opd_del (void *p) +{ + free (p); +} + +static hashval_t +opd_tabent_hash (const void *p) +{ + struct opd_tabent *e = (struct opd_tabent *)p; + + return e->ent->opd; +} + +static int +opd_tabent_eq (const void *p, const void *q) +{ + struct opd_tabent *e = (struct opd_tabent *)p; + struct opd_tabent *f = (struct opd_tabent *)q; + + return e->ent == f->ent; +} + +static hashval_t +opd_refent_hash (const void *p) +{ + struct opd_refent *e = (struct opd_refent *)p; + + return e->val ^ (e->val >> 31); +} + +static int +opd_refent_eq (const void *p, const void *q) +{ + struct opd_refent *e = (struct opd_refent *)p; + struct opd_refent *f = (struct opd_refent *)q; + + return e->val == f->val && e->gp == f->gp; +} + +static int +opd_gather_refent (void **p, void *info) +{ + struct opd_refent ***ptr = (struct opd_refent ***) info; + struct opd_refent *r = *(struct opd_refent **) p, *t; + + for (t = r; t; t = t->next) + { + *(*ptr)++ = t; + t->first = r; + } + return 1; +} + +static int +opd_refent_cmp (const void *A, const void *B) +{ + struct opd_refent *a = * (struct opd_refent **) A; + struct opd_refent *b = * (struct opd_refent **) B; + + if (a->refcnt > b->refcnt) + return -1; + if (a->refcnt < b->refcnt) + return 1; + return 0; +} + +int +opd_init (struct prelink_info *info) +{ + int i, j, nrefent = 0; + struct opd_lib *l; + struct opd_refent refent, *r, **refarr, **a; + struct opd_tabent tabent, *t; + void **tabslot; + htab_t tabent_htab = NULL, refent_htab = NULL; + + l = calloc (sizeof (struct opd_lib), 1); + if (l == NULL) + goto error_mem; + l->nrefs = (info->symtab_end - info->symtab_start) / info->symtab_entsize; + if (l->nrefs) + { + l->u.refp = calloc (l->nrefs, sizeof (struct opd_ref *)); + if (l->u.refp == NULL) + goto error_mem; + } + else + l->u.refp = NULL; + tabent_htab = htab_try_create (100, opd_tabent_hash, opd_tabent_eq, opd_del); + refent_htab = htab_try_create (100, opd_refent_hash, opd_refent_eq, opd_del); + l->htab = htab_try_create (100, opd_refent_hash, opd_refent_eq, opd_del); + if (tabent_htab == NULL || refent_htab == NULL || l->htab == NULL) + goto error_mem; + + for (i = 0; i < info->ent->ndepends; ++i) + { + struct prelink_entry *ent; + struct prelink_conflict *conflict; + struct opd_lib *ol; + + ent = info->ent->depends[i]; + ol = ent->opd; + for (j = 0; j < ol->nrefs; ++j) + { + refent.val = ol->u.refs[j].ent->val; + refent.gp = ol->u.refs[j].ent->gp; + for (conflict = info->conflicts[i + 1]; conflict; + conflict = conflict->next) + { + if (conflict->symoff == ol->u.refs[j].symoff + && conflict->reloc_class != RTYPE_CLASS_COPY + && conflict->reloc_class != RTYPE_CLASS_TLS) + break; + } + + if (conflict) + { + if (refent.val + != conflict->conflict.ent->base + conflict->conflictval + || refent.gp != conflict->conflict.ent->pltgot) + { + error (0, 0, "%s: OPD value changed during prelinking", + info->ent->filename); + goto error_out; + } + + refent.val = conflict->lookup.ent->base + conflict->lookupval; + refent.gp = conflict->lookup.ent->pltgot; + } + + if (ol->u.refs[j].ent->opd & OPD_ENT_PLT) + { + struct opd_ent_plt *entp + = (struct opd_ent_plt *) ol->u.refs[j].ent; + int k; + + for (k = 0; k < info->ent->ndepends; ++k) + if (info->ent->depends[k] == entp->lib) + break; + + assert (k < info->ent->ndepends); + + for (conflict = info->conflicts[k + 1]; conflict; + conflict = conflict->next) + { + if (conflict->symoff == entp->symoff + && conflict->reloc_class == RTYPE_CLASS_PLT) + break; + } + + if (conflict) + { + if (ol->u.refs[j].ent->val + != conflict->conflict.ent->base + conflict->conflictval + || ol->u.refs[j].ent->gp + != conflict->conflict.ent->pltgot) + { + error (0, 0, "%s: OPD value changed during prelinking", + info->ent->filename); + goto error_out; + } + + /* FPTR originally pointed into .plt, but since they + now resolve to different values, this cannot be used. */ + if (refent.val + != conflict->lookup.ent->base + conflict->lookupval + || refent.gp != conflict->lookup.ent->pltgot) + continue; + } + else if (refent.val != ol->u.refs[j].ent->val + || refent.gp != ol->u.refs[j].ent->gp) + continue; + } + + tabslot = htab_find_slot (refent_htab, &refent, INSERT); + if (tabslot == NULL) + goto error_mem; + + if (*tabslot != NULL) + { + for (r = (struct opd_refent *) *tabslot; r; r = r->next) + if (r->tabent->ent == ol->u.refs[j].ent) + { + r->refcnt += ol->u.refs[j].refcnt; + break; + } + + if (r) + continue; + } + + r = (struct opd_refent *) calloc (sizeof (struct opd_refent), 1); + if (r == NULL) + goto error_mem; + + ++nrefent; + r->next = (struct opd_refent *) *tabslot; + *tabslot = r; + r->val = refent.val; + r->gp = refent.gp; + r->refcnt = ol->u.refs[j].refcnt; + + tabent.ent = ol->u.refs[j].ent; + + tabslot = htab_find_slot (tabent_htab, &tabent, INSERT); + if (tabslot == NULL) + goto error_mem; + + if (*tabslot != NULL) + { + t = (struct opd_tabent *) *tabslot; + t->ref->nextref = r; + r->nextref = t->ref; + } + else + { + t = (struct opd_tabent *) calloc (sizeof (struct opd_tabent), 1); + if (t == NULL) + goto error_mem; + t->ent = ol->u.refs[j].ent; + *tabslot = t; + r->nextref = r; + t->ref = r; + } + + r->tabent = t; + } + } + + refarr = alloca (nrefent * sizeof (struct opd_refent *)); + a = refarr; + htab_traverse (refent_htab, opd_gather_refent, &a); + assert (a == refarr + nrefent); + qsort (refarr, nrefent, sizeof (struct opd_refent *), opd_refent_cmp); + for (i = 0; i < nrefent; ++i) + { + struct opd_fptr *f; + + if (refarr[i]->tabent == NULL) + continue; + + f = (struct opd_fptr *) calloc (sizeof (struct opd_fptr), 1); + if (f == NULL) + goto error_mem; + + f->val = refarr[i]->val; + f->gp = refarr[i]->gp; + f->ent = refarr[i]->tabent->ent; + tabslot = htab_find_slot (l->htab, f, INSERT); + if (tabslot == NULL) + goto error_mem; + + *tabslot = f; + r = refarr[i]->tabent->ref; + do + { + if (r != refarr[i]) + r->tabent = NULL; + r = r->nextref; + } + while (r != refarr[i]->tabent->ref); + + for (r = refarr[i]->first; r; r = r->next) + r->tabent = NULL; + } + + htab_delete (tabent_htab); + htab_delete (refent_htab); + info->ent->opd = l; + return 0; + +error_mem: + error (0, ENOMEM, "%s: Could not create OPD table", + info->ent->filename); +error_out: + if (tabent_htab) + htab_delete (tabent_htab); + if (refent_htab) + htab_delete (refent_htab); + if (l && l->htab) + htab_delete (l->htab); + free (l); + return 1; +} + +int +opd_add (struct prelink_info *info, GElf_Word r_sym, int reloc_type) +{ + struct opd_fptr *f, fp; + void **tabslot; + struct opd_lib *l = info->ent->opd; + + if (l->u.refp[r_sym] != NULL) + { + ++l->u.refp[r_sym]->refcnt; + return 0; + } + + if (ELF64_ST_BIND (info->symtab [r_sym].st_info) + == STB_LOCAL) + { + fp.val = info->symtab [r_sym].st_value; + fp.gp = info->ent->pltgot; + } + else + { + fp.val = info->resolve (info, r_sym, reloc_type); + if (info->resolveent == NULL) + return 0; + fp.gp = info->resolveent->pltgot; + } + + l->u.refp[r_sym] = malloc (sizeof (struct opd_ref)); + if (l->u.refp[r_sym] == NULL) + goto error_mem; + l->u.refp[r_sym]->symoff = r_sym; + l->u.refp[r_sym]->refcnt = 1; + l->u.refp[r_sym]->ent = NULL; + + tabslot = htab_find_slot (l->htab, &fp, INSERT); + if (tabslot == NULL) + goto error_mem; + + if (*tabslot == NULL) + { + f = calloc (sizeof (struct opd_fptr), 1); + if (f == NULL) + goto error_mem; + f->val = fp.val; + f->gp = fp.gp; + *tabslot = f; + } + + l->u.refp[r_sym]->ent = *tabslot; + return 0; + +error_mem: + error (0, ENOMEM, "%s: Could not create OPD table", + info->ent->filename); + return 1; +} + +void +opd_note_plt (struct prelink_info *info, GElf_Word r_sym, int reloc_type, + GElf_Addr r_offset) +{ + struct opd_fptr *f, fp; + struct opd_lib *l = info->ent->opd; + struct opd_ent_plt *entp; + + if (ELF64_ST_BIND (info->symtab [r_sym].st_info) + == STB_LOCAL) + { + fp.val = info->symtab [r_sym].st_value; + fp.gp = info->ent->pltgot; + } + else + { + fp.val = info->resolve (info, r_sym, reloc_type); + if (info->resolveent == NULL) + return; + fp.gp = info->resolveent->pltgot; + } + + f = (struct opd_fptr *) htab_find (l->htab, &fp); + if (f == NULL || f->ent != NULL) + return; + + entp = calloc (sizeof (struct opd_ent_plt), 1); + if (entp == NULL) + return; + + entp->v.val = fp.val; + entp->v.gp = fp.gp; + entp->v.opd = (r_offset - l->plt_start) | (OPD_ENT_PLT | OPD_ENT_NEW); + entp->lib = info->ent; + entp->symoff = r_sym; + f->ent = &entp->v; +} + +GElf_Addr +opd_size (struct prelink_info *info, GElf_Word entsize) +{ + struct opd_lib *l = info->ent->opd; + int i; + GElf_Addr ret = 0; + struct opd_ent *e; + struct opd_fptr *f; + + for (i = 0; i < l->nrefs; ++i) + if ((f = (struct opd_fptr *) l->u.refp[i]->ent)->ent == NULL) + { + e = calloc (sizeof (struct opd_ent), 1); + if (e == NULL) + { + error (0, ENOMEM, "%s: Could not create OPD table", + info->ent->filename); + return -1; + } + + e->val = f->val; + e->gp = f->gp; + e->opd = ret | OPD_ENT_NEW; + ret += entsize; + } + + return ret; +} diff --git a/trunk/src/fptr.h b/trunk/src/fptr.h new file mode 100644 index 0000000..36ef7c6 --- /dev/null +++ b/trunk/src/fptr.h @@ -0,0 +1,67 @@ +/* Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef FPTR_H +#define FPTR_H + +#include "prelink.h" +#include "hashtab.h" + +struct opd_ent +{ + GElf_Addr val; + GElf_Addr gp; + GElf_Addr opd; +#define OPD_ENT_PLT 1 +#define OPD_ENT_NEW 2 +}; + +struct opd_ent_plt +{ + struct opd_ent v; + struct prelink_entry *lib; + GElf_Word symoff; +}; + +struct opd_ref +{ + GElf_Word symoff; + GElf_Word refcnt; + struct opd_ent *ent; +}; + +struct opd_lib +{ + GElf_Addr symtab_start; + GElf_Addr opd_start; + GElf_Addr plt_start; + union + { + struct opd_ref *refs; + struct opd_ref **refp; + } u; + htab_t htab; + int nrefs; +}; + +int opd_init (struct prelink_info *info); +int opd_add (struct prelink_info *info, GElf_Word r_sym, int reloc_type); +void opd_note_plt (struct prelink_info *info, GElf_Word r_sym, int reloc_type, + GElf_Addr r_offset); +GElf_Addr opd_size (struct prelink_info *info, GElf_Word entsize); + +#endif /* FPTR_H */ diff --git a/trunk/src/gather.c b/trunk/src/gather.c new file mode 100644 index 0000000..9219fdf --- /dev/null +++ b/trunk/src/gather.c @@ -0,0 +1,1412 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <fnmatch.h> +#include <ftw.h> +#include <glob.h> +#include <stddef.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "prelinktab.h" +#include "reloc.h" + +#ifndef HAVE_FTW_ACTIONRETVAL +# define FTW_ACTIONRETVAL 0 +# define FTW_CONTINUE 0 +# define FTW_STOP 1 +#endif + +static int gather_lib (struct prelink_entry *ent); +static int implicit; + +static struct prelink_dir *dirs; +static struct prelink_dir *blacklist; +#ifndef HAVE_FTW_ACTIONRETVAL +static char *blacklist_dir; +static size_t blacklist_dir_len; +#endif +static struct extension +{ + const char *ext; + size_t len; + int is_glob; +} *blacklist_ext; +static int blacklist_next; + +static int +gather_deps (DSO *dso, struct prelink_entry *ent) +{ + int i, j, seen = 0; + FILE *f = NULL; + const char *argv[6]; + const char *envp[5]; + char *line = NULL, *p, *q = NULL; + const char **depends = NULL; + size_t ndepends = 0, ndepends_alloced = 0; + size_t len = 0; + ssize_t n; + Elf_Scn *scn; + Elf_Data *data; + Elf32_Lib *liblist = NULL; + int nliblist = 0; + const char *dl; + const char *ent_filename; + + if (check_dso (dso)) + { + if (! undo) + ent->type = ET_UNPRELINKABLE; + goto error_out; + } + + ent->pltgot = dso->info[DT_PLTGOT]; + ent->soname = strdup (dso->soname); + ent->flags = (dso->arch->class == ELFCLASS64 ? PCF_ELF64 : 0) + | (dso->arch->machine & PCF_MACHINE); + if (ent->soname == NULL) + { + error (0, ENOMEM, "%s: Could not record SONAME", ent->filename); + goto error_out; + } + + dl = dynamic_linker ?: dso->arch->dynamic_linker; + if (strcmp (dso->filename, dl) == 0 + || is_ldso_soname (dso->soname)) + { + if (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT) + && dynamic_info_is_set (dso, DT_CHECKSUM_BIT)) + { + if (! undo && dso->arch->read_opd) + dso->arch->read_opd (dso, ent); + ent->done = 2; + } + close_dso (dso); + return 0; + } + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + const char *name; + if (dso->shdr[i].sh_type == SHT_GNU_LIBLIST + && (name = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name)) + && ! strcmp (name, ".gnu.liblist") + && (dso->shdr[i].sh_size % sizeof (Elf32_Lib)) == 0) + { + nliblist = dso->shdr[i].sh_size / sizeof (Elf32_Lib); + liblist = (Elf32_Lib *) alloca (dso->shdr[i].sh_size); + scn = dso->scn[i]; + data = elf_getdata (scn, NULL); + if (data == NULL || elf_getdata (scn, data) + || data->d_buf == NULL || data->d_off + || data->d_size != dso->shdr[i].sh_size) + liblist = NULL; + else + memcpy (liblist, data->d_buf, dso->shdr[i].sh_size); + if (! undo) + break; + } + else if (undo + && dso->shdr[i].sh_type == SHT_PROGBITS + && (name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name)) + && ! strcmp (name, ".gnu.prelink_undo")) + ent->done = 2; + } + + if (! undo && dso->arch->read_opd) + dso->arch->read_opd (dso, ent); + close_dso (dso); + dso = NULL; + + i = 0; + argv[i++] = dl; + if (strchr (ent->filename, '/') != NULL) + ent_filename = ent->filename; + else + { + size_t flen = strlen (ent->filename); + char *tp = alloca (2 + flen + 1); + memcpy (tp, "./", 2); + memcpy (tp + 2, ent->filename, flen + 1); + ent_filename = tp; + } + + if (prelink_rtld == NULL) + { + i = 0; + argv[i++] = dl; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; + envp[1] = "LD_TRACE_PRELINKING=1"; + envp[2] = "LD_WARN="; + envp[3] = NULL; + f = execve_open (dl, (char * const *)argv, (char * const *)envp); + } + else + { + char *path; + i = 0; + argv[i++] = prelink_rtld; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = "--target-paths"; + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "RTLD_TRACE_PRELINKING=1"; + envp[1] = "LD_WARN="; + path = alloca (sizeof "PATH=" + strlen (getenv ("PATH"))); + sprintf (path, "PATH=%s", getenv ("PATH")); + envp[2] = path; + + if (sysroot) + { + envp[3] = alloca (sizeof "PRELINK_SYSROOT=" + strlen (sysroot)); + sprintf ((char *) envp[3], "PRELINK_SYSROOT=%s", sysroot); + envp[4] = NULL; + } + else + envp[3] = NULL; + + f = execve_open (prelink_rtld, (char * const *)argv, (char * const *)envp); + } + + if (f == NULL) + goto error_out; + + do + { + n = getline (&line, &len, f); + if (n < 0) + break; + + if (line[n - 1] == '\n') + line[n - 1] = '\0'; + + p = strstr (line, " => "); + if (p) + { + q = strstr (p, " ("); + if (q == NULL && strcmp (p, " => not found") == 0) + { + error (0, 0, "%s: Could not find one of the dependencies: %s", + ent->filename, line); + goto error_out; + } + } + if (p == NULL || q == NULL) + { + if (strstr (line, "statically linked") != NULL) + error (0, 0, "%s: Library without dependencies", ent->filename); + else + { + p = strstr (line, "error while loading shared libraries: "); + if (p != NULL) + { + p += sizeof "error while loading shared libraries: " - 1; + q = strstr (line, "cannot open shared object file: " + "No such file or directory"); + if (q != NULL) + { + error (0, 0, + "%s: Could not find one of the dependencies", + ent->filename); + goto error_out; + } + } + error (0, 0, "%s: Could not parse `%s'", ent->filename, line); + } + goto error_out; + } + + *p = '\0'; + p += sizeof " => " - 1; + *q = '\0'; + if (! strcmp (p, ent_filename)) + { + ++seen; + continue; + } + if (ndepends == ndepends_alloced) + { + ndepends_alloced += 10; + depends = + (const char **) realloc (depends, + ndepends_alloced * sizeof (char *)); + if (depends == NULL) + { + error (0, ENOMEM, "%s: Could not record dependencies", + ent->filename); + goto error_out; + } + } + + depends[ndepends] = strdupa (p); + ++ndepends; + } while (!feof (f)); + + if (execve_close (f)) + { + f = NULL; + error (0, 0, "%s: Dependency tracing failed", ent->filename); + goto error_out; + } + + f = NULL; + if (seen != 1) + { + error (0, 0, "%s seen %d times in LD_TRACE_PRELINKING output, expected once", + ent->filename, seen); + goto error_out; + } + + free (line); + line = NULL; + + if (ndepends == 0) + ent->depends = NULL; + else + { + ent->depends = + (struct prelink_entry **) + malloc (ndepends * sizeof (struct prelink_entry *)); + if (ent->depends == NULL) + { + error (0, ENOMEM, "%s: Could not record dependencies", ent->filename); + goto error_out; + } + } + + ent->ndepends = ndepends; + char *cache_dyn_depends = NULL; + if (ndepends) + { + cache_dyn_depends = alloca (ndepends); + memset (cache_dyn_depends, '\0', ndepends); + } + for (i = 0; i < ndepends; ++i) + { + ent->depends[i] = prelink_find_entry (depends [i], NULL, 1); + if (ent->depends[i] == NULL) + goto error_out_free_depends; + + if (ent->depends[i]->type == ET_CACHE_DYN) + { + ent->depends[i]->type = ET_NONE; + free (ent->depends[i]->depends); + ent->depends[i]->depends = NULL; + ent->depends[i]->ndepends = 0; + cache_dyn_depends[i] = 1; + } + + if (ent->depends[i]->type != ET_NONE + && ent->depends[i]->type != ET_BAD + && ent->depends[i]->type != ET_DYN + && ent->depends[i]->type != ET_UNPRELINKABLE) + { + error (0, 0, "%s is not a shared library", depends [i]); +error_out_regather_libs: + for (i = 0; i < ndepends; ++i) + { + if (cache_dyn_depends[i] && ent->depends[i]->type == ET_NONE) + gather_lib (ent->depends[i]); + } + goto error_out_free_depends; + } + } + + free (depends); + depends = NULL; + + for (i = 0; i < ndepends; ++i) + if (ent->depends[i]->type == ET_NONE + && gather_lib (ent->depends[i])) + { + cache_dyn_depends[i] = 0; + goto error_out_regather_libs; + } + + for (i = 0; i < ndepends; ++i) + for (j = 0; j < ent->depends[i]->ndepends; ++j) + if (ent->depends[i]->depends[j] == ent) + { + error (0, 0, "%s has a dependency cycle", ent->canon_filename); + goto error_out_free_depends; + } + + for (i = 0; i < ndepends; ++i) + if (ent->depends[i]->type == ET_UNPRELINKABLE) + { + error (0, 0, "Could not prelink %s because its dependency %s could not be prelinked", + ent->filename, ent->depends[i]->filename); + ent->type = ET_UNPRELINKABLE; + goto error_out; + } + + if (! undo && (!nliblist || liblist) && nliblist == ndepends) + { + for (i = 0; i < ndepends; ++i) + if (liblist[i].l_time_stamp != ent->depends[i]->timestamp + || liblist[i].l_checksum != ent->depends[i]->checksum + || ! ent->depends[i]->done) + break; + + if (i == ndepends) + ent->done = 2; + } + + return 0; + +error_out_free_depends: + free (ent->depends); + ent->depends = NULL; + ent->ndepends = 0; +error_out: + if (f) + execve_close (f); + free (line); + free (depends); + if (dso) + close_dso (dso); + return 1; +} + +static int +gather_dso (DSO *dso, struct prelink_entry *ent) +{ + int prelinked; + + if (verbose > 5) + printf ("Checking shared library %s\n", ent->canon_filename); + + if (dso->ehdr.e_type != ET_DYN) + { + error (0, 0, "%s is not a shared library", ent->filename); + close_dso (dso); + return 1; + } + + prelinked = (dynamic_info_is_set (dso, DT_GNU_PRELINKED_BIT) + && dynamic_info_is_set (dso, DT_CHECKSUM_BIT)); + ent->timestamp = dso->info_DT_GNU_PRELINKED; + ent->checksum = dso->info_DT_CHECKSUM; + ent->base = dso->base; + ent->end = dso->end; + if (dso->arch->need_rel_to_rela != NULL && ! prelinked) + { + /* If the library has not been prelinked yet and we need + to convert REL to RELA, then make room for it. */ + struct reloc_info rinfo; + GElf_Addr adjust = 0; + int sec = dso->ehdr.e_shnum; + + if (find_reloc_sections (dso, &rinfo)) + { + close_dso (dso); + return 1; + } + + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + if (rinfo.rel_to_rela) + { + sec = rinfo.first; + adjust = (dso->shdr[rinfo.last].sh_addr + + dso->shdr[rinfo.last].sh_size + - dso->shdr[rinfo.first].sh_addr) / 2; + } + if (rinfo.rel_to_rela_plt) + { + if (rinfo.plt < sec) + sec = rinfo.plt; + adjust += dso->shdr[rinfo.plt].sh_size / 2; + } + if (adjust) + { + int align = 0, i, last; + GElf_Addr start; + + for (i = rinfo.plt ? rinfo.plt : rinfo.first; + i < dso->ehdr.e_shnum; i++) + { + if (dso->shdr[i].sh_addralign > align) + align = dso->shdr[i].sh_addralign; + } + + if (rinfo.plt) + start = dso->shdr[rinfo.plt].sh_addr + + dso->shdr[rinfo.plt].sh_size; + else + start = dso->shdr[rinfo.first].sh_addr + + dso->shdr[rinfo.first].sh_size; + + /* Need to make sure that all the remaining sections are properly + aligned. */ + if (align) + adjust = (adjust + align - 1) & ~(align - 1); + + /* Need to make sure adjust doesn't cause different Phdr segments + to overlap on the same page. */ + last = -1; + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz >= start) + { + if (last != -1 + && (((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz + - 1) ^ dso->phdr[i].p_vaddr) + & ~(dso->arch->max_page_size - 1)) + && !(((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz + + adjust - 1) + ^ (dso->phdr[i].p_vaddr + adjust)) + & ~(dso->arch->max_page_size - 1))) + { + if (align >= dso->arch->max_page_size) + { + error (0, 0, "%s: Cannot grow reloc sections", + ent->filename); + close_dso (dso); + return 1; + } + adjust = (adjust + dso->arch->max_page_size - 1) + & ~(dso->arch->max_page_size - 1); + } + last = i; + } + + ent->end += adjust; + } + } + + if (gather_deps (dso, ent)) + return 1; + + if (ent->done && ! prelinked && ! undo) + ent->done = 0; + ent->type = ET_DYN; + return 0; +} + +static int +gather_lib (struct prelink_entry *ent) +{ + DSO *dso; + + ent->type = ET_BAD; + dso = open_dso (ent->filename); + if (dso == NULL) + return 1; + + return gather_dso (dso, ent); +} + +static int +gather_exec (DSO *dso, const struct stat64 *st) +{ + int i, j; + Elf_Data *data; + const char *dl; + struct prelink_entry *ent; + + if (verbose > 5) + printf ("Checking executable %s\n", dso->filename); + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_INTERP) + break; + + /* If there are no PT_INTERP segments, it is statically linked. */ + if (i == dso->ehdr.e_phnum) + { +make_unprelinkable: + if (undo) + goto error_out; + + ent = prelink_find_entry (dso->filename, st, 1); + if (ent == NULL) + goto error_out; + + assert (ent->type == ET_NONE); + ent->type = ET_UNPRELINKABLE; + if (dso) + close_dso (dso); + return 0; + } + + j = addr_to_sec (dso, dso->phdr[i].p_vaddr); + if (j == -1 || dso->shdr[j].sh_addr != dso->phdr[i].p_vaddr + || dso->shdr[j].sh_type != SHT_PROGBITS) + { + error (0, 0, "%s: PT_INTERP segment not corresponding to .interp section", + dso->filename); + goto make_unprelinkable; + } + + data = elf_getdata (dso->scn[j], NULL); + if (data == NULL) + { + error (0, 0, "%s: Could not read .interp section", dso->filename); + goto error_out; + } + + i = strnlen (data->d_buf, data->d_size); + if (i == data->d_size) + { + error (0, 0, "%s: .interp section not zero terminated", dso->filename); + goto error_out; + } + + dl = dynamic_linker ?: dso->arch->dynamic_linker; + if (strcmp (dl, data->d_buf) != 0 + && (dynamic_linker != NULL || dso->arch->dynamic_linker_alt == NULL + || strcmp (dso->arch->dynamic_linker_alt, data->d_buf) != 0)) + { + error (0, 0, "%s: Using %s, not %s as dynamic linker", dso->filename, + (char *) data->d_buf, dl); + goto error_out; + } + + ent = prelink_find_entry (dso->filename, st, 1); + if (ent == NULL) + goto error_out; + + assert (ent->type == ET_NONE); + ent->u.explicit = 1; + + if (gather_deps (dso, ent)) + return 0; + + for (i = 0; i < ent->ndepends; ++i) + ++ent->depends[i]->refs; + + ent->type = ET_EXEC; + return 0; + +error_out: + if (dso) + close_dso (dso); + return 0; +} + +static int +add_dir_to_dirlist (const char *name, dev_t dev, int flags) +{ + const char *canon_name; + struct prelink_dir *dir; + size_t len; + + canon_name = wrap_prelink_canonicalize (name, NULL); + if (canon_name == NULL) + { + if (! all && implicit) + return 0; + error (0, errno, "Could not record directory %s", name); + return 1; + } + + len = strlen (canon_name); + + for (dir = blacklist; dir; dir = dir->next) + if (((dir->flags != FTW_CHDIR && len >= dir->len) + || (dir->flags == FTW_CHDIR && len == dir->len)) + && strncmp (dir->dir, canon_name, dir->len) == 0) + { + if (dir->flags == FTW_CHDIR) + break; + if ((dir->flags & FTW_MOUNT) && dir->dev != dev) + continue; + break; + } + + if (dir != NULL) + { + free ((char *) canon_name); + return 2; + } + + dir = malloc (sizeof (struct prelink_dir) + len + 1); + if (dir == NULL) + { + error (0, ENOMEM, "Could not record directory %s", name); + free ((char *) canon_name); + return 1; + } + + dir->next = dirs; + dir->flags = flags; + dir->dev = dev; + dir->len = len; + strcpy (dir->dir, canon_name); + free ((char *) canon_name); + dirs = dir; + return 0; +} + +static int +gather_func (const char *name, const struct stat64 *st, int type, + struct FTW *ftwp) +{ + unsigned char e_ident [sizeof (Elf64_Ehdr) + sizeof (Elf64_Phdr)]; + +#ifndef HAVE_FTW_ACTIONRETVAL + if (blacklist_dir) + { + if (strncmp (name, blacklist_dir, blacklist_dir_len) == 0) + return FTW_CONTINUE; + free (blacklist_dir); + blacklist_dir = NULL; + } +#endif + if (type == FTW_F && S_ISREG (st->st_mode) && (st->st_mode & 0111)) + { + int fd, i; + DSO *dso; + struct prelink_entry *ent; + size_t len = strlen (name); + const char *base = NULL; + + for (i = 0; i < blacklist_next; ++i) + if (blacklist_ext[i].is_glob) + { + if (base == NULL) + { + base = strrchr (name, '/'); + if (base == NULL) + base = name; + else + ++base; + } + if (fnmatch (blacklist_ext[i].ext, base, FNM_PERIOD) == 0) + return FTW_CONTINUE; + } + else if (blacklist_ext[i].len <= len + && memcmp (name + len - blacklist_ext[i].len, + blacklist_ext[i].ext, blacklist_ext[i].len) == 0) + return FTW_CONTINUE; + + ent = prelink_find_entry (name, st, 0); + if (ent != NULL && ent->type != ET_NONE) + { + if (verbose > 5) + { + if (ent->type == ET_CACHE_EXEC || ent->type == ET_CACHE_DYN) + printf ("Assuming prelinked %s\n", name); + if (ent->type == ET_UNPRELINKABLE) + printf ("Assuming non-prelinkable %s\n", name); + } + ent->u.explicit = 1; + return FTW_CONTINUE; + } + + if (st->st_size < sizeof (e_ident)) + return FTW_CONTINUE; + + fd = wrap_open (name, O_RDONLY); + if (fd == -1) + return FTW_CONTINUE; + + if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident)) + { +close_it: + close (fd); + return FTW_CONTINUE; + } + + /* Quickly find ET_EXEC ELF binaries and most of PIE binaries. */ + + if (memcmp (e_ident, ELFMAG, SELFMAG) != 0) + { +make_unprelinkable: + if (! undo) + { + ent = prelink_find_entry (name, st, 1); + if (ent != NULL) + { + assert (ent->type == ET_NONE); + ent->type = ET_UNPRELINKABLE; + } + } + close (fd); + return FTW_CONTINUE; + } + + switch (e_ident [EI_DATA]) + { + case ELFDATA2LSB: + if (e_ident [EI_NIDENT + 1] != 0) + goto make_unprelinkable; + if (e_ident [EI_NIDENT] != ET_EXEC) + { + if (e_ident [EI_NIDENT] != ET_DYN) + goto make_unprelinkable; + else if (e_ident [EI_CLASS] == ELFCLASS32) + { + if (e_ident [offsetof (Elf32_Ehdr, e_phoff)] + == sizeof (Elf32_Ehdr) + && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff) + 1, + "\0\0\0", 3) == 0 + && (e_ident [offsetof (Elf32_Ehdr, e_phnum)] + || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1]) + && e_ident [sizeof (Elf32_Ehdr) + + offsetof (Elf32_Phdr, p_type)] == PT_PHDR + && memcmp (e_ident + sizeof (Elf32_Ehdr) + + offsetof (Elf32_Phdr, p_type) + 1, + "\0\0\0", 3) == 0) + { +maybe_pie: + dso = fdopen_dso (fd, name); + if (dso == NULL) + goto close_it; + if (dynamic_info_is_set (dso, DT_DEBUG)) + { + close_dso (dso); + goto make_unprelinkable; + } + close_dso (dso); + } + goto close_it; + } + else if (e_ident [EI_CLASS] == ELFCLASS64) + { + if (e_ident [offsetof (Elf64_Ehdr, e_phoff)] + == sizeof (Elf64_Ehdr) + && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff) + 1, + "\0\0\0\0\0\0\0", 7) == 0 + && (e_ident [offsetof (Elf64_Ehdr, e_phnum)] + || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1]) + && e_ident [sizeof (Elf64_Ehdr) + + offsetof (Elf64_Phdr, p_type)] == PT_PHDR + && memcmp (e_ident + sizeof (Elf64_Ehdr) + + offsetof (Elf64_Phdr, p_type) + 1, + "\0\0\0", 3) == 0) + goto maybe_pie; + goto close_it; + } + else + goto make_unprelinkable; + } + break; + case ELFDATA2MSB: + if (e_ident [EI_NIDENT] != 0) + goto make_unprelinkable; + if (e_ident [EI_NIDENT + 1] != ET_EXEC) + { + if (e_ident [EI_NIDENT + 1] != ET_DYN) + goto make_unprelinkable; + else if (e_ident [EI_CLASS] == ELFCLASS32) + { + if (e_ident [offsetof (Elf32_Ehdr, e_phoff) + 3] + == sizeof (Elf32_Ehdr) + && memcmp (e_ident + offsetof (Elf32_Ehdr, e_phoff), + "\0\0\0", 3) == 0 + && (e_ident [offsetof (Elf32_Ehdr, e_phnum)] + || e_ident [offsetof (Elf32_Ehdr, e_phnum) + 1]) + && e_ident [sizeof (Elf32_Ehdr) + + offsetof (Elf32_Phdr, p_type) + 3] + == PT_PHDR + && memcmp (e_ident + sizeof (Elf32_Ehdr) + + offsetof (Elf32_Phdr, p_type), + "\0\0\0", 3) == 0) + goto maybe_pie; + goto close_it; + } + else if (e_ident [EI_CLASS] == ELFCLASS64) + { + if (e_ident [offsetof (Elf64_Ehdr, e_phoff) + 7] + == sizeof (Elf64_Ehdr) + && memcmp (e_ident + offsetof (Elf64_Ehdr, e_phoff), + "\0\0\0\0\0\0\0", 7) == 0 + && (e_ident [offsetof (Elf64_Ehdr, e_phnum)] + || e_ident [offsetof (Elf64_Ehdr, e_phnum) + 1]) + && e_ident [sizeof (Elf64_Ehdr) + + offsetof (Elf64_Phdr, p_type) + 3] + == PT_PHDR + && memcmp (e_ident + sizeof (Elf64_Ehdr) + + offsetof (Elf64_Phdr, p_type), + "\0\0\0", 3) == 0) + goto maybe_pie; + goto close_it; + } + else + goto make_unprelinkable; + } + break; + default: + goto make_unprelinkable; + } + + dso = fdopen_dso (fd, name); + if (dso == NULL) + return FTW_CONTINUE; + + gather_exec (dso, st); + } + else if (type == FTW_D) + switch (add_dir_to_dirlist (name, st->st_dev, FTW_CHDIR)) + { + case 0: return FTW_CONTINUE; + default: return FTW_STOP; + case 2: +#ifdef HAVE_FTW_ACTIONRETVAL + return FTW_SKIP_SUBTREE; +#else + { + blacklist_dir_len = strlen (name) + 1; + if (blacklist_dir_len > 1 && name[blacklist_dir_len - 2] == '/') + blacklist_dir_len--; + blacklist_dir = malloc (blacklist_dir_len + 1); + if (blacklist_dir == NULL) + { + error (0, ENOMEM, "Cannot store blacklisted dir name"); + return FTW_STOP; + } + memcpy (blacklist_dir, name, blacklist_dir_len - 1); + blacklist_dir[blacklist_dir_len - 1] = '/'; + blacklist_dir[blacklist_dir_len] = '\0'; + return FTW_CONTINUE; + } +#endif + } + + return FTW_CONTINUE; +} + +static int +gather_binlib (const char *name, const struct stat64 *st) +{ + unsigned char e_ident [EI_NIDENT + 2]; + int fd, type; + DSO *dso; + struct prelink_entry *ent; + + if (! S_ISREG (st->st_mode)) + { + error (0, 0, "%s is not a regular file", name); + return 1; + } + + ent = prelink_find_entry (name, st, 0); + if (ent != NULL && ent->type == ET_UNPRELINKABLE) + { + free (ent->depends); + ent->depends = NULL; + ent->ndepends = 0; + ent->type = ET_NONE; + } + if (ent != NULL && ent->type != ET_NONE) + { + ent->u.explicit = 1; + return 0; + } + + fd = wrap_open (name, O_RDONLY); + if (fd == -1) + { + error (0, errno, "Could not open %s", name); + return 1; + } + + if (read (fd, e_ident, sizeof (e_ident)) != sizeof (e_ident)) + { + error (0, errno, "Could not read ELF header from %s", name); + close (fd); + return 1; + } + + /* Quickly find ET_EXEC/ET_DYN ELF binaries/libraries only. */ + + if (memcmp (e_ident, ELFMAG, SELFMAG) != 0) + { + error (0, 0, "%s is not an ELF object", name); + close (fd); + return 1; + } + + switch (e_ident [EI_DATA]) + { + case ELFDATA2LSB: + if (e_ident [EI_NIDENT + 1] != 0) + goto unsupported_type; + type = e_ident [EI_NIDENT]; + break; + case ELFDATA2MSB: + if (e_ident [EI_NIDENT] != 0) + goto unsupported_type; + type = e_ident [EI_NIDENT + 1]; + break; + default: + goto unsupported_type; + } + + if (type != ET_EXEC && type != ET_DYN) + { +unsupported_type: + error (0, 0, "%s is neither ELF executable nor ELF shared library", name); + close (fd); + return 1; + } + + dso = fdopen_dso (fd, name); + if (dso == NULL) + return 0; + + if (type == ET_EXEC) + { + int i; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_INTERP) + break; + + /* If there are no PT_INTERP segments, it is statically linked. */ + if (i == dso->ehdr.e_phnum) + { + error (0, 0, "%s is statically linked", name); + close_dso (dso); + return 1; + } + + return gather_exec (dso, st); + } + + ent = prelink_find_entry (name, st, 1); + if (ent == NULL) + { + close_dso (dso); + return 1; + } + + assert (ent->type == ET_NONE); + ent->type = ET_BAD; + ent->u.explicit = 1; + return gather_dso (dso, ent); +} + +int +gather_object (const char *name, int deref, int onefs) +{ + struct stat64 st; + + if (wrap_stat64 (name, &st) < 0) + { + if (implicit) + return 0; + error (0, errno, "Could not stat %s", name); + return 1; + } + + if (S_ISDIR (st.st_mode)) + { + int flags = 0, ret; + if (! deref) flags |= FTW_PHYS; + if (onefs) flags |= FTW_MOUNT; + + if (implicit && ! deref) + { + ret = add_dir_to_dirlist (name, st.st_dev, flags); + if (ret) + return ret == 2 ? 0 : 1; + } + if (!all && implicit && ! deref) + return 0; + ++implicit; + ret = wrap_nftw64 (name, gather_func, 20, flags | FTW_ACTIONRETVAL); + --implicit; +#ifndef HAVE_FTW_ACTIONRETVAL + free (blacklist_dir); + blacklist_dir = NULL; +#endif + return ret; + } + else + return gather_binlib (name, &st); +} + +int +gather_config (const char *config) +{ + FILE *file = fopen (config, "r"); + char *line = NULL; + size_t len; + int ret = 0; + + if (file == NULL) + { + error (0, errno, "Can't open configuration file %s", config); + return 1; + } + + implicit = 1; + do + { + ssize_t i = getline (&line, &len, file); + int deref = 0; + int onefs = 0; + char *p; + + if (i < 0) + break; + + if (line[i - 1] == '\n') + line[i - 1] = '\0'; + + p = strchr (line, '#'); + if (p != NULL) + *p = '\0'; + + p = line + strspn (line, " \t"); + + while (*p == '-') + { + switch (p[1]) + { + case 'h': deref = 1; break; + case 'l': onefs = 1; break; + case 'b': *p = '\0'; continue; + default: + error (0, 0, "Unknown directory option `%s'\n", p); + break; + } + p = p + 2 + strspn (p + 2, " \t"); + } + + if (*p == '\0') + continue; + + if (strpbrk (p, "*?[{") == NULL) + { + ret = gather_object (p, deref, onefs); + if (ret) + { + ret = 1; + break; + } + } + else + { + glob_t g; + + if (!glob (p, GLOB_BRACE, NULL, &g)) + { + size_t n; + + for (n = 0; n < g.gl_pathc; ++n) + { + ret = gather_object (g.gl_pathv[n], deref, onefs); + if (ret) + { + ret = 1; + break; + } + } + + globfree (&g); + if (ret) + break; + } + } + } while (!feof (file)); + + free (line); + fclose (file); + implicit = 0; + return ret; +} + +static int +gather_check_lib (void **p, void *info) +{ + struct prelink_entry *e = * (struct prelink_entry **) p; + + if (e->type != ET_DYN) + return 1; + + if (! e->u.explicit) + { + struct prelink_dir *dir; + const char *name; + size_t len; + + name = strrchr (e->canon_filename, '/'); + if (!name) + name = e->canon_filename; + len = name - e->canon_filename; + + for (dir = blacklist; dir; dir = dir->next) + if (((dir->flags != FTW_CHDIR && len >= dir->len) + || (dir->flags == FTW_CHDIR && len == dir->len)) + && strncmp (dir->dir, e->canon_filename, dir->len) == 0) + { + if (dir->flags == FTW_CHDIR) + break; + if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev) + continue; + break; + } + + if (dir != NULL) + { + error (0, 0, "%s is present in a blacklisted directory %s", + e->canon_filename, dir->dir); + e->type = ET_BAD; + return 1; + } + + for (dir = dirs; dir; dir = dir->next) + if (((dir->flags != FTW_CHDIR && len >= dir->len) + || (dir->flags == FTW_CHDIR && len == dir->len)) + && strncmp (dir->dir, e->canon_filename, dir->len) == 0) + { + if (dir->flags == FTW_CHDIR) + break; + if ((dir->flags & FTW_MOUNT) && dir->dev != e->dev) + continue; + break; + } + + if (dir == NULL) + { + error (0, 0, "%s is not present in any config file directories, nor was specified on command line", + e->canon_filename); + e->type = ET_BAD; + return 1; + } + } + + return 1; +} + +int +gather_check_libs (void) +{ + struct prelink_dir *dir; + void *f; + + htab_traverse (prelink_filename_htab, gather_check_lib, NULL); + + dir = dirs; + while (dir != NULL) + { + f = dir; + dir = dir->next; + free (f); + } + + dir = blacklist; + while (dir != NULL) + { + f = dir; + dir = dir->next; + free (f); + } + + dirs = NULL; + blacklist = NULL; + return 0; +} + +int +add_to_blacklist (const char *name, int deref, int onefs) +{ + const char *canon_name; + struct prelink_dir *path; + size_t len; + struct stat64 st; + + if (stat64 (name, &st) < 0) + { + if (implicit) + return 0; + error (0, errno, "Could not stat %s", name); + return 1; + } + + if (!S_ISDIR (st.st_mode)) + { + struct prelink_entry *ent; + + ent = prelink_find_entry (name, &st, 1); + if (ent == NULL) + return 1; + + ent->type = ET_BAD; + ent->u.explicit = 1; + return 0; + } + + canon_name = wrap_prelink_canonicalize (name, NULL); + if (canon_name == NULL) + { + if (implicit) + return 0; + error (0, errno, "Could not canonicalize %s", name); + return 1; + } + + len = strlen (canon_name); + path = malloc (sizeof (struct prelink_dir) + len + 1); + if (path == NULL) + { + error (0, ENOMEM, "Could not record path %s", name); + free ((char *) canon_name); + return 1; + } + + path->next = blacklist; + path->flags = 0; + if (! deref) path->flags |= FTW_PHYS; + if (onefs) path->flags |= FTW_MOUNT; + path->dev = 0; + path->len = len; + strcpy (path->dir, canon_name); + free ((char *) canon_name); + blacklist = path; + return 0; +} + +void +add_blacklist_ext (const char *ext) +{ + blacklist_ext = realloc (blacklist_ext, + (blacklist_next + 1) * sizeof (*blacklist_ext)); + if (blacklist_ext == NULL) + error (EXIT_FAILURE, errno, "can't create blacklist extension list"); + if (*ext == '*' && strpbrk (ext + 1, "*?[{") == NULL) + { + blacklist_ext[blacklist_next].is_glob = 0; + ext++; + } + else + blacklist_ext[blacklist_next].is_glob = 1; + blacklist_ext[blacklist_next].ext = strdup (ext); + if (blacklist_ext[blacklist_next].ext == NULL) + error (EXIT_FAILURE, errno, "can't create blacklist extension list"); + blacklist_ext[blacklist_next].len = strlen (ext); + blacklist_next++; +} + +int +blacklist_from_config (const char *config) +{ + FILE *file = fopen (config, "r"); + char *line = NULL; + size_t len; + int ret = 0; + + if (file == NULL) + { + error (0, errno, "Can't open configuration file %s", config); + return 1; + } + + implicit = 1; + do + { + ssize_t i = getline (&line, &len, file); + int deref = 0; + int onefs = 0; + int blacklist = 0; + char *p; + + if (i < 0) + break; + + if (line[i - 1] == '\n') + line[i - 1] = '\0'; + + p = strchr (line, '#'); + if (p != NULL) + *p = '\0'; + + p = line + strspn (line, " \t"); + + while (*p == '-') + { + switch (p[1]) + { + case 'h': deref = 1; break; + case 'l': onefs = 1; break; + case 'b': blacklist = 1; break; + } + p = p + 2 + strspn (p + 2, " \t"); + } + + if (*p == '\0' || !blacklist) + continue; + + if (strchr (p, '/') == NULL) + { + add_blacklist_ext (p); + continue; + } + + if (strpbrk (p, "*?[{") == NULL) + { + ret = add_to_blacklist (p, deref, onefs); + if (ret) + { + ret = 1; + break; + } + } + else + { + glob_t g; + + if (!glob (p, GLOB_BRACE | GLOB_PERIOD, NULL, &g)) + { + size_t n; + + for (n = 0; n < g.gl_pathc; ++n) + { + ret = add_to_blacklist (g.gl_pathv[n], deref, onefs); + if (ret) + { + ret = 1; + break; + } + } + + globfree (&g); + if (ret) + break; + } + } + } while (!feof (file)); + + free (line); + fclose (file); + implicit = 0; + return ret; +} diff --git a/trunk/src/get.c b/trunk/src/get.c new file mode 100644 index 0000000..0ae418b --- /dev/null +++ b/trunk/src/get.c @@ -0,0 +1,673 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include <sys/wait.h> +#include "prelink.h" + +int +is_ldso_soname (const char *soname) +{ + if (! strcmp (soname, "ld-linux.so.2") + || ! strcmp (soname, "ld-linux.so.3") + || ! strcmp (soname, "ld.so.1") + || ! strcmp (soname, "ld-linux-ia64.so.2") + || ! strcmp (soname, "ld-linux-x86-64.so.2") + || ! strcmp (soname, "ld64.so.1")) + return 1; + return 0; +} + +static int +prelink_record_relocations (struct prelink_info *info, FILE *f, + const char *ent_filename) +{ + char buffer[8192]; + DSO *dso = info->dso; + struct prelink_entry *ent, *ent2; + struct prelink_tls *tls; + struct deps + { + struct prelink_entry *ent; + char *soname; + GElf_Addr start; + GElf_Addr l_addr; + GElf_Addr tls_modid; + GElf_Addr tls_offset; + } deps[info->ent->ndepends + 1]; + char *r; + int i, ndeps = 0, undef = 0, seen = 0, tdeps = 0; + int mask_32bit = (info->dso->ehdr.e_ident[EI_CLASS] == ELFCLASS32); + + /* Record the dependencies. */ + while ((r = fgets (buffer, 8192, f)) != NULL) + { + char *soname, *filename, *p, *q; + GElf_Addr start = 0, l_addr = 0, tls_modid = 0, tls_offset = 0; + unsigned long long l; + + if (buffer[0] != '\t' || (filename = strstr (buffer, " => ")) == NULL) + break; + soname = buffer + 1; + p = strstr (filename + sizeof (" => "), " (0x"); + if (p != NULL) + { + l = strtoull (p + sizeof (" (0x") - 1, &q, 16); + start = (GElf_Addr) l; + if (start != l || strncmp (q, ", 0x", sizeof (", 0x") - 1)) + p = NULL; + else + { + l = strtoull (q + sizeof (", 0x") - 1, &q, 16); + l_addr = (GElf_Addr) l; + if (l_addr != l || q[-1] == 'x') + p = NULL; + else if (strncmp (q, ") TLS(0x", sizeof (") TLS(0x") - 1) == 0) + { + l = strtoull (q + sizeof (") TLS(0x") - 1, &q, 16); + tls_modid = (GElf_Addr) l; + if (tls_modid != l || q[-1] == 'x' + || strncmp (q, ", 0x", sizeof (", 0x") - 1)) + p = NULL; + else + { + l = strtoull (q + sizeof (", 0x") - 1, &q, 16); + tls_offset = (GElf_Addr) l; + if (tls_offset != l || q[-1] == 'x') + p = NULL; + } + } + if (p && strcmp (q, ")\n")) + p = NULL; + } + } + if (p == NULL) + { + p = strchr (buffer, '\n'); + if (p != NULL) + *p = '\0'; + error (0, 0, "Could not parse line `%s'", buffer); + goto error_out; + } + *filename = '\0'; + filename += sizeof (" => ") - 1; + *p = '\0'; + + if (ndeps > info->ent->ndepends) + { + error (0, 0, "%s: Recorded %d dependencies, now seeing %d\n", + info->ent->filename, info->ent->ndepends, ndeps - 1); + goto error_out; + } + + tdeps = ndeps - seen + 1; + if (! seen + && (strcmp (info->ent->filename, filename) == 0 + || (info->ent->filename != ent_filename + && strcmp (ent_filename, filename) == 0) + || strcmp (info->ent->canon_filename, filename) == 0)) + { + seen = 1; + tdeps = 0; + } + else if (ent2 = info->ent->depends [tdeps - 1], + strcmp (ent2->filename, filename) != 0 + && strcmp (ent2->canon_filename, filename) != 0) + { + struct prelink_link *hardlink; + + for (hardlink = ent2->hardlink; hardlink; hardlink = hardlink->next) + if (strcmp (hardlink->canon_filename, filename) == 0) + break; + + if (hardlink == NULL) + { + struct stat64 st; + + if (wrap_stat64 (filename, &st) < 0) + { + error (0, errno, "%s: Could not stat %s", + info->ent->filename, filename); + goto error_out; + } + + if (st.st_dev != ent2->dev || st.st_ino != ent2->ino) + { + error (0, 0, "%s: %s => %s does not match recorded dependency", + info->ent->filename, soname, filename); + goto error_out; + } + } + } + + if (! tdeps) + deps[0].ent = info->ent; + else + deps[tdeps].ent = info->ent->depends[tdeps - 1]; + deps[tdeps].soname = strdup (soname); + if (deps[tdeps].soname == NULL) + { + error (0, ENOMEM, "Could not record `%s' SONAME", soname); + goto error_out; + } + deps[tdeps].start = start; + deps[tdeps].l_addr = l_addr; + deps[tdeps].tls_modid = tls_modid; + deps[tdeps].tls_offset = tls_offset; + ++ndeps; + } + + if (ndeps != info->ent->ndepends + 1) + { + error (0, 0, "%s: Recorded %d dependencies, now seeing %d\n", + info->ent->filename, info->ent->ndepends, ndeps - 1); + goto error_out; + } + + if (r == NULL && !ndeps) + { + error (0, 0, "%s: %s did not print any lookup lines", info->ent->filename, + dynamic_linker ?: dso->arch->dynamic_linker); + goto error_out; + } + + info->tls = malloc (ndeps * sizeof (struct prelink_tls)); + if (info->tls == NULL) + { + error (0, ENOMEM, "%s: Could not record dependency TLS information", + dso->filename); + goto error_out; + } + + for (i = 0; i < ndeps; i++) + { + info->tls[i].modid = deps[i].tls_modid; + info->tls[i].offset = deps[i].tls_offset; + } + + if (dso->ehdr.e_type == ET_EXEC || dso->arch->create_opd) + { + info->conflicts = (struct prelink_conflict **) + calloc (sizeof (struct prelink_conflict *), ndeps); + if (info->conflicts == NULL) + { + error (0, ENOMEM, "%s: Can't build list of conflicts", info->ent->filename); + goto error_out; + } + } + do + { + unsigned long long symstart, symoff, valstart[3], value[3]; + int reloc_class, len, type = 1; + char *symname; + + r = strchr (buffer, '\n'); + if (r) + *r = '\0'; + if (strncmp (buffer, "lookup ", sizeof ("lookup ") - 1) == 0) + { + struct prelink_symbol *s; + + if (sscanf (buffer, "lookup 0x%llx 0x%llx -> 0x%llx 0x%llx %n", + &symstart, &symoff, &valstart[0], &value[0], &len) != 4) + { + error (0, 0, "%s: Could not parse `%s'", info->ent->filename, buffer); + goto error_out; + } + + if (buffer[len] == '/') + { + ++len; + type = 0; + } + + reloc_class = strtoul (buffer + len, &symname, 16); + if (buffer + len == symname || (reloc_class == 0 && type) + || (*symname != ' ' && *symname != '\t')) + { + error (0, 0, "%s: Could not parse `%s'", info->ent->filename, buffer); + goto error_out; + } + + if (type) + reloc_class = dso->arch->reloc_class (reloc_class); + else + reloc_class |= RTYPE_CLASS_VALID; + + while (*symname == ' ' || *symname == '\t') ++symname; + + ent = NULL; + tls = NULL; + if (symstart == deps[0].start + || (reloc_class == RTYPE_CLASS_TLS && info->conflicts)) + { + for (i = 0; i < ndeps; i++) + if (deps[i].start == valstart[0]) + { + if (reloc_class == RTYPE_CLASS_TLS) + tls = info->tls + i; + else + { + ent = deps[i].ent; + /* If the library the symbol is bound to is already + prelinked, adjust the value so that it is relative + to library base. */ + if (mask_32bit) + value[0] -= (Elf32_Addr) (deps[i].start - deps[i].l_addr); + else + value[0] -= deps[i].start - deps[i].l_addr; + } + break; + } + + if (ent == NULL && tls == NULL && valstart[0]) + { + error (0, 0, "Could not find base 0x%08llx in the list of bases `%s'", + valstart[0], buffer); + goto error_out; + } + } + + if (symstart == deps[0].start) + { + /* Only interested in relocations from the current object. */ + if (symoff < info->symtab_start || symoff >= info->symtab_end) + { + error (0, 0, "%s: Symbol `%s' offset 0x%08llx does not point into .dynsym section", + info->ent->filename, symname, symoff); + goto error_out; + } + + if (ent == info->ent && reloc_class != RTYPE_CLASS_TLS) + value[0] = adjust_old_to_new (info->dso, value[0]); + + s = &info->symbols[(symoff - info->symtab_start) + / info->symtab_entsize]; + if (s->reloc_class) + { + while (s->reloc_class != reloc_class && s->next != NULL) + s = s->next; + if (s->reloc_class == reloc_class) + { + if ((reloc_class != RTYPE_CLASS_TLS && s->u.ent != ent) + || (reloc_class == RTYPE_CLASS_TLS + && s->u.tls != tls) + || s->value != value[0]) + { + error (0, 0, "%s: Symbol `%s' with the same reloc type resolves to different values each time", + info->ent->filename, symname); + goto error_out; + } + s = NULL; + } + else + { + s->next = (struct prelink_symbol *) + malloc (sizeof (struct prelink_symbol)); + if (s->next == NULL) + { + error (0, ENOMEM, "Cannot build symbol lookup map"); + goto error_out; + } + s = s->next; + } + } + if (s) + { + if (reloc_class == RTYPE_CLASS_TLS) + s->u.tls = tls; + else + s->u.ent = ent; + s->value = value[0]; + s->reloc_class = reloc_class; + s->next = NULL; + } + } + else if (reloc_class == RTYPE_CLASS_TLS && info->conflicts) + { + struct prelink_conflict *conflict; + int symowner; + + for (symowner = 1; symowner < ndeps; symowner++) + if (deps[symowner].start == symstart) + break; + if (symowner == ndeps) + { + error (0, 0, "Could not find base 0x%08llx in the list of bases `%s'", + symstart, buffer); + goto error_out; + } + + for (conflict = info->conflicts[symowner]; conflict; + conflict = conflict->next) + if (conflict->symoff == symoff + && conflict->reloc_class == reloc_class) + { + if (conflict->lookup.tls != tls + || conflict->conflict.tls != tls + || conflict->lookupval != value[0] + || conflict->conflictval != value[0]) + { + error (0, 0, "%s: Symbol `%s' with the same reloc type resolves to different values each time", + info->ent->filename, symname); + goto error_out; + } + break; + } + if (conflict == NULL) + { + conflict = malloc (sizeof (struct prelink_conflict)); + if (conflict == NULL) + { + error (0, ENOMEM, "Cannot build list of conflicts"); + goto error_out; + } + + conflict->next = info->conflicts[symowner]; + info->conflicts[symowner] = conflict; + conflict->lookup.tls = tls; + conflict->conflict.tls = tls; + conflict->lookupval = value[0]; + conflict->conflictval = value[0]; + conflict->symoff = symoff; + conflict->reloc_class = reloc_class; + conflict->used = 0; + } + } + } + else if (strncmp (buffer, "conflict ", sizeof ("conflict ") - 1) == 0) + { + if (sscanf (buffer, "conflict 0x%llx 0x%llx -> 0x%llx 0x%llx x 0x%llx 0x%llx %n", + &symstart, &symoff, &valstart[0], &value[0], + &valstart[1], &value[1], &len) != 6) + { + error (0, 0, "%s: Could not parse `%s'", info->ent->filename, buffer); + goto error_out; + } + + if (buffer[len] == '/') + { + ++len; + type = 0; + } + + reloc_class = strtoul (buffer + len, &symname, 16); + if (buffer + len == symname || (reloc_class == 0 && type) + || (*symname != ' ' && *symname != '\t')) + { + error (0, 0, "%s: Could not parse `%s'", info->ent->filename, buffer); + goto error_out; + } + + if (type) + reloc_class = dso->arch->reloc_class (reloc_class); + else + reloc_class |= RTYPE_CLASS_VALID; + + while (*symname == ' ' || *symname == '\t') ++symname; + + if (symstart == deps[0].start) + { + error (0, 0, "Conflict in _dl_loaded `%s'", buffer); + goto error_out; + } + + if (info->conflicts) + { + struct prelink_entry *ents[2]; + struct prelink_tls *tlss[2]; + struct prelink_conflict *conflict; + int symowner, j; + + for (symowner = 1; symowner < ndeps; symowner++) + if (deps[symowner].start == symstart) + break; + if (symowner == ndeps) + { + error (0, 0, "Could not find base 0x%08llx in the list of bases `%s'", + symstart, buffer); + goto error_out; + } + + for (j = 0; j < 2; j++) + { + ents[j] = NULL; + tlss[j] = NULL; + for (i = 0; i < ndeps; i++) + if (deps[i].start == valstart[j]) + { + if (reloc_class == RTYPE_CLASS_TLS) + tlss[j] = info->tls + i; + else + { + ents[j] = deps[i].ent; + /* If the library the symbol is bound to is already + prelinked, adjust the value so that it is relative + to library base. */ + if (mask_32bit) + value[j] -= (Elf32_Addr) (deps[i].start - deps[i].l_addr); + else + value[j] -= deps[i].start - deps[i].l_addr; + } + break; + } + if (ents[j] == NULL && tlss[j] == NULL && valstart[j]) + { + error (0, 0, "Could not find base 0x%08llx in the list of bases `%s'", + valstart[j], buffer); + goto error_out; + } + } + + for (conflict = info->conflicts[symowner]; conflict; + conflict = conflict->next) + if (conflict->symoff == symoff + && conflict->reloc_class == reloc_class) + { + if ((reloc_class != RTYPE_CLASS_TLS + && (conflict->lookup.ent != ents[0] + || conflict->conflict.ent != ents[1])) + || (reloc_class == RTYPE_CLASS_TLS + && (conflict->lookup.tls != tlss[0] + || conflict->conflict.tls != tlss[1])) + || conflict->lookupval != value[0] + || conflict->conflictval != value[1]) + { + error (0, 0, "%s: Symbol `%s' with the same reloc type resolves to different values each time", + info->ent->filename, symname); + goto error_out; + } + break; + } + if (conflict == NULL) + { + conflict = malloc (sizeof (struct prelink_conflict)); + if (conflict == NULL) + { + error (0, ENOMEM, "Cannot build list of conflicts"); + goto error_out; + } + + conflict->next = info->conflicts[symowner]; + info->conflicts[symowner] = conflict; + if (reloc_class != RTYPE_CLASS_TLS) + { + conflict->lookup.ent = ents[0]; + conflict->conflict.ent = ents[1]; + } + else + { + conflict->lookup.tls = tlss[0]; + conflict->conflict.tls = tlss[1]; + } + conflict->lookupval = value[0]; + conflict->conflictval = value[1]; + conflict->symoff = symoff; + conflict->reloc_class = reloc_class; + conflict->used = 0; + } + } + } + else if (strncmp (buffer, "undefined symbol: ", + sizeof ("undefined symbol: ") - 1) == 0 && ! undef) + { + undef = 1; + if (verbose) + error (0, 0, "Warning: %s has undefined non-weak symbols", + info->ent->filename); + } + } while (fgets (buffer, 8192, f) != NULL); + + info->sonames = malloc (ndeps * sizeof (const char *)); + if (info->sonames == NULL) + { + error (0, ENOMEM, "%s: Could not record dependency SONAMEs", dso->filename); + goto error_out; + } + + for (i = 0; i < ndeps; i++) + info->sonames[i] = deps[i].soname; + + return 0; + +error_out: + for (i = 0; i < ndeps; i++) + free (deps[i].soname); + return 1; +} + +int +prelink_get_relocations (struct prelink_info *info) +{ + FILE *f; + DSO *dso = info->dso; + const char *argv[6]; + const char *envp[4]; + int i, ret, status; + char *p; + const char *dl = dynamic_linker ?: dso->arch->dynamic_linker; + const char *ent_filename; + + if (info->ent->type == ET_DYN) + { + assert (info->ent->base == dso->base); + if (info->ent->end < dso->end) + { + error (0, 0, "%s: grew since it has been recorded", info->ent->filename); + return 0; + } + } + else + { + info->ent->base = dso->base; + info->ent->end = dso->end; + } + + if (is_ldso_soname (info->dso->soname)) + return 1; + + info->symbol_count = (info->symtab_end - info->symtab_start) + / info->symtab_entsize; + info->symbols = calloc (sizeof (struct prelink_symbol), info->symbol_count); + + if (strchr (info->ent->filename, '/') != NULL) + ent_filename = info->ent->filename; + else + { + size_t flen = strlen (info->ent->filename); + char *p = alloca (2 + flen + 1); + memcpy (p, "./", 2); + memcpy (p + 2, info->ent->filename, flen + 1); + ent_filename = p; + } + if (prelink_rtld == NULL) + { + i = 0; + argv[i++] = dl; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = ent_filename; + argv[i] = NULL; + envp[0] = "LD_TRACE_LOADED_OBJECTS=1"; + envp[1] = "LD_BIND_NOW=1"; + p = alloca (sizeof "LD_TRACE_PRELINKING=" + strlen (info->ent->filename)); + strcpy (stpcpy (p, "LD_TRACE_PRELINKING="), info->ent->filename); + envp[2] = p; + envp[3] = NULL; + ret = 2; + f = execve_open (dl, (char * const *)argv, (char * const *)envp); + } + else + { + i = 0; + argv[i++] = prelink_rtld; + if (ld_library_path) + { + argv[i++] = "--library-path"; + argv[i++] = ld_library_path; + } + argv[i++] = "--target-paths"; + argv[i++] = ent_filename; + argv[i] = NULL; + p = alloca (sizeof "RTLD_TRACE_PRELINKING=" + strlen (info->ent->filename)); + strcpy (stpcpy (p, "RTLD_TRACE_PRELINKING="), info->ent->filename); + envp[0] = p; + p = alloca (sizeof "PATH=" + strlen (getenv ("PATH"))); + sprintf (p, "PATH=%s", getenv ("PATH")); + envp[1] = p; + envp[2] = NULL; + if (sysroot) + { + p = alloca (sizeof "PRELINK_SYSROOT=" + strlen (sysroot)); + sprintf (p, "PRELINK_SYSROOT=%s", sysroot); + envp[2] = p; + envp[3] = NULL; + } + ret = 2; + f = execve_open (prelink_rtld, (char * const *)argv, (char * const *)envp); + } + + if (f == NULL) + { + error (0, errno, "%s: Could not trace symbol resolving", + info->ent->filename); + return 0; + } + + if (prelink_record_relocations (info, f, ent_filename)) + ret = 0; + + if ((status = execve_close (f))) + { + if (ret) + error (0, status == -1 ? errno : 0, + "%s Could not trace symbol resolving", info->ent->filename); + return 0; + } + + return ret; +} diff --git a/trunk/src/hashtab.c b/trunk/src/hashtab.c new file mode 100644 index 0000000..fa27446 --- /dev/null +++ b/trunk/src/hashtab.c @@ -0,0 +1,609 @@ +/* An expandable hash tables datatype. + Copyright (C) 1999, 2000, 2001 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). + +This file is part of the libiberty library. +Libiberty is free software; you can redistribute it and/or +modify it under the terms of the GNU Library General Public +License as published by the Free Software Foundation; either +version 2 of the License, or (at your option) any later version. + +Libiberty is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +Library General Public License for more details. + +You should have received a copy of the GNU Library General Public +License along with libiberty; see the file COPYING.LIB. If +not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, +Boston, MA 02111-1307, USA. */ + +/* This package implements basic hash table functionality. It is possible + to search for an entry, create an entry and destroy an entry. + + Elements in the table are generic pointers. + + The size of the table is not fixed; if the occupancy of the table + grows too high the hash table will be expanded. + + The abstract data implementation is based on generalized Algorithm D + from Knuth's book "The art of computer programming". Hash table is + expanded by creation of new hash table and transferring elements from + the old table to the new table. */ + +#include <config.h> +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include "hashtab.h" + +/* This macro defines reserved value for empty table entry. */ + +#define EMPTY_ENTRY ((void *) 0) + +/* This macro defines reserved value for table entry which contained + a deleted element. */ + +#define DELETED_ENTRY ((void *) 1) + +static unsigned long higher_prime_number (unsigned long); +static hashval_t hash_pointer (const void *); +static int eq_pointer (const void *, const void *); +static int htab_expand (htab_t); +static void **find_empty_slot_for_expand (htab_t, hashval_t); + +/* At some point, we could make these be NULL, and modify the + hash-table routines to handle NULL specially; that would avoid + function-call overhead for the common case of hashing pointers. */ +htab_hash htab_hash_pointer = hash_pointer; +htab_eq htab_eq_pointer = eq_pointer; + +/* The following function returns a nearest prime number which is + greater than N, and near a power of two. */ + +static unsigned long +higher_prime_number (n) + unsigned long n; +{ + /* These are primes that are near, but slightly smaller than, a + power of two. */ + static unsigned long primes[] = { + (unsigned long) 2, + (unsigned long) 7, + (unsigned long) 13, + (unsigned long) 31, + (unsigned long) 61, + (unsigned long) 127, + (unsigned long) 251, + (unsigned long) 509, + (unsigned long) 1021, + (unsigned long) 2039, + (unsigned long) 4093, + (unsigned long) 8191, + (unsigned long) 16381, + (unsigned long) 32749, + (unsigned long) 65521, + (unsigned long) 131071, + (unsigned long) 262139, + (unsigned long) 524287, + (unsigned long) 1048573, + (unsigned long) 2097143, + (unsigned long) 4194301, + (unsigned long) 8388593, + (unsigned long) 16777213, + (unsigned long) 33554393, + (unsigned long) 67108859, + (unsigned long) 134217689, + (unsigned long) 268435399, + (unsigned long) 536870909, + (unsigned long) 1073741789, + (unsigned long) 2147483647, + /* 4294967291L */ + ((unsigned long) 2147483647) + ((unsigned long) 2147483644), + }; + + unsigned long* low = &primes[0]; + unsigned long* high = &primes[sizeof(primes) / sizeof(primes[0])]; + + while (low != high) + { + unsigned long* mid = low + (high - low) / 2; + if (n > *mid) + low = mid + 1; + else + high = mid; + } + + /* If we've run out of primes, abort. */ + if (n > *low) + { + fprintf (stderr, "Cannot find prime bigger than %lu\n", n); + abort (); + } + + return *low; +} + +/* Returns a hash code for P. */ + +static hashval_t +hash_pointer (p) + const void * p; +{ + return (hashval_t) ((long)p >> 3); +} + +/* Returns non-zero if P1 and P2 are equal. */ + +static int +eq_pointer (p1, p2) + const void * p1; + const void * p2; +{ + return p1 == p2; +} + +/* This function creates table with length slightly longer than given + source length. The created hash table is initiated as empty (all the + hash table entries are EMPTY_ENTRY). The function returns the created + hash table. Memory allocation may fail; it may return NULL. */ + +htab_t +htab_try_create (size, hash_f, eq_f, del_f) + size_t size; + htab_hash hash_f; + htab_eq eq_f; + htab_del del_f; +{ + htab_t result; + + size = higher_prime_number (size); + result = (htab_t) calloc (1, sizeof (struct htab)); + if (result == NULL) + return NULL; + + result->entries = (void **) calloc (size, sizeof (void *)); + if (result->entries == NULL) + { + free (result); + return NULL; + } + + result->size = size; + result->hash_f = hash_f; + result->eq_f = eq_f; + result->del_f = del_f; + result->return_allocation_failure = 1; + return result; +} + +/* This function frees all memory allocated for given hash table. + Naturally the hash table must already exist. */ + +void +htab_delete (htab) + htab_t htab; +{ + int i; + + if (htab->del_f) + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i] != EMPTY_ENTRY + && htab->entries[i] != DELETED_ENTRY) + (*htab->del_f) (htab->entries[i]); + + free (htab->entries); + free (htab); +} + +/* This function clears all entries in the given hash table. */ + +void +htab_empty (htab) + htab_t htab; +{ + int i; + + if (htab->del_f) + for (i = htab->size - 1; i >= 0; i--) + if (htab->entries[i] != EMPTY_ENTRY + && htab->entries[i] != DELETED_ENTRY) + (*htab->del_f) (htab->entries[i]); + + memset (htab->entries, 0, htab->size * sizeof (void *)); +} + +/* Similar to htab_find_slot, but without several unwanted side effects: + - Does not call htab->eq_f when it finds an existing entry. + - Does not change the count of elements/searches/collisions in the + hash table. + This function also assumes there are no deleted entries in the table. + HASH is the hash value for the element to be inserted. */ + +static void ** +find_empty_slot_for_expand (htab, hash) + htab_t htab; + hashval_t hash; +{ + size_t size = htab->size; + hashval_t hash2 = 1 + hash % (size - 2); + unsigned int index = hash % size; + + for (;;) + { + void **slot = htab->entries + index; + + if (*slot == EMPTY_ENTRY) + return slot; + else if (*slot == DELETED_ENTRY) + abort (); + + index += hash2; + if (index >= size) + index -= size; + } +} + +/* The following function changes size of memory allocated for the + entries and repeatedly inserts the table elements. The occupancy + of the table after the call will be about 50%. Naturally the hash + table must already exist. Remember also that the place of the + table entries is changed. If memory allocation failures are allowed, + this function will return zero, indicating that the table could not be + expanded. If all goes well, it will return a non-zero value. */ + +static int +htab_expand (htab) + htab_t htab; +{ + void **oentries; + void **olimit; + void **p; + + oentries = htab->entries; + olimit = oentries + htab->size; + + htab->size = higher_prime_number (htab->size * 2); + + if (htab->return_allocation_failure) + { + void **nentries = (void **) calloc (htab->size, sizeof (void **)); + if (nentries == NULL) + return 0; + htab->entries = nentries; + } + + htab->n_elements -= htab->n_deleted; + htab->n_deleted = 0; + + p = oentries; + do + { + void * x = *p; + + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) + { + void **q = find_empty_slot_for_expand (htab, (*htab->hash_f) (x)); + + *q = x; + } + + p++; + } + while (p < olimit); + + free (oentries); + return 1; +} + +/* This function searches for a hash table entry equal to the given + element. It cannot be used to insert or delete an element. */ + +void * +htab_find_with_hash (htab, element, hash) + htab_t htab; + const void * element; + hashval_t hash; +{ + unsigned int index; + hashval_t hash2; + size_t size; + void * entry; + + htab->searches++; + size = htab->size; + index = hash % size; + + entry = htab->entries[index]; + if (entry == EMPTY_ENTRY + || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))) + return entry; + + hash2 = 1 + hash % (size - 2); + + for (;;) + { + htab->collisions++; + index += hash2; + if (index >= size) + index -= size; + + entry = htab->entries[index]; + if (entry == EMPTY_ENTRY + || (entry != DELETED_ENTRY && (*htab->eq_f) (entry, element))) + return entry; + } +} + +/* Like htab_find_slot_with_hash, but compute the hash value from the + element. */ + +void * +htab_find (htab, element) + htab_t htab; + const void * element; +{ + return htab_find_with_hash (htab, element, (*htab->hash_f) (element)); +} + +/* This function searches for a hash table slot containing an entry + equal to the given element. To delete an entry, call this with + INSERT = 0, then call htab_clear_slot on the slot returned (possibly + after doing some checks). To insert an entry, call this with + INSERT = 1, then write the value you want into the returned slot. + When inserting an entry, NULL may be returned if memory allocation + fails. */ + +void ** +htab_find_slot_with_hash (htab, element, hash, insert) + htab_t htab; + const void * element; + hashval_t hash; + enum insert_option insert; +{ + void **first_deleted_slot; + unsigned int index; + hashval_t hash2; + size_t size; + + if (insert == INSERT && htab->size * 3 <= htab->n_elements * 4 + && htab_expand (htab) == 0) + return NULL; + + size = htab->size; + hash2 = 1 + hash % (size - 2); + index = hash % size; + + htab->searches++; + first_deleted_slot = NULL; + + for (;;) + { + void * entry = htab->entries[index]; + if (entry == EMPTY_ENTRY) + { + if (insert == NO_INSERT) + return NULL; + + htab->n_elements++; + + if (first_deleted_slot) + { + *first_deleted_slot = EMPTY_ENTRY; + return first_deleted_slot; + } + + return &htab->entries[index]; + } + + if (entry == DELETED_ENTRY) + { + if (!first_deleted_slot) + first_deleted_slot = &htab->entries[index]; + } + else if ((*htab->eq_f) (entry, element)) + return &htab->entries[index]; + + htab->collisions++; + index += hash2; + if (index >= size) + index -= size; + } +} + +/* Like htab_find_slot_with_hash, but compute the hash value from the + element. */ + +void ** +htab_find_slot (htab, element, insert) + htab_t htab; + const void * element; + enum insert_option insert; +{ + return htab_find_slot_with_hash (htab, element, (*htab->hash_f) (element), + insert); +} + +/* This function deletes an element with the given value from hash + table. If there is no matching element in the hash table, this + function does nothing. */ + +void +htab_remove_elt (htab, element) + htab_t htab; + void * element; +{ + void **slot; + + slot = htab_find_slot (htab, element, NO_INSERT); + if (*slot == EMPTY_ENTRY) + return; + + if (htab->del_f) + (*htab->del_f) (*slot); + + *slot = DELETED_ENTRY; + htab->n_deleted++; +} + +/* This function clears a specified slot in a hash table. It is + useful when you've already done the lookup and don't want to do it + again. */ + +void +htab_clear_slot (htab, slot) + htab_t htab; + void **slot; +{ + if (slot < htab->entries || slot >= htab->entries + htab->size + || *slot == EMPTY_ENTRY || *slot == DELETED_ENTRY) + abort (); + + if (htab->del_f) + (*htab->del_f) (*slot); + + *slot = DELETED_ENTRY; + htab->n_deleted++; +} + +/* This function scans over the entire hash table calling + CALLBACK for each live entry. If CALLBACK returns false, + the iteration stops. INFO is passed as CALLBACK's second + argument. */ + +void +htab_traverse (htab, callback, info) + htab_t htab; + htab_trav callback; + void * info; +{ + void **slot = htab->entries; + void **limit = slot + htab->size; + + do + { + void * x = *slot; + + if (x != EMPTY_ENTRY && x != DELETED_ENTRY) + if (!(*callback) (slot, info)) + break; + } + while (++slot < limit); +} + +/* Return the current size of given hash table. */ + +size_t +htab_size (htab) + htab_t htab; +{ + return htab->size; +} + +/* Return the current number of elements in given hash table. */ + +size_t +htab_elements (htab) + htab_t htab; +{ + return htab->n_elements - htab->n_deleted; +} + +/* Return the fraction of fixed collisions during all work with given + hash table. */ + +double +htab_collisions (htab) + htab_t htab; +{ + if (htab->searches == 0) + return 0.0; + + return (double) htab->collisions / (double) htab->searches; +} + +#ifndef NDEBUG +void +htab_dump (htab, name, dumpfn) + htab_t htab; + const char *name; + htab_dumpfn dumpfn; +{ + FILE *f = fopen (name, "w"); + size_t i, j; + + if (f == NULL) + abort (); + fprintf (f, "size %zd n_elements %zd n_deleted %zd\n", + htab->size, htab->n_elements, htab->n_deleted); + for (i = 0; i < htab->size; ++i) + { + if (htab->entries [i] == EMPTY_ENTRY + || htab->entries [i] == DELETED_ENTRY) + { + for (j = i + 1; j < htab->size; ++j) + if (htab->entries [j] != htab->entries [i]) + break; + fprintf (f, "%c%zd\n", + htab->entries [i] == EMPTY_ENTRY ? 'E' : 'D', + j - i); + i = j - 1; + } + else + { + fputc ('V', f); + (*dumpfn) (f, htab->entries [i]); + } + } + fclose (f); +} + +void +htab_restore (htab, name, restorefn) + htab_t htab; + const char *name; + htab_restorefn restorefn; +{ + FILE *f = fopen (name, "r"); + size_t size, n_elements, n_deleted, i, j, k; + int c; + + if (f == NULL) + abort (); + if (fscanf (f, "size %zd n_elements %zd n_deleted %zd\n", + &size, &n_elements, &n_deleted) != 3) + abort (); + htab_empty (htab); + free (htab->entries); + htab->entries = (void **) calloc (size, sizeof (void *)); + if (htab->entries == NULL) + abort (); + htab->size = size; + htab->n_elements = n_elements; + htab->n_deleted = n_deleted; + for (i = 0; i < htab->size; ++i) + { + switch ((c = fgetc (f))) + { + case 'E': + case 'D': + if (fscanf (f, "%zd\n", &j) != 1) + abort (); + if (i + j > htab->size) + abort (); + if (c == 'D') + for (k = i; k < i + j; ++k) + htab->entries [k] = DELETED_ENTRY; + i += j - 1; + break; + case 'V': + htab->entries [i] = (*restorefn) (f); + break; + default: + abort (); + } + } + fclose (f); +} +#endif diff --git a/trunk/src/hashtab.h b/trunk/src/hashtab.h new file mode 100644 index 0000000..31e63e0 --- /dev/null +++ b/trunk/src/hashtab.h @@ -0,0 +1,155 @@ +/* An expandable hash tables datatype. + Copyright (C) 1999, 2000 Free Software Foundation, Inc. + Contributed by Vladimir Makarov (vmakarov@cygnus.com). + +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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* This package implements basic hash table functionality. It is possible + to search for an entry, create an entry and destroy an entry. + + Elements in the table are generic pointers. + + The size of the table is not fixed; if the occupancy of the table + grows too high the hash table will be expanded. + + The abstract data implementation is based on generalized Algorithm D + from Knuth's book "The art of computer programming". Hash table is + expanded by creation of new hash table and transferring elements from + the old table to the new table. */ + +#ifndef __HASHTAB_H__ +#define __HASHTAB_H__ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* The type for a hash code. */ +typedef unsigned int hashval_t; + +/* Callback function pointer types. */ + +/* Calculate hash of a table entry. */ +typedef hashval_t (*htab_hash) (const void *); + +/* Compare a table entry with a possible entry. The entry already in + the table always comes first, so the second element can be of a + different type (but in this case htab_find and htab_find_slot + cannot be used; instead the variants that accept a hash value + must be used). */ +typedef int (*htab_eq) (const void *, const void *); + +/* Cleanup function called whenever a live element is removed from + the hash table. */ +typedef void (*htab_del) (void *); + +/* Function called by htab_traverse for each live element. The first + arg is the slot of the element (which can be passed to htab_clear_slot + if desired), the second arg is the auxiliary pointer handed to + htab_traverse. Return 1 to continue scan, 0 to stop. */ +typedef int (*htab_trav) (void **, void *); + +/* Hash tables are of the following type. The structure + (implementation) of this type is not needed for using the hash + tables. All work with hash table should be executed only through + functions mentioned below. */ + +struct htab +{ + /* Pointer to hash function. */ + htab_hash hash_f; + + /* Pointer to comparison function. */ + htab_eq eq_f; + + /* Pointer to cleanup function. */ + htab_del del_f; + + /* Table itself. */ + void **entries; + + /* Current size (in entries) of the hash table */ + size_t size; + + /* Current number of elements including also deleted elements */ + size_t n_elements; + + /* Current number of deleted elements in the table */ + size_t n_deleted; + + /* The following member is used for debugging. Its value is number + of all calls of `htab_find_slot' for the hash table. */ + unsigned int searches; + + /* The following member is used for debugging. Its value is number + of collisions fixed for time of work with the hash table. */ + unsigned int collisions; + + /* This is non-zero if we are allowed to return NULL for function calls + that allocate memory. */ + int return_allocation_failure; +}; + +typedef struct htab *htab_t; + +/* An enum saying whether we insert into the hash table or not. */ +enum insert_option {NO_INSERT, INSERT}; + +/* The prototypes of the package functions. */ + +/* This function is like htab_create, but may return NULL if memory + allocation fails, and also signals that htab_find_slot_with_hash and + htab_find_slot are allowed to return NULL when inserting. */ +extern htab_t htab_try_create (size_t, htab_hash, htab_eq, htab_del); +extern void htab_delete (htab_t); +extern void htab_empty (htab_t); + +extern void *htab_find (htab_t, const void *); +extern void **htab_find_slot (htab_t, const void *, enum insert_option); +extern void *htab_find_with_hash (htab_t, const void *, hashval_t); +extern void **htab_find_slot_with_hash (htab_t, const void *, hashval_t, + enum insert_option); +extern void htab_clear_slot (htab_t, void **); +extern void htab_remove_elt (htab_t, void *); + +extern void htab_traverse (htab_t, htab_trav, void *); + +extern size_t htab_size (htab_t); +extern size_t htab_elements (htab_t); +extern double htab_collisions (htab_t); + +/* A hash function for pointers. */ +extern htab_hash htab_hash_pointer; + +/* An equality function for pointers. */ +extern htab_eq htab_eq_pointer; + +#ifndef NDEBUG + +#include <stdio.h> + +typedef void (*htab_dumpfn) (FILE *, const void *); +typedef void *(*htab_restorefn) (FILE *); + +extern void htab_dump (htab_t, const char *, htab_dumpfn); +extern void htab_restore (htab_t, const char *, htab_restorefn); + +#endif + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* __HASHTAB_H */ diff --git a/trunk/src/layout.c b/trunk/src/layout.c new file mode 100644 index 0000000..9292425 --- /dev/null +++ b/trunk/src/layout.c @@ -0,0 +1,647 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <alloca.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "prelinktab.h" +#include "layout.h" + +#ifndef NDEBUG +# define DEBUG_LAYOUT +#endif + +#ifdef DEBUG_LAYOUT +void +print_ent (struct prelink_entry *e) +{ + printf ("%s: %08x %08x/%08x\n", + e->filename, (int)e->base, (int)e->end, (int)e->layend); +} + +void +print_list (struct prelink_entry *e) +{ + for (; e; e = e->next) + print_ent (e); + printf ("\n"); +} +#endif + +static int +find_arches (void **p, void *info) +{ + struct layout_libs *l = (struct layout_libs *) info; + struct prelink_entry *e = * (struct prelink_entry **) p; + int i; + + if (e->type == ET_DYN || e->type == ET_EXEC + || e->type == ET_CACHE_DYN || e->type == ET_CACHE_EXEC) + { + for (i = 0; i < l->nbinlibs; ++i) + if ((l->binlibs[i]->flags & (PCF_ELF64 | PCF_MACHINE)) + == (e->flags & (PCF_ELF64 | PCF_MACHINE))) + return 1; + + l->binlibs[l->nbinlibs++] = e; + } + + return 1; +} + +static int +find_libs (void **p, void *info) +{ + struct layout_libs *l = (struct layout_libs *) info; + struct prelink_entry *e = * (struct prelink_entry **) p; + + if ((e->flags & (PCF_ELF64 | PCF_MACHINE)) != l->flags) + return 1; + + if (e->type == ET_DYN || e->type == ET_EXEC + || e->type == ET_CACHE_DYN || e->type == ET_CACHE_EXEC) + l->binlibs[l->nbinlibs++] = e; + if (e->type == ET_DYN || e->type == ET_CACHE_DYN) + l->libs[l->nlibs++] = e; + if (force) + e->done = 0; + if (e->type == ET_CACHE_DYN || e->type == ET_CACHE_EXEC) + e->done = 2; + if (e->base & (l->max_page_size - 1)) + { + e->done = 0; + e->end -= e->base; + e->base = 0; + } + + return 1; +} + +static int +refs_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + int i; + + /* Dynamic linkers first. */ + if (! a->ndepends && b->ndepends) + return -1; + if (a->ndepends && ! b->ndepends) + return 1; + /* Most widely used libraries first. */ + if (a->refs > b->refs) + return -1; + if (a->refs < b->refs) + return 1; + /* Largest libraries first. */ + if (a->layend - a->base > b->layend - b->base) + return -1; + if (a->layend - a->base < b->layend - b->base) + return 1; + if (a->refs) + { + i = strcmp (a->soname, b->soname); + if (i) + return i; + } + return strcmp (a->filename, b->filename); +} + +static int +refs_rnd_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + int i, refs; + + /* Dynamic linkers first. */ + if (! a->ndepends && b->ndepends) + return -1; + if (a->ndepends && ! b->ndepends) + return 1; + /* Most widely used libraries first with some randomization. */ + refs = a->refs < b->refs ? a->refs : b->refs; + if (refs < 8) + i = 1; + else if (refs < 32) + i = 2; + else if (refs < 128) + i = 4; + else + i = 8; + if (a->refs > b->refs && a->refs - b->refs >= i) + return -1; + if (a->refs < b->refs && b->refs - a->refs >= i) + return 1; + if (a->u.tmp < b->u.tmp) + return -1; + if (a->u.tmp > b->u.tmp) + return 1; + /* Largest libraries first. */ + if (a->layend - a->base > b->layend - b->base) + return -1; + if (a->layend - a->base < b->layend - b->base) + return 1; + if (a->refs && b->refs) + { + i = strcmp (a->soname, b->soname); + if (i) + return i; + } + return strcmp (a->filename, b->filename); +} + +static int +addr_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + + if (! a->done) + return b->done ? 1 : 0; + else if (! b->done) + return -1; + if (a->base < b->base) + return -1; + else if (a->base > b->base) + return 1; + if (a->layend < b->layend) + return -1; + else if (a->layend > b->layend) + return 1; + return 0; +} + +int deps_cmp (const void *A, const void *B) +{ + struct prelink_entry *a = * (struct prelink_entry **) A; + struct prelink_entry *b = * (struct prelink_entry **) B; + + if (a->base < b->base) + return -1; + if (a->base > b->base) + return 1; + return 0; +} + +int +layout_libs (void) +{ + struct layout_libs l; + int arch, *arches, narches; + struct prelink_entry **plibs, **pbinlibs; + + memset (&l, 0, sizeof (l)); + l.libs = plibs = + (struct prelink_entry **) alloca (prelink_entry_count + * sizeof (struct prelink_entry *)); + l.binlibs = pbinlibs = + (struct prelink_entry **) alloca (prelink_entry_count + * sizeof (struct prelink_entry *)); + htab_traverse (prelink_filename_htab, find_arches, &l); + narches = l.nbinlibs; + arches = (int *) alloca (narches * sizeof (int)); + for (arch = 0; arch < narches; ++arch) + arches[arch] = l.binlibs[arch]->flags & (PCF_ELF64 | PCF_MACHINE); + + for (arch = 0; arch < narches; ++arch) + { + struct PLArch *plarch; + extern struct PLArch __start_pl_arch[], __stop_pl_arch[]; + int i, j, k, m, done, class; + GElf_Addr mmap_start, mmap_base, mmap_end, mmap_fin, max_page_size; + GElf_Addr base, size; + struct prelink_entry *list, *e, *fake, **deps; + struct prelink_entry fakeent; + int fakecnt; + int (*layout_libs_pre) (struct layout_libs *l); + int (*layout_libs_post) (struct layout_libs *l); + + for (plarch = __start_pl_arch; plarch < __stop_pl_arch; plarch++) + if (plarch->class == (arches[arch] & PCF_ELF64 ? ELFCLASS64 : ELFCLASS32) + && plarch->machine == (arches[arch] & PCF_MACHINE)) + break; + + if (plarch == __stop_pl_arch) + error (EXIT_FAILURE, 0, "%d-bit ELF e_machine %04x not supported", + (arches[arch] & PCF_ELF64) ? 64 : 32, arches[arch] & PCF_MACHINE); + + list = NULL; + fake = NULL; + fakecnt = 0; + memset (&l, 0, sizeof (l)); + l.flags = arches[arch]; + l.libs = plibs; + l.binlibs = pbinlibs; + l.max_page_size = plarch->max_page_size; + htab_traverse (prelink_filename_htab, find_libs, &l); + max_page_size = plarch->max_page_size; + + /* Make sure there is some room between libraries. */ + for (i = 0; i < l.nlibs; ++i) + l.libs[i]->layend = (l.libs[i]->end + 8192 + max_page_size - 1) + & ~(max_page_size - 1); + + if (plarch->layout_libs_init) + { + plarch->layout_libs_init (&l); + mmap_base = l.mmap_base; + mmap_end = l.mmap_end; + } + else + { + mmap_base = plarch->mmap_base; + mmap_end = plarch->mmap_end; + } + if (mmap_reg_start != ~(GElf_Addr) 0) + mmap_base = mmap_reg_start; + if (mmap_reg_end != ~(GElf_Addr) 0) + mmap_end = mmap_reg_end; + if (mmap_base >= mmap_end) + error (EXIT_FAILURE, 0, + "--mmap-region-start cannot be bigger than --mmap-region-end"); + class = plarch->class; + /* The code below relies on having a VA slot as big as <mmap_base,mmap_end) + above mmap_end for -R. */ + if (mmap_end + (mmap_end - mmap_base) <= mmap_end) + random_base = 0; + layout_libs_pre = plarch->layout_libs_pre; + layout_libs_post = plarch->layout_libs_post; + + deps = (struct prelink_entry **) + alloca (l.nlibs * sizeof (struct prelink_entry *)); + + /* Now see which already prelinked libraries have to be + re-prelinked to avoid overlaps. */ + for (i = 0; i < l.nbinlibs; ++i) + { + for (j = 0, k = 0; j < l.binlibs[i]->ndepends; ++j) + if (l.binlibs[i]->depends[j]->type == ET_DYN + && l.binlibs[i]->depends[j]->done) + deps[k++] = l.binlibs[i]->depends[j]; + if (k) + { + qsort (deps, k, sizeof (struct prelink_entry *), deps_cmp); + for (j = 1; j < k; ++j) + if (deps[j]->base < deps[j - 1]->end + && (deps[j]->type == ET_DYN + || deps[j - 1]->type == ET_DYN)) + { + if (deps[j - 1]->refs < deps[j]->refs) + --j; + deps[j]->done = 0; + --k; + memmove (deps + j, deps + j + 1, (k - j) * sizeof (*deps)); + if (j > 0) + --j; + } + } + } + + /* If layout_libs_init or the for cycle above cleared + done flags for some libraries, make sure all libraries + that depend on them are re-prelinked as well. */ + for (i = 0; i < l.nlibs; ++i) + if (l.libs[i]->done) + for (j = 0; j < l.libs[i]->ndepends; ++j) + if (l.libs[i]->depends[j]->done == 0) + { + l.libs[i]->done = 0; + break; + } + + /* Put the already prelinked libs into double linked list. */ + qsort (l.libs, l.nlibs, sizeof (struct prelink_entry *), addr_cmp); + for (i = 0; i < l.nlibs; ++i) + if (! l.libs[i]->done || l.libs[i]->layend >= mmap_base) + break; + j = 0; + if (i < l.nlibs && l.libs[i]->done) + { + if (l.libs[i]->base < mmap_base) + random_base = 0; + for (j = i + 1; j < l.nlibs; ++j) + { + if (! l.libs[j]->done || l.libs[j]->base >= mmap_end) + break; + + if (l.libs[j]->base < mmap_base || l.libs[j]->layend > mmap_end) + random_base = 0; + l.libs[j]->prev = l.libs[j - 1]; + l.libs[j - 1]->next = l.libs[j]; + } + list = l.libs[i]; + list->prev = l.libs[j - 1]; + while (j < l.nlibs && l.libs[j]->done) ++j; + } + + mmap_start = mmap_base; + mmap_fin = mmap_end; + done = 1; + if (random_base & 2) + { + mmap_start = seed; + if (mmap_start < mmap_base || mmap_start >= mmap_end) + mmap_start = mmap_base; + + mmap_start = (mmap_start + max_page_size - 1) & ~(max_page_size - 1); + } + else if (random_base) + { + int fd = open ("/dev/urandom", O_RDONLY); + + mmap_start = 0; + if (fd != -1) + { + GElf_Addr x; + + if (read (fd, &x, sizeof (x)) == sizeof (x)) + { + mmap_start = x % (mmap_end - mmap_base); + mmap_start += mmap_base; + } + + close (fd); + } + + if (! mmap_start) + { + mmap_start = ((mmap_end - mmap_base) >> 16) + * (time (NULL) & 0xffff); + mmap_start += mmap_base; + } + + seed = mmap_start; + mmap_start = (mmap_start + max_page_size - 1) & ~(max_page_size - 1); + } + if (random_base) + { + srandom (mmap_start >> 12); + for (i = 0; i < l.nlibs; ++i) + l.libs[i]->u.tmp = random (); + qsort (l.libs, l.nlibs, sizeof (struct prelink_entry *), refs_rnd_cmp); + } + else + qsort (l.libs, l.nlibs, sizeof (struct prelink_entry *), refs_cmp); + + if (verbose && l.nlibs > j) + { + printf ("Laying out %d libraries in virtual address space %0*llx-%0*llx\n", + l.nlibs - j, class == ELFCLASS32 ? 8 : 16, (long long) mmap_base, + class == ELFCLASS32 ? 8 : 16, (long long) mmap_end); + if (mmap_start != mmap_base) + printf ("Random base 0x%0*llx\n", class == ELFCLASS32 ? 8 : 16, + (long long) mmap_start); + } + + if (layout_libs_pre) + { + l.list = list; + l.mmap_base = mmap_base; + l.mmap_start = mmap_start; + l.mmap_end = mmap_end; + layout_libs_pre (&l); + list = l.list; + mmap_base = l.mmap_base; + mmap_start = l.mmap_start; + mmap_fin = l.mmap_fin; + mmap_end = l.mmap_end; + fake = l.fake; + fakecnt = l.fakecnt; + } + + if (mmap_start != mmap_base && list) + { + for (e = list; e != NULL; e = e->next) + { + if (e->base >= mmap_start) + break; + if (e->layend > mmap_start) + mmap_start = (e->layend + max_page_size - 1) + & ~(max_page_size - 1); + e->base += mmap_end - mmap_base; + e->end += mmap_end - mmap_base; + e->layend += mmap_end - mmap_base; + e->done |= 0x80; + } + + if (mmap_start < mmap_end) + { + if (e && e != list) + { + memset (&fakeent, 0, sizeof (fakeent)); + fakeent.u.tmp = -1; + fakeent.base = mmap_end; + fakeent.end = mmap_end; + fakeent.layend = mmap_end; + fake = &fakeent; + fakecnt = 1; + fakeent.prev = list->prev; + fakeent.next = list; + list->prev = fake; + fakeent.prev->next = fake; + list = e; + e->prev->next = NULL; + } + } + else + { + mmap_start = mmap_base; + for (e = list; e != NULL; e = e->next) + if (e->done & 0x80) + { + e->done &= ~0x80; + e->base -= mmap_end - mmap_base; + e->end -= mmap_end - mmap_base; + e->layend -= mmap_end - mmap_base; + } + } + } + + if (mmap_start != mmap_base) + { + done |= 0x80; + mmap_fin = mmap_end + (mmap_start - mmap_base); + } + + for (i = 0; i < l.nlibs; ++i) + l.libs[i]->u.tmp = -1; + m = -1; + + for (i = 0; i < l.nlibs; ++i) + if (! l.libs[i]->done) + { + if (conserve_memory) + { + /* If conserving virtual address space, only consider libraries + which ever appear together with this one. Otherwise consider + all libraries. */ + m = i; + for (j = 0; j < l.nbinlibs; ++j) + { + for (k = 0; k < l.binlibs[j]->ndepends; ++k) + if (l.binlibs[j]->depends[k] == l.libs[i]) + { + for (k = 0; k < l.binlibs[j]->ndepends; ++k) + l.binlibs[j]->depends[k]->u.tmp = m; + break; + } + } + for (j = 0; j < fakecnt; ++j) + fake[j].u.tmp = m; + } + + size = l.libs[i]->layend - l.libs[i]->base; + base = mmap_start; + for (e = list; e; e = e->next) + if (e->u.tmp == m) + { + if (base + size <= e->base) + goto found; + + if (base < e->layend) + base = e->layend; + } + + if (base + size > mmap_fin) + goto not_found; +found: + l.libs[i]->end += base - l.libs[i]->base; + l.libs[i]->base = base; + l.libs[i]->layend = base + size; + if (base >= mmap_end) + l.libs[i]->done = done; + else + l.libs[i]->done = 1; + if (list == NULL) + { + list = l.libs[i]; + list->prev = list; + } + else + { + if (e == NULL) + e = list->prev; + else + e = e->prev; + while (e != list && e->base > base) + e = e->prev; + if (e->base > base) + { + l.libs[i]->next = list; + l.libs[i]->prev = list->prev; + list->prev = l.libs[i]; + list = l.libs[i]; + } + else + { + l.libs[i]->next = e->next; + l.libs[i]->prev = e; + if (e->next) + e->next->prev = l.libs[i]; + else + list->prev = l.libs[i]; + e->next = l.libs[i]; + } + } +#ifdef DEBUG_LAYOUT + { + struct prelink_entry *last = list; + base = 0; + for (e = list; e; last = e, e = e->next) + { + if (e->base < base) + abort (); + base = e->base; + if ((e == list && e->prev->next != NULL) + || (e != list && e->prev->next != e)) + abort (); + } + if (list->prev != last) + abort (); + } +#endif + continue; + +not_found: + error (EXIT_FAILURE, 0, "Could not find virtual address slot for %s", + l.libs[i]->filename); + } + + if (layout_libs_post) + { + l.list = list; + layout_libs_post (&l); + } + + if (done & 0x80) + for (e = list; e != NULL; e = e->next) + if (e->done & 0x80) + { + e->done &= ~0x80; + e->base -= mmap_end - mmap_base; + e->end -= mmap_end - mmap_base; + e->layend -= mmap_base - mmap_base; + } + + if (verbose) + { + if (narches == 1) + printf ("Assigned virtual address space slots for libraries:\n"); + else + printf ("Assigned virtual address space slots for %d-bit %s ELF libraries:\n", + class == ELFCLASS32 ? 32 : 64, plarch->name); + + for (i = 0; i < l.nlibs; ++i) + if (l.libs[i]->done >= 1) + printf ("%-60s %0*llx-%0*llx\n", l.libs[i]->filename, + class == ELFCLASS32 ? 8 : 16, (long long) l.libs[i]->base, + class == ELFCLASS32 ? 8 : 16, (long long) l.libs[i]->end); + } + +#ifdef DEBUG_LAYOUT + for (i = 0; i < l.nbinlibs; ++i) + { + for (j = 0; j < l.binlibs[i]->ndepends; ++j) + if ((l.binlibs[i]->depends[j]->type != ET_DYN + && l.binlibs[i]->depends[j]->type != ET_CACHE_DYN) + || l.binlibs[i]->depends[j]->done == 0) + break; + if (j < l.binlibs[i]->ndepends) + continue; + memcpy (deps, l.binlibs[i]->depends, + l.binlibs[i]->ndepends * sizeof (struct prelink_entry *)); + qsort (deps, l.binlibs[i]->ndepends, sizeof (struct prelink_entry *), + deps_cmp); + for (j = 1; j < l.binlibs[i]->ndepends; ++j) + if (deps[j]->base + < ((deps[j - 1]->end + max_page_size - 1) + & ~(max_page_size - 1)) + && (deps[j]->type == ET_DYN || deps[j - 1]->type == ET_DYN)) + abort (); + } +#endif + } + + return 0; +} diff --git a/trunk/src/layout.h b/trunk/src/layout.h new file mode 100644 index 0000000..f481d22 --- /dev/null +++ b/trunk/src/layout.h @@ -0,0 +1,35 @@ +/* Copyright (C) 2001, 2004, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef LAYOUT_H +#define LAYOUT_H + +struct layout_libs + { + struct prelink_entry **libs; + struct prelink_entry **binlibs; + struct prelink_entry *list; + struct prelink_entry *fake; + GElf_Addr mmap_base, mmap_start, mmap_fin, mmap_end, max_page_size; + void *arch_data; + int flags; + int nlibs; + int nbinlibs; + int fakecnt; + }; + +#endif /* LAYOUT_H */ diff --git a/trunk/src/ld-do-lookup.h b/trunk/src/ld-do-lookup.h new file mode 100644 index 0000000..62a1280 --- /dev/null +++ b/trunk/src/ld-do-lookup.h @@ -0,0 +1,225 @@ +/* Look up a symbol in the loaded objects. + Copyright (C) 1995,96,97,98,99,2000,2001,2002 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#if VERSIONED +# define FCT do_lookup_versioned +# define ARG const struct r_found_version *const version +#else +# define FCT do_lookup +# define ARG int flags +#endif + +/* Inner part of the lookup functions. We return a value > 0 if we + found the symbol, the value 0 if nothing is found and < 0 if + something bad happened. */ +static inline int +FCT (const char *undef_name, unsigned long int hash, const ElfW(Sym) *ref, + struct sym_val *result, struct r_scope_elem *scope, size_t i, ARG, + struct ldlibs_link_map *skip, int type_class, int machine) +{ + struct ldlibs_link_map **list = scope->r_list; + size_t n = scope->r_nlist; + struct ldlibs_link_map *map; + + do + { + const ElfW(Sym) *symtab; + const char *strtab; + const ElfW(Half) *verstab; + Elf_Symndx symidx; + const ElfW(Sym) *sym; +#if ! VERSIONED + int num_versions = 0; + const ElfW(Sym) *versioned_sym = NULL; +#endif + + map = list[i]; + + /* Here come the extra test needed for `_dl_lookup_symbol_skip'. */ + if (skip != NULL && map == skip) + continue; + + /* Don't search the executable when resolving a copy reloc. */ + if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable) + continue; + + /* Print some debugging info if wanted. */ + if (__builtin_expect (GL(dl_debug_mask) & DL_DEBUG_SYMBOLS, 0)) + INTUSE(_dl_debug_printf) ("symbol=%s; lookup in file=%s\n", + undef_name, (map->l_name[0] + ? map->l_name : rtld_progname)); + + symtab = (const void *) D_PTR (map, l_info[DT_SYMTAB]); + strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); + verstab = map->l_versyms; + + /* Search the appropriate hash bucket in this object's symbol table + for a definition for the same symbol name. */ + for (symidx = map->l_buckets[hash % map->l_nbuckets]; + symidx != STN_UNDEF; + symidx = map->l_chain[symidx]) + { + sym = &symtab[symidx]; + + assert (ELF_RTYPE_CLASS_PLT == 1); + if ((sym->st_value == 0 /* No value. */ +#ifdef USE_TLS + && ELFW(ST_TYPE) (sym->st_info) != STT_TLS +#endif + ) + || (type_class & (sym->st_shndx == SHN_UNDEF))) + continue; + + if (ELFW(ST_TYPE) (sym->st_info) > STT_FUNC + && (machine != EM_ARM + || ELFW(ST_TYPE) (sym->st_info) != STT_ARM_TFUNC) +#ifdef USE_TLS + && ELFW(ST_TYPE) (sym->st_info) != STT_TLS +#endif + ) + /* Ignore all but STT_NOTYPE, STT_OBJECT and STT_FUNC + entries (and STT_TLS if TLS is supported) since these + are no code/data definitions. */ + continue; + + if (sym != ref && strcmp (strtab + sym->st_name, undef_name)) + /* Not the symbol we are looking for. */ + continue; + +#if VERSIONED + if (__builtin_expect (verstab == NULL, 0)) + { + /* We need a versioned symbol but haven't found any. If + this is the object which is referenced in the verneed + entry it is a bug in the library since a symbol must + not simply disappear. + + It would also be a bug in the object since it means that + the list of required versions is incomplete and so the + tests in dl-version.c haven't found a problem.*/ + assert (version->filename == NULL + || ! _dl_soname_match_p (version->filename, map)); + + /* Otherwise we accept the symbol. */ + } + else + { + /* We can match the version information or use the + default one if it is not hidden. */ + ElfW(Half) ndx = verstab[symidx] & 0x7fff; + if ((map->l_versions[ndx].hash != version->hash + || strcmp (map->l_versions[ndx].name, version->name)) + && (version->hidden || map->l_versions[ndx].hash + || (verstab[symidx] & 0x8000))) + /* It's not the version we want. */ + continue; + } +#else + /* No specific version is selected. There are two ways we + can got here: + + - a binary which does not include versioning information + is loaded + + - dlsym() instead of dlvsym() is used to get a symbol which + might exist in more than one form + + If the library does not provide symbol version + information there is no problem at at: we simply use the + symbol if it is defined. + + These two lookups need to be handled differently if the + library defines versions. In the case of the old + unversioned application the oldest (default) version + should be used. In case of a dlsym() call the latest and + public interface should be returned. */ + if (verstab != NULL) + { + if ((verstab[symidx] & 0x7fff) + >= ((flags & DL_LOOKUP_RETURN_NEWEST) ? 2 : 3)) + { + /* Don't accept hidden symbols. */ + if ((verstab[symidx] & 0x8000) == 0 && num_versions++ == 0) + /* No version so far. */ + versioned_sym = sym; + + continue; + } + } +#endif + + /* There cannot be another entry for this symbol so stop here. */ + goto found_it; + } + + /* If we have seen exactly one versioned symbol while we are + looking for an unversioned symbol and the version is not the + default version we still accept this symbol since there are + no possible ambiguities. */ +#if VERSIONED + sym = NULL; +#else + sym = num_versions == 1 ? versioned_sym : NULL; +#endif + + if (sym != NULL) + { + found_it: + switch (ELFW(ST_BIND) (sym->st_info)) + { + case STB_WEAK: + /* Weak definition. Use this value if we don't find another. */ + if (__builtin_expect (GL(dl_dynamic_weak), 0)) + { + if (! result->s) + { + result->s = sym; + result->m = map; + } + break; + } + /* FALLTHROUGH */ + case STB_GLOBAL: + /* Global definition. Just what we need. */ + result->s = sym; + result->m = map; + return 1; + default: + /* Local symbols are ignored. */ + break; + } + } + +#if VERSIONED + /* If this current map is the one mentioned in the verneed entry + and we have not found a weak entry, it is a bug. */ + if (symidx == STN_UNDEF && version->filename != NULL + && __builtin_expect (_dl_soname_match_p (version->filename, map), 0)) + return -1; +#endif + } + while (++i < n); + + /* We have not found anything until now. */ + return 0; +} + +#undef FCT +#undef ARG +#undef VERSIONED diff --git a/trunk/src/ld-libs.c b/trunk/src/ld-libs.c new file mode 100644 index 0000000..b169cde --- /dev/null +++ b/trunk/src/ld-libs.c @@ -0,0 +1,1371 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <ctype.h> +#include <errno.h> +#include <error.h> +#include <argp.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "prelinktab.h" +#include "reloc.h" + +#include "ld-libs.h" + +struct search_path +{ + int maxlen, count, allocated; + char **dirs; +}; + +struct search_path ld_dirs, ld_library_search_path; +int host_paths; + +void string_to_path (struct search_path *path, const char *string); + +const char *argp_program_version = "prelink-rtld 1.0 (20061201) Wind River Linux"; + +const char *argp_program_bug_address = "<support@windriver.com>"; + +static char argp_doc[] = "prelink-rtld -- program to simulate the runtime linker"; + +#define OPT_SYSROOT 0x8c +#define OPT_LIBRARY_PATH 0x8e +#define OPT_TARGET_PATHS 0x8f + +static struct argp_option options[] = { + {"library-path", OPT_LIBRARY_PATH, "LIBRARY_PATH", 0, "Set library search path to LIBRARY_PATH" }, + {"root", OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" }, + {"target-paths", OPT_TARGET_PATHS, 0, 0, "Specified paths are based on ROOT_PATH" }, + { 0 } +}; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + switch (key) + { + case OPT_SYSROOT: + sysroot = arg; + break; + case OPT_LIBRARY_PATH: + string_to_path(&ld_library_search_path, arg); + break; + case OPT_TARGET_PATHS: + host_paths = 0; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +#ifndef PT_TLS +#define PT_TLS 7 /* Thread-local storage segment */ +#endif + +#ifndef R_ARM_TLS_DTPMOD32 +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#endif + +/* This function returns the same constants expected by glibc's + symbol lookup routines. This is slightly different from the + equivalent routines in prelink. It should return PLT for any + relocation where an undefined symbol in the application should + be ignored: typically, this means any jump slot or TLS relocations, + but not copy relocations. Don't return the prelinker's + RTYPE_CLASS_TLS. */ +int +reloc_type_class (int type, int machine) +{ + switch (machine) + { + case EM_386: + switch (type) + { + case R_386_COPY: return ELF_RTYPE_CLASS_COPY; + case R_386_JMP_SLOT: + case R_386_TLS_DTPMOD32: + case R_386_TLS_DTPOFF32: + case R_386_TLS_TPOFF32: + case R_386_TLS_TPOFF: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_X86_64: + switch (type) + { + case R_X86_64_COPY: return ELF_RTYPE_CLASS_COPY; + case R_X86_64_JUMP_SLOT: + case R_X86_64_DTPMOD64: + case R_X86_64_DTPOFF64: + case R_X86_64_TPOFF64: + case R_X86_64_DTPOFF32: + case R_X86_64_TPOFF32: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_ARM: + switch (type) + { + case R_ARM_COPY: return ELF_RTYPE_CLASS_COPY; + case R_ARM_JUMP_SLOT: + case R_ARM_TLS_DTPMOD32: + case R_ARM_TLS_DTPOFF32: + case R_ARM_TLS_TPOFF32: + return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_SH: + switch (type) + { + case R_SH_COPY: return ELF_RTYPE_CLASS_COPY; + case R_SH_JMP_SLOT: return ELF_RTYPE_CLASS_PLT; + default: return 0; + } + + case EM_PPC: + switch (type) + { + case R_PPC_COPY: return ELF_RTYPE_CLASS_COPY; + case R_PPC_JMP_SLOT: return ELF_RTYPE_CLASS_PLT; + default: + if (type >= R_PPC_DTPMOD32 && type <= R_PPC_DTPREL32) + return ELF_RTYPE_CLASS_PLT; + return 0; + } + + case EM_PPC64: + switch (type) + { + case R_PPC64_COPY: return ELF_RTYPE_CLASS_COPY; + case R_PPC64_ADDR24: return ELF_RTYPE_CLASS_PLT; + default: + if (type >= R_PPC64_DTPMOD64 && type <= R_PPC64_TPREL16_HIGHESTA) + return ELF_RTYPE_CLASS_PLT; + return 0; + } + + default: + printf ("Unknown architecture!\n"); + exit (1); + return 0; + } +} + +int +is_ldso_soname (const char *soname) +{ + if (! strcmp (soname, "ld-linux.so.2") + || ! strcmp (soname, "ld-linux.so.3") + || ! strcmp (soname, "ld.so.1") + || ! strcmp (soname, "ld-linux-ia64.so.2") + || ! strcmp (soname, "ld-linux-x86-64.so.2") + || ! strcmp (soname, "ld64.so.1")) + return 1; + return 0; +} + + +struct needed_list +{ + struct dso_list *ent; + struct needed_list *next; +}; + +struct dso_list +{ + DSO *dso; + struct ldlibs_link_map *map; + struct dso_list *next, *prev; + struct needed_list *needed, *needed_tail; + const char *name; + struct dso_list *loader; + const char *canon_filename; +}; + +static int dso_open_error = 0; + +static void +free_needed (struct needed_list *p) +{ + struct needed_list *old_p = p; + while (old_p) + { + old_p = p->next; + free (p); + p = old_p; + } +} + +static struct dso_list * +in_dso_list (struct dso_list *dso_list, const char *soname, const char *filename) +{ + while (dso_list != NULL) + { + if (dso_list->dso != NULL) + { + if (strcmp (dso_list->dso->soname, soname) == 0) + return dso_list; + } + + if (strcmp (dso_list->name, soname) == 0) + return dso_list; + + if (filename && dso_list->canon_filename + && strcmp (dso_list->canon_filename, filename) == 0) + return dso_list; + + dso_list = dso_list->next; + } + return NULL; +} + +static int +in_needed_list (struct needed_list *needed_list, const char *soname) +{ + while (needed_list != NULL) + { + if (needed_list->ent->dso != NULL + && strcmp (needed_list->ent->dso->soname, soname) == 0) + return 1; + needed_list = needed_list->next; + } + return 0; +} + + +/****/ + +void +add_dir (struct search_path *path, const char *dir, int dirlen) +{ + if (path->allocated == 0) + { + path->allocated = 5; + path->dirs = malloc (sizeof (char *) * 5); + } + else if (path->count == path->allocated) + { + path->allocated *= 2; + path->dirs = realloc (path->dirs, sizeof (char *) * path->allocated); + } + path->dirs[path->count] = malloc (dirlen + 1); + memcpy (path->dirs[path->count], dir, dirlen); + path->dirs[path->count++][dirlen] = 0; + + if (path->maxlen < dirlen) + path->maxlen = dirlen; +} + +void +free_path (struct search_path *path) +{ + if (path->allocated) + { + int i; + for (i = 0; i < path->count; i++) + free (path->dirs[i]); + free (path->dirs); + } +} + +void +load_ld_so_conf (int use_64bit) +{ + int fd; + FILE *conf; + char buf[1024]; + + memset (&ld_dirs, 0, sizeof (ld_dirs)); + + /* Only use the correct machine, to prevent mismatches if we + have both /lib/ld.so and /lib64/ld.so on x86-64. */ + if (use_64bit) + { + add_dir (&ld_dirs, "/lib64/tls", strlen ("/lib64/tls")); + add_dir (&ld_dirs, "/lib64", strlen ("/lib64")); + add_dir (&ld_dirs, "/usr/lib64/tls", strlen ("/usr/lib64/tls")); + add_dir (&ld_dirs, "/usr/lib64", strlen ("/usr/lib64")); + } + else + { + add_dir (&ld_dirs, "/lib/tls", strlen ("/lib/tls")); + add_dir (&ld_dirs, "/lib", strlen ("/lib")); + add_dir (&ld_dirs, "/usr/lib/tls", strlen ("/usr/lib/tls")); + add_dir (&ld_dirs, "/usr/lib", strlen ("/usr/lib")); + } + + fd = wrap_open ("/etc/ld.so.conf", O_RDONLY); + if (fd == -1) + return; + conf = fdopen (fd, "r"); + while (fgets (buf, 1024, conf) != NULL) + { + int len; + char *p; + + p = strchr (buf, '#'); + if (p) + *p = 0; + len = strlen (buf); + while (isspace (buf[len - 1])) + buf[--len] = 0; + + add_dir (&ld_dirs, buf, len); + } + fclose (conf); +} + +void +string_to_path (struct search_path *path, const char *string) +{ + const char *start, *end, *end_tmp; + + start = string; + while (1) { + end = start; + while (*end && *end != ':' && *end != ';') + end ++; + + /* Eliminate any trailing '/' characters, but be sure to leave a + leading slash if someeone wants / in their RPATH. */ + end_tmp = end; + while (end_tmp > start + 1 && end_tmp[-1] == '/') + end_tmp --; + + add_dir (path, start, end_tmp - start); + + if (*end == 0) + break; + + /* Skip the separator. */ + start = end + 1; + } +} + +char * +find_lib_in_path (struct search_path *path, const char *soname, + int elfclass) +{ + char *ret; + int i; + + ret = malloc (strlen (soname) + 2 + path->maxlen); + + for (i = 0; i < path->count; i++) + { + sprintf (ret, "%s/%s", path->dirs[i], soname); + if (wrap_access (ret, F_OK) == 0) + { + /* Skip 32-bit libraries when looking for 64-bit. */ + DSO *dso = open_dso (ret); + + if (dso == NULL) + continue; + + if (gelf_getclass (dso->elf) != elfclass) + { + close_dso (dso); + continue; + } + + close_dso (dso); + return ret; + } + } + + free (ret); + return NULL; +} + +char * +find_lib_by_soname (const char *soname, struct dso_list *loader, + int elfclass) +{ + char *ret; + + if (strchr (soname, '/')) + return strdup (soname); + + if (loader->dso->info[DT_RUNPATH] == 0) + { + /* Search DT_RPATH all the way up. */ + struct dso_list *loader_p = loader; + while (loader_p) + { + if (loader_p->dso->info[DT_RPATH]) + { + struct search_path r_path; + const char *rpath = get_data (loader_p->dso, + loader_p->dso->info[DT_STRTAB] + + loader_p->dso->info[DT_RPATH], + NULL, NULL); + memset (&r_path, 0, sizeof (r_path)); + string_to_path (&r_path, rpath); + ret = find_lib_in_path (&r_path, soname, elfclass); + free_path (&r_path); + if (ret) + return ret; + } + loader_p = loader_p->loader; + } + } + + ret = find_lib_in_path (&ld_library_search_path, soname, elfclass); + if (ret) + return ret; + + if (loader->dso->info[DT_RUNPATH]) + { + struct search_path r_path; + const char *rpath = get_data (loader->dso, + loader->dso->info[DT_STRTAB] + + loader->dso->info[DT_RUNPATH], + NULL, NULL); + memset (&r_path, 0, sizeof (r_path)); + string_to_path (&r_path, rpath); + ret = find_lib_in_path (&r_path, soname, elfclass); + free_path (&r_path); + if (ret) + return ret; + } + + ret = find_lib_in_path (&ld_dirs, soname, elfclass); + if (ret) + return ret; + + return NULL; +} + +static struct dso_list * +load_dsos (DSO *dso) +{ + struct dso_list *dso_list, *dso_list_tail, *cur_dso_ent, *new_dso_ent; + + dso_list = malloc (sizeof (struct dso_list)); + dso_list->dso = dso; + dso_list->next = NULL; + dso_list->prev = NULL; + dso_list->needed = NULL; + dso_list->name = dso->filename; + dso_list->loader = NULL; + dso_list->canon_filename = wrap_prelink_canonicalize (dso->filename, NULL); + + cur_dso_ent = dso_list_tail = dso_list; + + while (cur_dso_ent != NULL) + { + DSO *cur_dso, *new_dso; + Elf_Scn *scn; + Elf_Data *data; + GElf_Dyn dyn; + + cur_dso = cur_dso_ent->dso; + if (cur_dso == NULL) + { + cur_dso_ent = cur_dso_ent->next; + continue; + } + + scn = cur_dso->scn[cur_dso->dynamic]; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + maxndx = data->d_size / cur_dso->shdr[cur_dso->dynamic].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + { + gelfx_getdyn (cur_dso->elf, data, ndx, &dyn); + if (dyn.d_tag == DT_NULL) + break; + if (dyn.d_tag == DT_NEEDED) + { + char *new_name=NULL, *new_canon_name=NULL; + const char *soname = get_data (cur_dso, + cur_dso->info[DT_STRTAB] + + dyn.d_un.d_val, + NULL, NULL); + new_dso_ent = in_dso_list (dso_list, soname, NULL); + if (new_dso_ent == NULL) + { + new_name = find_lib_by_soname (soname, cur_dso_ent, + gelf_getclass (dso->elf)); + if (new_name == 0 || wrap_access (new_name, R_OK) < 0) + { + dso_open_error ++; + + new_dso_ent = malloc (sizeof (struct dso_list)); + dso_list_tail->next = new_dso_ent; + dso_list_tail->next->prev = dso_list_tail; + dso_list_tail = dso_list_tail->next; + dso_list_tail->next = NULL; + dso_list_tail->dso = NULL; + dso_list_tail->needed = NULL; + dso_list_tail->name = soname; + dso_list_tail->loader = NULL; + dso_list_tail->canon_filename = soname; + + continue; + } + + /* See if the filename we found has already been + opened (possibly under a different SONAME via + some symlink). */ + new_canon_name = wrap_prelink_canonicalize (new_name, NULL); + if (new_canon_name == NULL) + new_canon_name = strdup (new_name); + new_dso_ent = in_dso_list (dso_list, soname, new_canon_name); + } + else if (new_dso_ent->dso == NULL) + continue; + + if (new_dso_ent == NULL) + { + new_dso = open_dso (new_name); + free (new_name); + new_dso_ent = malloc (sizeof (struct dso_list)); + dso_list_tail->next = new_dso_ent; + dso_list_tail->next->prev = dso_list_tail; + dso_list_tail = dso_list_tail->next; + dso_list_tail->next = NULL; + dso_list_tail->dso = new_dso; + dso_list_tail->needed = NULL; + dso_list_tail->loader = cur_dso_ent; + dso_list_tail->canon_filename = new_canon_name; + + if (is_ldso_soname (new_dso->soname)) + dso_list_tail->name = new_dso->filename; + else if (strcmp (new_dso->soname, new_dso->filename) == 0) + /* new_dso->soname might be a full path if the library + had no SONAME. Use the original SONAME instead. */ + dso_list_tail->name = soname; + else + /* Use the new SONAME if possible, in case some library + links to this one using an incorrect SONAME. */ + dso_list_tail->name = new_dso->soname; + } + + if (!cur_dso_ent->needed) + { + cur_dso_ent->needed = malloc (sizeof (struct needed_list)); + cur_dso_ent->needed_tail = cur_dso_ent->needed; + cur_dso_ent->needed_tail->ent = new_dso_ent; + cur_dso_ent->needed_tail->next = NULL; + } + else if (!in_needed_list (cur_dso_ent->needed, soname)) + { + cur_dso_ent->needed_tail->next = malloc (sizeof (struct needed_list)); + cur_dso_ent->needed_tail = cur_dso_ent->needed_tail->next; + cur_dso_ent->needed_tail->ent = new_dso_ent; + cur_dso_ent->needed_tail->next = NULL; + } + + continue; + } + if (dyn.d_tag == DT_FILTER || dyn.d_tag == DT_AUXILIARY) + { + // big fat warning; + } + } + } + cur_dso_ent = cur_dso_ent->next; + } + return dso_list; +} + +static void +get_version_info (DSO *dso, struct ldlibs_link_map *map) +{ + int i; + Elf_Data *data; + int ndx_high; + const char *strtab = map->l_info[DT_STRTAB]; + + /* Fortunately, 32-bit and 64-bit ELF use the same Verneed and Verdef + structures, so this function will work for either. */ + + Elf64_Verneed *verneed; + Elf64_Verdef *verdef; + + map->l_versyms = NULL; + + if (dso->info_set_mask & (1ULL << DT_VERNEED_BIT)) + { + i = addr_to_sec (dso, dso->info_DT_VERNEED); + data = elf_getdata (dso->scn[i], NULL); + verneed = data->d_buf; + } + else + verneed = NULL; + + if (dso->info_set_mask & (1ULL << DT_VERDEF_BIT)) + { + i = addr_to_sec (dso, dso->info_DT_VERDEF); + data = elf_getdata (dso->scn[i], NULL); + verdef = data->d_buf; + } + else + verdef = NULL; + + ndx_high = 0; + if (verneed) + { + Elf64_Verneed *ent = verneed; + Elf64_Vernaux *aux; + while (1) + { + aux = (Elf64_Vernaux *) ((char *) ent + ent->vn_aux); + while (1) + { + if ((unsigned int) (aux->vna_other & 0x7fff) > ndx_high) + ndx_high = aux->vna_other & 0x7fff; + + if (aux->vna_next == 0) + break; + aux = (Elf64_Vernaux *) ((char *) aux + aux->vna_next); + } + + if (ent->vn_next == 0) + break; + ent = (Elf64_Verneed *) ((char *) ent + ent->vn_next); + } + } + + if (verdef) + { + Elf64_Verdef *ent = verdef; + while (1) + { + if ((unsigned int) (ent->vd_ndx & 0x7fff) > ndx_high) + ndx_high = ent->vd_ndx & 0x7fff; + + if (ent->vd_next == 0) + break; + ent = (Elf64_Verdef *) ((char *) ent + ent->vd_next); + } + } + + if (ndx_high) + { + map->l_versions = (struct r_found_version *) + calloc (ndx_high + 1, sizeof (struct r_found_version)); + map->l_nversions = ndx_high + 1; + + i = addr_to_sec (dso, dso->info_DT_VERSYM); + data = elf_getdata (dso->scn[i], NULL); + map->l_versyms = data->d_buf; + + if (verneed) + { + Elf64_Verneed *ent = verneed; + + while (1) + { + Elf64_Vernaux *aux; + aux = (Elf64_Vernaux *) ((char *) ent + ent->vn_aux); + while (1) + { + Elf64_Half ndx = aux->vna_other & 0x7fff; + map->l_versions[ndx].hash = aux->vna_hash; + map->l_versions[ndx].hidden = aux->vna_other & 0x8000; + map->l_versions[ndx].name = &strtab[aux->vna_name]; + map->l_versions[ndx].filename = &strtab[ent->vn_file]; + + if (aux->vna_next == 0) + break; + aux = (Elf64_Vernaux *) ((char *) aux + aux->vna_next); + } + + if (ent->vn_next == 0) + break; + ent = (Elf64_Verneed *) ((char *) ent + ent->vn_next); + } + } + + if (verdef) + { + Elf64_Verdef *ent = verdef; + Elf64_Verdaux *aux; + while (1) + { + aux = (Elf64_Verdaux *) ((char *) ent + ent->vd_aux); + + if ((ent->vd_flags & VER_FLG_BASE) == 0) + { + /* The name of the base version should not be + available for matching a versioned symbol. */ + Elf64_Half ndx = ent->vd_ndx & 0x7fff; + map->l_versions[ndx].hash = ent->vd_hash; + map->l_versions[ndx].name = &strtab[aux->vda_name]; + map->l_versions[ndx].filename = NULL; + } + + if (ent->vd_next == 0) + break; + ent = (Elf64_Verdef *) ((char *) ent + ent->vd_next); + } + } + } +} + +const char *rtld_progname; + +static Elf64_Addr load_addr = 0xdead0000; + +static void +create_ldlibs_link_map (struct dso_list *cur_dso_ent) +{ + struct ldlibs_link_map *map = malloc (sizeof (struct ldlibs_link_map)); + DSO *dso = cur_dso_ent->dso; + int i; + Elf_Data *data; + Elf_Symndx *hash; + + memset (map, 0, sizeof (*map)); + cur_dso_ent->map = map; + + if (is_ldso_soname (cur_dso_ent->dso->soname)) + { + map->l_name = dso->filename; + rtld_progname = dso->filename; + } + else + map->l_name = dso->soname; + map->l_soname = dso->soname; + map->filename = dso->filename; + + if (dso->ehdr.e_type == ET_EXEC) + map->l_type = lt_executable; + else + map->l_type = lt_library; + + /* FIXME: gelfify, endianness issues */ + /* and leaks? */ + i = addr_to_sec (dso, dso->info[DT_SYMTAB]); + data = elf_getdata (dso->scn[i], NULL); + map->l_info[DT_SYMTAB] = data->d_buf; + + i = addr_to_sec (dso, dso->info[DT_STRTAB]); + data = elf_getdata (dso->scn[i], NULL); + map->l_info[DT_STRTAB] = data->d_buf; + + i = addr_to_sec (dso, dso->info[DT_HASH]); + data = elf_getdata (dso->scn[i], NULL); + hash = data->d_buf; + map->l_nbuckets = *hash; + map->l_buckets = hash + 2; + map->l_chain = hash + 2 + map->l_nbuckets; + + get_version_info (dso, map); + + map->l_map_start = load_addr; + load_addr += 0x1000; + + map->sym_base = dso->info[DT_SYMTAB] - dso->base; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_TLS) + { + map->l_tls_blocksize = dso->phdr[i].p_memsz; + map->l_tls_align = dso->phdr[i].p_align; + if (map->l_tls_align == 0) + map->l_tls_firstbyte_offset = 0; + else + map->l_tls_firstbyte_offset = dso->phdr[i].p_vaddr & (map->l_tls_align - 1); + break; + } +} + +struct +{ + void *symptr; + int rtypeclass; +} cache; + +void +do_rel_section (DSO *dso, struct ldlibs_link_map *map, + struct r_scope_elem *scope, + int tag, int section) +{ + Elf_Data *data; + int ndx, maxndx, sym, type; + struct r_found_version *ver; + int rtypeclass; + void *symptr; + const char *name; + Elf64_Word st_name; + + data = elf_getdata (dso->scn[section], NULL); + maxndx = data->d_size / dso->shdr[section].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + if (tag == DT_REL) + { + GElf_Rel rel; + gelfx_getrel (dso->elf, data, ndx, &rel); + sym = GELF_R_SYM (rel.r_info); + type = GELF_R_TYPE (rel.r_info); + } + else + { + GElf_Rela rela; + gelfx_getrela (dso->elf, data, ndx, &rela); + sym = GELF_R_SYM (rela.r_info); + type = GELF_R_TYPE (rela.r_info); + } + if (sym == 0) + continue; + if (map->l_versyms) + { + int vernum = map->l_versyms[sym] & 0x7fff; + ver = &map->l_versions[vernum]; + } + else + ver = NULL; + + rtypeclass = reloc_type_class (type, dso->ehdr.e_machine); + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + Elf32_Sym *sym32 = &((Elf32_Sym *)map->l_info[DT_SYMTAB])[sym]; + + if (ELF32_ST_BIND (sym32->st_info) == STB_LOCAL) + continue; + symptr = sym32; + st_name = sym32->st_name; + } + else + { + Elf64_Sym *sym64 = &((Elf64_Sym *)map->l_info[DT_SYMTAB])[sym]; + + if (ELF64_ST_BIND (sym64->st_info) == STB_LOCAL) + continue; + symptr = sym64; + st_name = sym64->st_name; + } + + if (cache.symptr == symptr && cache.rtypeclass == rtypeclass) + continue; + cache.symptr = symptr; + cache.rtypeclass = rtypeclass; + + name = ((const char *)map->l_info[DT_STRTAB]) + st_name; + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + if (ver && ver->hash) + rtld_lookup_symbol_versioned (name, symptr, scope, ver, rtypeclass, map, + dso->ehdr.e_machine); + else + rtld_lookup_symbol (name, symptr, scope, rtypeclass, map, dso->ehdr.e_machine); + } + else + { + if (ver && ver->hash) + rtld_lookup_symbol_versioned64 (name, symptr, scope, ver, rtypeclass, map, + dso->ehdr.e_machine); + else + rtld_lookup_symbol64 (name, symptr, scope, rtypeclass, map, dso->ehdr.e_machine); + } + } +} + +void +do_relocs (DSO *dso, struct ldlibs_link_map *map, struct r_scope_elem *scope, int tag) +{ + GElf_Addr rel_start, rel_end; + GElf_Addr pltrel_start, pltrel_end; + int first, last; + + /* Load the DT_REL or DT_RELA section. */ + if (dso->info[tag] != 0) + { + rel_start = dso->info[tag]; + rel_end = rel_start + dso->info[tag == DT_REL ? DT_RELSZ : DT_RELASZ]; + first = addr_to_sec (dso, rel_start); + last = addr_to_sec (dso, rel_end - 1); + while (first <= last) + do_rel_section (dso, map, scope, tag, first++); + + /* If the DT_JMPREL relocs are of the same type and not included, + load them too. Assume they overlap completely or not at all, + and are in at most a single section. They also need to be adjacent. */ + if (dso->info[DT_PLTREL] == tag) + { + pltrel_start = dso->info[DT_JMPREL]; + pltrel_end = pltrel_start + dso->info[DT_PLTRELSZ]; + if (pltrel_start < rel_start || pltrel_start >= rel_end) + do_rel_section (dso, map, scope, tag, addr_to_sec (dso, pltrel_start)); + } + } + else if (dso->info[DT_PLTREL] == tag) + do_rel_section (dso, map, scope, tag, addr_to_sec (dso, dso->info[DT_JMPREL])); +} + +void +handle_relocs (DSO *dso, struct dso_list *dso_list) +{ + struct dso_list *ldso, *tail; + + /* do them all last to first. + skip the dynamic linker; then do it last + in glibc this is conditional on the opencount; but every binary + should be linked to libc and thereby have an opencount for ld.so... + besides, that's the only way it would get on our dso list. */ + + tail = dso_list; + while (tail->next) + tail = tail->next; + + ldso = NULL; + while (tail) + { + if (is_ldso_soname (tail->dso->soname)) + ldso = tail; + else + { + /* Load the symbols and relocations. */ + do_relocs (tail->dso, tail->map, dso_list->map->l_local_scope, DT_REL); + do_relocs (tail->dso, tail->map, dso_list->map->l_local_scope, DT_RELA); + } + tail = tail->prev; + } + + if (ldso) + { + do_relocs (ldso->dso, ldso->map, dso_list->map->l_local_scope, DT_REL); + do_relocs (ldso->dso, ldso->map, dso_list->map->l_local_scope, DT_RELA); + } +} + +void +add_to_scope (struct r_scope_elem *scope, struct dso_list *ent) +{ + struct needed_list *n; + int i; + + for (i = 0; i < scope->r_nlist; i++) + if (scope->r_list[i] == ent->map) + return; + + scope->r_list[scope->r_nlist++] = ent->map; + n = ent->needed; + while (n) + { + add_to_scope (scope, n->ent); + n = n->next; + } +} + +void +build_local_scope (struct dso_list *ent, int max) +{ + ent->map->l_local_scope = malloc (sizeof (struct r_scope_elem)); + ent->map->l_local_scope->r_list = malloc (sizeof (struct ldlibs_link_map *) * max); + ent->map->l_local_scope->r_nlist = 0; + add_to_scope (ent->map->l_local_scope, ent); +} + +/* Assign TLS offsets for every loaded library. This code is taken + almost directly from glibc! */ + +#define roundup(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) + +static void +determine_tlsoffsets (int e_machine, struct r_scope_elem *search_list) +{ + uint64_t freetop = 0; + uint64_t freebottom = 0; + uint64_t offset; + uint64_t modid = 1; + int i; + + /* This comes from each architecture's ABI. If TLS_TCB_AT_TP, then + set offset to -1; if TLS_DTV_AT_TP, then set offset to + TLS_TCB_SIZE. */ + switch (e_machine) + { + case EM_X86_64: + offset = -1; + break; + + case EM_386: + offset = -1; + break; + + case EM_SH: + offset = 8; + break; + + case EM_PPC: + offset = 0; + break; + + case EM_PPC64: + offset = 0; + break; + + case EM_ARM: + offset = 8; + break; + + default: + /* Hope there's no TLS! */ + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + + if (map->l_tls_blocksize > 0) + error (1, 0, "TLS encountered on an unsupported architecture"); + } + + return; + } + + /* Loop over the loaded DSOs. We use the symbol search order; this + should be the same as glibc's ordering, which traverses l_next. + It's somewhat important that we use both the same ordering to + assign module IDs and the same algorithm to assign offsets, + because the prelinker will resolve all relocations using these + offsets... and then glibc will recalculate them. Future dynamic + relocations in any loaded modules will use glibc's values. Also + if we take too much space here, glibc won't allocate enough + static TLS area to hold it. */ + + if (offset == (uint64_t) -1) + { + /* We simply start with zero. */ + offset = 0; + + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + uint64_t firstbyte = (-map->l_tls_firstbyte_offset + & (map->l_tls_align - 1)); + uint64_t off; + + if (map->l_tls_blocksize == 0) + continue; + map->l_tls_modid = modid++; + + if (freebottom - freetop >= map->l_tls_blocksize) + { + off = roundup (freetop + map->l_tls_blocksize + - firstbyte, map->l_tls_align) + + firstbyte; + if (off <= freebottom) + { + freetop = off; + + map->l_tls_offset = off; + continue; + } + } + + off = roundup (offset + map->l_tls_blocksize - firstbyte, + map->l_tls_align) + firstbyte; + if (off > offset + map->l_tls_blocksize + + (freebottom - freetop)) + { + freetop = offset; + freebottom = off - map->l_tls_blocksize; + } + offset = off; + + map->l_tls_offset = off; + } + } + else + { + for (i = 0; i < search_list->r_nlist; i++) + { + struct ldlibs_link_map *map = search_list->r_list[i]; + uint64_t firstbyte = (-map->l_tls_firstbyte_offset + & (map->l_tls_align - 1)); + uint64_t off; + + if (map->l_tls_blocksize == 0) + continue; + map->l_tls_modid = modid++; + + if (map->l_tls_blocksize <= freetop - freebottom) + { + off = roundup (freebottom, map->l_tls_align); + if (off - freebottom < firstbyte) + off += map->l_tls_align; + if (off + map->l_tls_blocksize - firstbyte <= freetop) + { + map->l_tls_offset = off - firstbyte; + freebottom = (off + map->l_tls_blocksize + - firstbyte); + continue; + } + } + + off = roundup (offset, map->l_tls_align); + if (off - offset < firstbyte) + off += map->l_tls_align; + + map->l_tls_offset = off - firstbyte; + if (off - firstbyte - offset > freetop - freebottom) + { + freebottom = offset; + freetop = off - firstbyte; + } + + offset = off + map->l_tls_blocksize - firstbyte; + } + } +} + +static struct argp argp = { options, parse_opt, "[FILES]", argp_doc }; + +struct ldlibs_link_map *requested_map; + +static void process_one_dso (DSO *dso, int host_paths); + +int +main(int argc, char **argv) +{ + int remaining; + int multiple = 0; + host_paths = 1; + + sysroot = getenv ("PRELINK_SYSROOT"); +#ifdef DEFAULT_SYSROOT + if (sysroot == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + sysroot = make_relative_prefix (argv[0], BINDIR, DEFAULT_SYSROOT); + } +#endif + + elf_version (EV_CURRENT); + + argp_parse (&argp, argc, argv, 0, &remaining, 0); + + if (sysroot) + sysroot = prelink_canonicalize (sysroot, NULL); + + if (remaining == argc) + error (1, 0, "missing file arguments\nTry `%s: --help' for more information.", argv[0]); + + if ((argc-remaining) >= 2) + multiple = 1; + + while (remaining < argc) + { + DSO *dso = NULL; + int i, fd; + + if (host_paths) + fd = open (argv[remaining], O_RDONLY); + else + fd = wrap_open (argv[remaining], O_RDONLY); + + if (fd >= 0) + dso = fdopen_dso (fd, argv[remaining]); + + if (dso == NULL) + error (1, errno, "Could not open %s", argv[remaining]); + + load_ld_so_conf (gelf_getclass (dso->elf) == ELFCLASS64); + + if (multiple) + printf ("%s:\n", argv[remaining]); + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_INTERP) + break; + + /* If there are no PT_INTERP segments, it is statically linked. */ + if (dso->ehdr.e_type == ET_EXEC && i == dso->ehdr.e_phnum) + printf ("\tnot a dynamic executable\n"); + else + process_one_dso (dso, host_paths); + + remaining++; + } + + return 0; +} + +static void +process_one_dso (DSO *dso, int host_paths) +{ + struct dso_list *dso_list, *cur_dso_ent, *old_dso_ent; + const char *req = getenv ("RTLD_TRACE_PRELINKING"); + int i, flag; + int process_relocs = 0; + + /* Close enough. Really it's if LD_WARN is "" and RTLD_TRACE_PRELINKING. */ + if (getenv ("LD_WARN") == 0 && req != NULL) + process_relocs = 1; + + dso_list = load_dsos (dso); + + cur_dso_ent = dso_list; + i = 0; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + { + create_ldlibs_link_map (cur_dso_ent); + if (req && strcmp (req, cur_dso_ent->dso->filename) == 0) + requested_map = cur_dso_ent->map; + i++; + } + cur_dso_ent = cur_dso_ent->next; + } + dso_list->map->l_local_scope = malloc (sizeof (struct r_scope_elem)); + dso_list->map->l_local_scope->r_list = malloc (sizeof (struct ldlibs_link_map *) * i); + dso_list->map->l_local_scope->r_nlist = i; + cur_dso_ent = dso_list; + i = 0; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + { + dso_list->map->l_local_scope->r_list[i] = cur_dso_ent->map; + if (cur_dso_ent != dso_list) + build_local_scope (cur_dso_ent, dso_list->map->l_local_scope->r_nlist); + + i++; + } + cur_dso_ent = cur_dso_ent->next; + } + + determine_tlsoffsets (dso->ehdr.e_machine, dso_list->map->l_local_scope); + + cur_dso_ent = dso_list; + flag = 0; + /* In ldd mode, do not show the application. Note that we do show it + in list-loaded-objects RTLD_TRACE_PRELINK mode. */ + if (req == NULL && cur_dso_ent) + cur_dso_ent = cur_dso_ent->next; + while (cur_dso_ent) + { + char *filename; + + if (host_paths && sysroot && cur_dso_ent->dso) + { + const char *rooted_filename; + + if (cur_dso_ent->dso->filename[0] == '/') + rooted_filename = cur_dso_ent->dso->filename; + else + rooted_filename = wrap_prelink_canonicalize (cur_dso_ent->dso->filename, NULL); + + /* This covers the odd case where we have a sysroot set, + * but the item isn't in the sysroot! + */ + if (rooted_filename == NULL) + filename = strdup (cur_dso_ent->dso->filename); + else + { + filename = malloc (strlen (rooted_filename) + strlen (sysroot) + 1); + strcpy (filename, sysroot); + strcat (filename, rooted_filename); + } + } + else if (cur_dso_ent->dso) + filename = strdup (cur_dso_ent->dso->filename); + else + filename = NULL; + + /* The difference between the two numbers must be dso->base, + and the first number must be unique. */ + if (cur_dso_ent->dso == NULL) + printf ("\t%s => not found\n", cur_dso_ent->name); + else if (gelf_getclass (cur_dso_ent->dso->elf) == ELFCLASS32) + { + if (process_relocs) + { + printf ("\t%s => %s (0x%08x, 0x%08x)", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start, + (uint32_t) (cur_dso_ent->map->l_map_start - cur_dso_ent->dso->base)); + if (cur_dso_ent->map->l_tls_modid) + printf (" TLS(0x%x, 0x%08x)", + (uint32_t) cur_dso_ent->map->l_tls_modid, + (uint32_t) cur_dso_ent->map->l_tls_offset); + printf ("\n"); + } + else + printf ("\t%s => %s (0x%08x)\n", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start); + } + else + { + if (process_relocs) + { + printf ("\t%s => %s (0x%016" HOST_LONG_LONG_FORMAT + "x, 0x%016" HOST_LONG_LONG_FORMAT "x)", + cur_dso_ent->name, filename, + (unsigned long long) cur_dso_ent->map->l_map_start, + (unsigned long long) (cur_dso_ent->map->l_map_start - cur_dso_ent->dso->base)); + if (cur_dso_ent->map->l_tls_modid) + printf (" TLS(0x%x, 0x%016" HOST_LONG_LONG_FORMAT "x)", + (uint32_t) cur_dso_ent->map->l_tls_modid, + (unsigned long long) cur_dso_ent->map->l_tls_offset); + printf ("\n"); + } + else + printf ("\t%s => %s (0x%08x)\n", + cur_dso_ent->name, filename, + (uint32_t) cur_dso_ent->map->l_map_start); + } + + if (filename) + free (filename); + + cur_dso_ent = cur_dso_ent->next; + flag = 1; + } + + if (dso_open_error) + exit (1); + + if (process_relocs) + handle_relocs (dso_list->dso, dso_list); + + cur_dso_ent = dso_list; + while (cur_dso_ent) + { + if (cur_dso_ent->dso) + close_dso (cur_dso_ent->dso); + old_dso_ent = cur_dso_ent; + cur_dso_ent = cur_dso_ent->next; + if (old_dso_ent->needed) + free_needed (old_dso_ent->needed); + free (old_dso_ent); + } +} diff --git a/trunk/src/ld-libs.h b/trunk/src/ld-libs.h new file mode 100644 index 0000000..48dd555 --- /dev/null +++ b/trunk/src/ld-libs.h @@ -0,0 +1,113 @@ +#ifndef _LD_LIBS_H +#define _LD_LIBS_H + +#if !defined (__linux__) +#define DT_VERSIONTAGNUM 16 +#endif + +struct ldlibs_link_map; + +struct r_scope_elem +{ + struct ldlibs_link_map **r_list; + unsigned int r_nlist; +}; + +struct r_found_version + { + const char *name; + Elf64_Word hash; + + int hidden; + const char *filename; + }; + +/* The size of entries in .hash. Only Alpha and 64-bit S/390 use 64-bit + entries; those are not currently supported. */ +typedef uint32_t Elf_Symndx; + +struct ldlibs_link_map + { + const char *l_name; + struct r_scope_elem *l_local_scope; + enum { lt_executable, lt_library, lt_loaded } l_type; + void *l_info[DT_NUM + DT_VERSIONTAGNUM]; + + /* Symbol hash table. */ + Elf_Symndx l_nbuckets; + const Elf_Symndx *l_buckets, *l_chain; + + unsigned int l_nversions; + struct r_found_version *l_versions; + + /* Pointer to the version information if available. Fortunately, 32-bit + and 64-bit ELF use the same Versym type. */ + Elf64_Versym *l_versyms; + + /* for _dl_soname_match_p */ + const char *l_soname; + + Elf64_Addr l_map_start; + + Elf64_Addr sym_base; + const char *filename; + + /* For TLS. From the object file. */ + uint64_t l_tls_blocksize; + uint64_t l_tls_align; + uint64_t l_tls_firstbyte_offset; + + /* For TLS. Computed. */ + uint64_t l_tls_modid; + uint64_t l_tls_offset; + }; + +#define ELF_RTYPE_CLASS_COPY 2 +#define ELF_RTYPE_CLASS_PLT 1 + +#define GL(X) _ ## X +#define INTUSE(X) X + +#define D_PTR(MAP,MEM) MAP->MEM +#define VERSYMIDX(tag) DT_NUM + DT_VERSIONTAGIDX (tag) + +extern int _dl_debug_mask; +#define DL_DEBUG_SYMBOLS 0 +#define DL_LOOKUP_RETURN_NEWEST 0 +#define _dl_dynamic_weak 0 +extern const char *rtld_progname; +#define _dl_debug_printf printf + + +#define USE_TLS + +#ifndef rtld_lookup_symbol +void rtld_lookup_symbol (const char *name, const Elf32_Sym *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +void rtld_lookup_symbol_versioned (const char *name, const Elf32_Sym *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +#endif + +void rtld_lookup_symbol64 (const char *name, const Elf64_Sym *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); +void rtld_lookup_symbol_versioned64 (const char *name, const Elf64_Sym *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine); + +extern struct ldlibs_link_map *requested_map; + +#define __builtin_expect(a,b) (a) + +#if defined(__MINGW32__) +# define HOST_LONG_LONG_FORMAT "I64" +#else +# define HOST_LONG_LONG_FORMAT "ll" +#endif + +#endif + diff --git a/trunk/src/ld-lookup.c b/trunk/src/ld-lookup.c new file mode 100644 index 0000000..69b6bd1 --- /dev/null +++ b/trunk/src/ld-lookup.c @@ -0,0 +1,214 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include "prelinktab.h" +#include "reloc.h" + +#include "ld-libs.h" + +#ifndef ElfW +/* Default to 32-bit. */ +#define ElfW(x) Elf32_##x +#define ELFW(x) ELF32_##x +#endif + +static int _dl_soname_match_p (const char *name, struct ldlibs_link_map *map); + +struct sym_val +{ + const ElfW(Sym) *s; + struct ldlibs_link_map *m; +}; + +#include "ld-do-lookup.h" +#define VERSIONED 1 +#include "ld-do-lookup.h" +#undef VERSIONED + +static unsigned long +rtld_elf_hash (const char *name) +{ + const unsigned char *str = (const unsigned char *) name; + unsigned long int hash, hi; + hash = *str++; + while (*str != '\0') + { + hash = (hash << 4) + *str++; + hi = hash & 0xf0000000; + hash ^= hi; + hash ^= hi >> 24; + } + return hash & 0xffffffff; +} + +static int +_dl_soname_match_p (const char *name, struct ldlibs_link_map *map) +{ + if (strcmp (name, map->l_name) == 0) + return 1; + if (strcmp (name, map->l_soname) == 0) + return 1; + return 0; +} + +#if 0 +void +rtld_lookup_symbol (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + int ret; + struct sym_val result; + + result.s = NULL; + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result, scope, 0, 0, NULL, rtypeclass); + if (ret > 0) + printf ("name %s /%d\n", name, rtypeclass); +#if 0 + printf ("name %s ret %d", name, ret); + if (result.s) + printf (" result sym 0x%08x (in %s)", result.s->st_value, result.m->l_name); + printf ("\n"); +#endif +} +#endif + +void +rtld_lookup_symbol (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, + int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + rtld_lookup_symbol_versioned (name, sym, scope, NULL, rtypeclass, undef_map, machine); +} + +void +rtld_lookup_symbol_versioned (const char *name, const ElfW(Sym) *sym, + struct r_scope_elem *scope, + struct r_found_version *version, int rtypeclass, + struct ldlibs_link_map *undef_map, int machine) +{ + int ret; + int conflict = 0; + int sym_offset; + struct sym_val result, result2; + unsigned int value1, value2; + + result.s = NULL; + result.m = NULL; + result2.s = NULL; + result2.m = NULL; + if (version) + ret = do_lookup_versioned (name, rtld_elf_hash (name), sym, + &result, scope, 0, version, NULL, rtypeclass, + machine); + else + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result, scope, 0, 0, NULL, rtypeclass, + machine); + + if (result.s == NULL && ELFW(ST_BIND) (sym->st_info) != STB_WEAK) + printf ("undefined symbol: %s\t(%s)\n", name, undef_map->filename); + + if (ret <= 0) + return; + + /* Don't do conflict checking for references in the executable. */ + if (undef_map->l_local_scope != scope) + { + result2.s = NULL; + result2.m = NULL; + if (version) + ret = do_lookup_versioned (name, rtld_elf_hash (name), sym, + &result2, undef_map->l_local_scope, 0, version, + NULL, rtypeclass, machine); + else + ret = do_lookup (name, rtld_elf_hash (name), sym, + &result2, undef_map->l_local_scope, 0, 0, + NULL, rtypeclass, machine); + + if (result2.s != result.s + || result2.m != result.m) + conflict = 1; + } + + if (result.s && ELFW(ST_TYPE) (result.s->st_info) == STT_TLS) + rtypeclass = 4; + + /* Print out information for the requested object, all conflicts, and all TLS. */ + if (!conflict + && rtypeclass != 4 + && requested_map + && requested_map != undef_map) + return; + + /* FIXME: Careful with this if we change the size of symbols when reading in! */ + sym_offset = ((char *)sym) - ((char *)undef_map->l_info[DT_SYMTAB]); + sym_offset += undef_map->sym_base; + + value1 = 0; + if (machine == EM_ARM && result.s + && ELFW(ST_TYPE) (result.s->st_info) == STT_ARM_TFUNC) + value1 = 1; + + value2 = 0; + if (machine == EM_ARM && conflict && result2.s + && ELFW(ST_TYPE) (result2.s->st_info) == STT_ARM_TFUNC) + value2 = 1; + +#if defined(rtld_lookup_symbol) /* 64-bit */ + printf ("%s 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x " + "-> 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x ", + conflict ? "conflict" : "lookup", + (unsigned long long) undef_map->l_map_start, + (unsigned long long) sym_offset, + (unsigned long long) (result.s ? result.m->l_map_start : 0), + (unsigned long long) (result.s ? result.s->st_value | value1 : 0)); + if (conflict) + printf ("x 0x%016" HOST_LONG_LONG_FORMAT "x " + "0x%016" HOST_LONG_LONG_FORMAT "x ", + (unsigned long long) (result2.s ? result2.m->l_map_start : 0), + (unsigned long long) (result2.s ? result2.s->st_value | value2 : 0)); +#else + printf ("%s 0x%08x 0x%08x -> 0x%08x 0x%08x ", + conflict ? "conflict" : "lookup", + (uint32_t) undef_map->l_map_start, + (uint32_t) sym_offset, + (uint32_t) (result.s ? result.m->l_map_start : 0), + (uint32_t) (result.s ? result.s->st_value | value1 : 0)); + if (conflict) + printf ("x 0x%08x 0x%08x ", + (uint32_t) (result2.s ? result2.m->l_map_start : 0), + (uint32_t) (result2.s ? result2.s->st_value | value2 : 0)); +#endif + printf ("/%x %s\n", rtypeclass, name); +} + diff --git a/trunk/src/ld-lookup64.c b/trunk/src/ld-lookup64.c new file mode 100644 index 0000000..7e35334 --- /dev/null +++ b/trunk/src/ld-lookup64.c @@ -0,0 +1,24 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003 + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#define ElfW(x) Elf64_ ## x +#define ELFW(x) ELF64_ ## x + +#define rtld_lookup_symbol rtld_lookup_symbol64 +#define rtld_lookup_symbol_versioned rtld_lookup_symbol_versioned64 + +#include "ld-lookup.c" diff --git a/trunk/src/main.c b/trunk/src/main.c new file mode 100644 index 0000000..631da44 --- /dev/null +++ b/trunk/src/main.c @@ -0,0 +1,486 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <locale.h> +#include <error.h> +#include <argp.h> +#include <stdlib.h> +#include <unistd.h> + +#include "prelink.h" + +#define PRELINK_CONF "/etc/prelink.conf" +#define PRELINK_CACHE "/etc/prelink.cache" + +int all; +int force; +int verbose; +int print_cache; +int reloc_only; +GElf_Addr reloc_base; +int no_update; +int random_base; +int conserve_memory; +int libs_only; +int dry_run; +int dereference; +int one_file_system; +int enable_cxx_optimizations = 1; +int exec_shield; +int undo, verify; +enum verify_method_t verify_method; +int quick; +int compute_checksum; +long long seed; +GElf_Addr mmap_reg_start = ~(GElf_Addr) 0; +GElf_Addr mmap_reg_end = ~(GElf_Addr) 0; +const char *dynamic_linker; +const char *ld_library_path; +const char *prelink_conf = PRELINK_CONF; +const char *prelink_cache = PRELINK_CACHE; +const char *undo_output; +int noreexecinit; +time_t initctime; + +const char *argp_program_version = "prelink 1.0 (20061201) Wind River Linux"; + +const char *argp_program_bug_address = "<support@windriver.com>"; + +static char argp_doc[] = "prelink -- program to relocate and prelink ELF shared libraries and programs"; + +#define OPT_DYNAMIC_LINKER 0x80 +#define OPT_LD_LIBRARY_PATH 0x81 +#define OPT_LIBS_ONLY 0x82 +#define OPT_CXX_DISABLE 0x83 +#define OPT_MMAP_REG_START 0x84 +#define OPT_MMAP_REG_END 0x85 +#define OPT_EXEC_SHIELD 0x86 +#define OPT_NO_EXEC_SHIELD 0x87 +#define OPT_SEED 0x88 +#define OPT_MD5 0x89 +#define OPT_SHA 0x8a +#define OPT_COMPUTE_CHECKSUM 0x8b +#define OPT_SYSROOT 0x8c +#define OPT_RTLD 0x8d + +static struct argp_option options[] = { + {"all", 'a', 0, 0, "Prelink all binaries" }, + {"black-list", 'b', "PATH", 0, "Blacklist path" }, + {"cache-file", 'C', "CACHE", 0, "Use CACHE as cache file" }, + {"config-file", 'c', "CONF", 0, "Use CONF as configuration file" }, + {"force", 'f', 0, 0, "Force prelinking" }, + {"dereference", 'h', 0, 0, "Follow symlinks when processing directory trees from command line" }, + {"one-file-system", 'l', 0, 0, "Stay in local file system when processing directories from command line" }, + {"conserve-memory", 'm', 0, 0, "Allow libraries to overlap as long as they never appear in the same program" }, + {"no-update-cache", 'N', 0, 0, "Don't update prelink cache" }, + {"dry-run", 'n', 0, 0, "Don't actually prelink anything" }, + {"undo-output", 'o', "FILE", 0, "Undo output file" }, + {"print-cache", 'p', 0, 0, "Print prelink cache" }, + {"quick", 'q', 0, 0, "Quick scan" }, + {"random", 'R', 0, 0, "Choose random base for libraries" }, + {"reloc-only", 'r', "BASE_ADDRESS", 0, "Relocate library to given address, don't prelink" }, + {"root", OPT_SYSROOT, "ROOT_PATH", 0, "Prefix all paths with ROOT_PATH" }, + {"undo", 'u', 0, 0, "Undo prelink" }, + {"verbose", 'v', 0, 0, "Produce verbose output" }, + {"verify", 'y', 0, 0, "Verify file consistency by undoing and redoing prelink and printing original to standard output" }, + {"md5", OPT_MD5, 0, 0, "For verify print MD5 sum of original to standard output instead of content" }, + {"sha", OPT_SHA, 0, 0, "For verify print SHA sum of original to standard output instead of content" }, + {"dynamic-linker", OPT_DYNAMIC_LINKER, "DYNAMIC_LINKER", + 0, "Special dynamic linker path" }, + {"exec-shield", OPT_EXEC_SHIELD, 0, 0, "Lay out libraries for exec-shield on IA-32" }, + {"no-exec-shield", OPT_NO_EXEC_SHIELD, 0, 0, "Don't lay out libraries for exec-shield on IA-32" }, + {"ld-library-path", OPT_LD_LIBRARY_PATH, "PATHLIST", + 0, "What LD_LIBRARY_PATH should be used" }, + {"libs-only", OPT_LIBS_ONLY, 0, 0, "Prelink only libraries, no binaries" }, + {"disable-c++-optimizations", OPT_CXX_DISABLE, 0, OPTION_HIDDEN, "" }, + {"mmap-region-start", OPT_MMAP_REG_START, "BASE_ADDRESS", OPTION_HIDDEN, "" }, + {"mmap-region-end", OPT_MMAP_REG_END, "BASE_ADDRESS", OPTION_HIDDEN, "" }, + {"seed", OPT_SEED, "SEED", OPTION_HIDDEN, "" }, + {"compute-checksum", OPT_COMPUTE_CHECKSUM, 0, OPTION_HIDDEN, "" }, + {"rtld", OPT_RTLD, "RTLD", OPTION_HIDDEN, "" }, + {"init", 'i', 0, 0, "Do not re-execute init" }, + { 0 } +}; + +static error_t +parse_opt (int key, char *arg, struct argp_state *state) +{ + char *endarg; + + switch (key) + { + case 'a': + all = 1; + break; + case 'b': + if (add_to_blacklist (arg, dereference, one_file_system)) + exit (EXIT_FAILURE); + break; + case 'f': + force = 1; + break; + case 'p': + print_cache = 1; + break; + case 'q': + quick = 1; + break; + case 'v': + ++verbose; + break; + case 'R': + random_base |= 1; + break; + case OPT_SEED: + random_base |= 2; + seed = strtoull (arg, &endarg, 0); + if (endarg != strchr (arg, '\0')) + error (EXIT_FAILURE, 0, "--seed option requires numberic argument"); + break; + case 'r': + reloc_only = 1; + reloc_base = strtoull (arg, &endarg, 0); + if (endarg != strchr (arg, '\0')) + error (EXIT_FAILURE, 0, "-r option requires numberic argument"); + break; + case 'h': + dereference = 1; + break; + case 'l': + one_file_system = 1; + break; + case 'm': + conserve_memory = 1; + break; + case 'N': + no_update = 1; + break; + case 'n': + dry_run = 1; + break; + case 'C': + prelink_cache = arg; + break; + case 'c': + prelink_conf = arg; + break; + case 'u': + undo = 1; + break; + case 'y': + verify = 1; + break; + case 'o': + undo_output = arg; + break; + case OPT_DYNAMIC_LINKER: + dynamic_linker = arg; + break; + case OPT_LD_LIBRARY_PATH: + ld_library_path = arg; + break; + case OPT_LIBS_ONLY: + libs_only = 1; + break; + case OPT_MD5: + verify_method = VERIFY_MD5; + break; + case OPT_SHA: + verify_method = VERIFY_SHA; + break; + case OPT_CXX_DISABLE: + enable_cxx_optimizations = 0; + break; + case OPT_MMAP_REG_START: + mmap_reg_start = strtoull (arg, &endarg, 0); + if (endarg != strchr (arg, '\0')) + error (EXIT_FAILURE, 0, "--mmap-region-start option requires numberic argument"); + break; + case OPT_MMAP_REG_END: + mmap_reg_end = strtoull (arg, &endarg, 0); + if (endarg != strchr (arg, '\0')) + error (EXIT_FAILURE, 0, "--mmap-region-end option requires numberic argument"); + break; + case OPT_EXEC_SHIELD: + exec_shield = 1; + break; + case OPT_NO_EXEC_SHIELD: + exec_shield = 0; + break; + case OPT_COMPUTE_CHECKSUM: + compute_checksum = 1; + break; + case OPT_SYSROOT: + sysroot = arg; + break; + case OPT_RTLD: + prelink_rtld = arg; + break; + case 'i': + noreexecinit=1; + break; + default: + return ARGP_ERR_UNKNOWN; + } + return 0; +} + +time_t get_ctime(const char *file) { + struct stat st; + if(stat(file,&st) == 0) + return st.st_ctime; + return 0; +} + +void checkinit() { + if(initctime != get_ctime("/sbin/init")) { + printf("Executing /sbin/init U\n"); + system("/sbin/init U"); + } +} + +static struct argp argp = { options, parse_opt, "[FILES]", argp_doc }; + +const char *prelink_rtld = NULL; + +int +main (int argc, char *argv[]) +{ + int remaining, failures = 0; + + setlocale (LC_ALL, ""); + + exec_shield = 2; + + prelink_init_cache (); + + elf_version (EV_CURRENT); + + argp_parse (&argp, argc, argv, 0, &remaining, 0); + + if(!noreexecinit) { + initctime = get_ctime("/sbin/init"); + atexit(checkinit); + } + + if (ld_library_path == NULL) + ld_library_path = getenv ("LD_LIBRARY_PATH"); + + if (all && reloc_only) + error (EXIT_FAILURE, 0, "--all and --reloc-only options are incompatible"); + if ((undo || verify) && reloc_only) + error (EXIT_FAILURE, 0, "--undo and --reloc-only options are incompatible"); + if (verify && (undo || all)) + error (EXIT_FAILURE, 0, "--verify and either --undo or --all options are incompatible"); + if (dry_run && verify) + error (EXIT_FAILURE, 0, "--dry-run and --verify options are incompatible"); + if ((undo || verify) && quick) + error (EXIT_FAILURE, 0, "--undo and --quick options are incompatible"); + + /* Set the default for exec_shield. */ + if (exec_shield == 2) + { + if (sysroot == NULL && ! access ("/proc/sys/kernel/exec-shield", F_OK)) + exec_shield = 1; + else + exec_shield = 0; + } + +#ifdef DEFAULT_SYSROOT + if (sysroot == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + sysroot = make_relative_prefix (argv[0], BINDIR, DEFAULT_SYSROOT); + } +#endif + + if (sysroot) + { + sysroot = prelink_canonicalize (sysroot, NULL); + if (sysroot == NULL) + error (EXIT_FAILURE, 0, "Could not canonicalize --root argument"); + asprintf ((char **) &prelink_conf, "%s%s", sysroot, prelink_conf); + } + + if (prelink_rtld == NULL) + { + extern char *make_relative_prefix (const char *, const char *, const char *); + const char *path = make_relative_prefix (argv[0], BINDIR, BINDIR); + if (strchr (argv[0], '/')) + asprintf ((char **) &prelink_rtld, "%s-rtld", argv[0]); + else + asprintf ((char **) &prelink_rtld, "%s/%s-rtld", path, argv[0]); + } + else if (prelink_rtld[0] == 0) + prelink_rtld = NULL; + + if (print_cache) + { + prelink_load_cache (); + prelink_print_cache (); + return 0; + } + + if (remaining == argc && ! all) + error (EXIT_FAILURE, 0, "no files given and --all not used"); + + if (undo_output && (!undo || all)) + error (EXIT_FAILURE, 0, "-o can be only specified together with -u and without -a"); + + if (undo_output && remaining + 1 != argc) + error (EXIT_FAILURE, 0, "-o can only be used when undoing a single object"); + + if (compute_checksum) + { + while (remaining < argc) + { + DSO *dso = open_dso (argv[remaining++]); + + if (dso == NULL || reopen_dso (dso, NULL, NULL) + || prelink_set_checksum (dso)) + error (0, 0, "could not recompute checksum of %s", dso->filename); + close_dso (dso); + error (0, 0, "%08x %s\n", (unsigned int) dso->info_DT_CHECKSUM, dso->filename); + } + exit (0); + } + + if (verify) + { + if (remaining + 1 != argc) + error (EXIT_FAILURE, 0, "only one library or binary can be verified in a single command"); + return prelink_verify (argv[remaining]); + } + + if (reloc_only || (undo && ! all)) + { + while (remaining < argc) + { + DSO *dso = open_dso (argv[remaining++]); + int ret; + + if (dso == NULL) + { + ++failures; + continue; + } + + if (dso->ehdr.e_type != ET_DYN + && (reloc_only || dso->ehdr.e_type != ET_EXEC)) + { + ++failures; + error (0, 0, "%s is not a shared library", dso->filename); + continue; + } + + if (undo) + ret = prelink_undo (dso); + else + ret = relocate_dso (dso, reloc_base); + + if (ret) + { + ++failures; + close_dso (dso); + continue; + } + + if (dynamic_info_is_set (dso, DT_CHECKSUM_BIT) + && dso_is_rdwr (dso) + && prelink_set_checksum (dso)) + { + ++failures; + close_dso (dso); + continue; + } + + if (dry_run) + { + close_dso (dso); + continue; + } + + if (reloc_only) + dso->permissive = 1; + else if (undo_output) + { + const char *output = strdup (undo_output); + const char *orig_filename; + if (!output) + { + ++failures; + close_dso (dso); + continue; + } + if (dso->filename != dso->soname) + orig_filename = dso->filename; + else + orig_filename = strdup (dso->filename); + if (!orig_filename) + { + ++failures; + close_dso (dso); + continue; + } + dso->filename = output; + if (update_dso (dso, orig_filename)) + ++failures; + free ((char *) orig_filename); + continue; + } + + if (update_dso (dso, NULL)) + ++failures; + } + + return failures; + } + + if (blacklist_from_config (prelink_conf)) + return EXIT_FAILURE; + + if (quick) + prelink_load_cache (); + + if (gather_config (prelink_conf)) + return EXIT_FAILURE; + + while (remaining < argc) + if (gather_object (argv[remaining++], dereference, one_file_system)) + return EXIT_FAILURE; + + if (gather_check_libs ()) + return EXIT_FAILURE; + + if (undo) + return undo_all (); + + if (! all && ! quick) + prelink_load_cache (); + + layout_libs (); + prelink_all (); + + if (! no_update && ! dry_run) + prelink_save_cache (all); + return 0; +} diff --git a/trunk/src/makecrc.c b/trunk/src/makecrc.c new file mode 100644 index 0000000..db52013 --- /dev/null +++ b/trunk/src/makecrc.c @@ -0,0 +1,63 @@ +/* Not copyrighted 1990 Mark Adler */ + +#ifndef lint +static char rcsid[] = "$Id: makecrc.c,v 0.6 1993/05/28 07:42:59 jloup Exp $"; +#endif + +#include <stdio.h> + +main() +/* + Generate a table for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The table is simply the CRC of all possible eight bit values. This is all + the information needed to generate CRC's on data a byte at a time for all + combinations of CRC register values and incoming bytes. The table is + written to stdout as 256 long hexadecimal values in C language format. +*/ +{ + unsigned long c; /* crc shift register */ + unsigned long e; /* polynomial exclusive-or pattern */ + int i; /* counter for all possible eight bit values */ + int k; /* byte being shifted into crc apparatus */ + + /* terms of polynomial defining this crc (except x^32): */ + static int p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* Make exclusive-or pattern from polynomial (0xedb88320) */ + e = 0; + for (i = 0; i < sizeof(p)/sizeof(int); i++) + e |= 1L << (31 - p[i]); + + /* Compute and print table of CRC's, five per line */ + printf(" 0x00000000"); + for (i = 1; i < 256; i++) + { + c = i; + /* The idea to initialize the register with the byte instead of + * zero was stolen from Haruhiko Okumura's ar002 + */ + for (k = 8; k; k--) + c = c & 1 ? (c >> 1) ^ e : c >> 1; + printf(i % 5 ? ", 0x%08lx" : ",\n 0x%08lx", c); + } + putchar('\n'); + return 0; +} diff --git a/trunk/src/md5.c b/trunk/src/md5.c new file mode 100644 index 0000000..0d2fdef --- /dev/null +++ b/trunk/src/md5.c @@ -0,0 +1,362 @@ +/* md5.c - Functions to compute MD5 message digest of files or memory blocks + according to the definition of MD5 in RFC 1321 from April 1992. + Copyright (C) 1995, 1996, 2001, 2003 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +/* Written by Ulrich Drepper <drepper@gnu.ai.mit.edu>, 1995. */ + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <endian.h> +#include <byteswap.h> +#include "md5.h" + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SWAP(n) bswap_32 (n) +#else +# define SWAP(n) (n) +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +void +md5_init_ctx (ctx) + struct md5_ctx *ctx; +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 16 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_read_ctx (ctx, resbuf) + const struct md5_ctx *ctx; + void *resbuf; +{ + ((md5_uint32 *) resbuf)[0] = SWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = SWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = SWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = SWAP (ctx->D); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +md5_finish_ctx (ctx, resbuf) + struct md5_ctx *ctx; + void *resbuf; +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad] = SWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = SWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + md5_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return md5_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +md5_buffer (buffer, len, resblock) + const char *buffer; + size_t len; + void *resblock; +{ + struct md5_ctx ctx; + + /* Initialize the computation context. */ + md5_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + md5_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return md5_finish_ctx (&ctx, resblock); +} + + +void +md5_process_bytes (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + md5_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + md5_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else + { + md5_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + md5_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + + +/* These are the four functions used in the four steps of the MD5 algorithm + and defined in the RFC 1321. The first function is a little bit optimized + (as found in Colin Plumbs public domain implementation). */ +/* #define FF(b, c, d) ((b & c) | (~b & d)) */ +#define FF(b, c, d) (d ^ (b & (c ^ d))) +#define FG(b, c, d) FF (d, b, c) +#define FH(b, c, d) (b ^ c ^ d) +#define FI(b, c, d) (c ^ (b | ~d)) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. */ + +void +md5_process_block (buffer, len, ctx) + const void *buffer; + size_t len; + struct md5_ctx *ctx; +{ + md5_uint32 correct_words[16]; + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 A = ctx->A; + md5_uint32 B = ctx->B; + md5_uint32 C = ctx->C; + md5_uint32 D = ctx->D; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + + /* Process all bytes in the buffer with 64 bytes in each round of + the loop. */ + while (words < endp) + { + md5_uint32 *cwp = correct_words; + md5_uint32 A_save = A; + md5_uint32 B_save = B; + md5_uint32 C_save = C; + md5_uint32 D_save = D; + + /* First round: using the given function, the context and a constant + the next context is computed. Because the algorithms processing + unit is a 32-bit word and it is determined to work on words in + little endian byte order we perhaps have to change the byte order + before the computation. To reduce the work for the next steps + we store the swapped words in the array CORRECT_WORDS. */ + +#define OP(a, b, c, d, s, T) \ + do \ + { \ + a += FF (b, c, d) + (*cwp++ = SWAP (*words)) + T; \ + ++words; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Before we start, one word to the strange constants. + They are defined in RFC 1321 as + + T[i] = (int) (4294967296.0 * fabs (sin (i))), i=1..64, or + perl -e 'foreach(1..64){printf "0x%08x\n", int (4294967296 * abs (sin $_))}' + */ + + /* Round 1. */ + OP (A, B, C, D, 7, 0xd76aa478); + OP (D, A, B, C, 12, 0xe8c7b756); + OP (C, D, A, B, 17, 0x242070db); + OP (B, C, D, A, 22, 0xc1bdceee); + OP (A, B, C, D, 7, 0xf57c0faf); + OP (D, A, B, C, 12, 0x4787c62a); + OP (C, D, A, B, 17, 0xa8304613); + OP (B, C, D, A, 22, 0xfd469501); + OP (A, B, C, D, 7, 0x698098d8); + OP (D, A, B, C, 12, 0x8b44f7af); + OP (C, D, A, B, 17, 0xffff5bb1); + OP (B, C, D, A, 22, 0x895cd7be); + OP (A, B, C, D, 7, 0x6b901122); + OP (D, A, B, C, 12, 0xfd987193); + OP (C, D, A, B, 17, 0xa679438e); + OP (B, C, D, A, 22, 0x49b40821); + + /* For the second to fourth round we have the possibly swapped words + in CORRECT_WORDS. Redefine the macro to take an additional first + argument specifying the function to use. */ +#undef OP +#define OP(f, a, b, c, d, k, s, T) \ + do \ + { \ + a += f (b, c, d) + correct_words[k] + T; \ + a = rol (a, s); \ + a += b; \ + } \ + while (0) + + /* Round 2. */ + OP (FG, A, B, C, D, 1, 5, 0xf61e2562); + OP (FG, D, A, B, C, 6, 9, 0xc040b340); + OP (FG, C, D, A, B, 11, 14, 0x265e5a51); + OP (FG, B, C, D, A, 0, 20, 0xe9b6c7aa); + OP (FG, A, B, C, D, 5, 5, 0xd62f105d); + OP (FG, D, A, B, C, 10, 9, 0x02441453); + OP (FG, C, D, A, B, 15, 14, 0xd8a1e681); + OP (FG, B, C, D, A, 4, 20, 0xe7d3fbc8); + OP (FG, A, B, C, D, 9, 5, 0x21e1cde6); + OP (FG, D, A, B, C, 14, 9, 0xc33707d6); + OP (FG, C, D, A, B, 3, 14, 0xf4d50d87); + OP (FG, B, C, D, A, 8, 20, 0x455a14ed); + OP (FG, A, B, C, D, 13, 5, 0xa9e3e905); + OP (FG, D, A, B, C, 2, 9, 0xfcefa3f8); + OP (FG, C, D, A, B, 7, 14, 0x676f02d9); + OP (FG, B, C, D, A, 12, 20, 0x8d2a4c8a); + + /* Round 3. */ + OP (FH, A, B, C, D, 5, 4, 0xfffa3942); + OP (FH, D, A, B, C, 8, 11, 0x8771f681); + OP (FH, C, D, A, B, 11, 16, 0x6d9d6122); + OP (FH, B, C, D, A, 14, 23, 0xfde5380c); + OP (FH, A, B, C, D, 1, 4, 0xa4beea44); + OP (FH, D, A, B, C, 4, 11, 0x4bdecfa9); + OP (FH, C, D, A, B, 7, 16, 0xf6bb4b60); + OP (FH, B, C, D, A, 10, 23, 0xbebfbc70); + OP (FH, A, B, C, D, 13, 4, 0x289b7ec6); + OP (FH, D, A, B, C, 0, 11, 0xeaa127fa); + OP (FH, C, D, A, B, 3, 16, 0xd4ef3085); + OP (FH, B, C, D, A, 6, 23, 0x04881d05); + OP (FH, A, B, C, D, 9, 4, 0xd9d4d039); + OP (FH, D, A, B, C, 12, 11, 0xe6db99e5); + OP (FH, C, D, A, B, 15, 16, 0x1fa27cf8); + OP (FH, B, C, D, A, 2, 23, 0xc4ac5665); + + /* Round 4. */ + OP (FI, A, B, C, D, 0, 6, 0xf4292244); + OP (FI, D, A, B, C, 7, 10, 0x432aff97); + OP (FI, C, D, A, B, 14, 15, 0xab9423a7); + OP (FI, B, C, D, A, 5, 21, 0xfc93a039); + OP (FI, A, B, C, D, 12, 6, 0x655b59c3); + OP (FI, D, A, B, C, 3, 10, 0x8f0ccc92); + OP (FI, C, D, A, B, 10, 15, 0xffeff47d); + OP (FI, B, C, D, A, 1, 21, 0x85845dd1); + OP (FI, A, B, C, D, 8, 6, 0x6fa87e4f); + OP (FI, D, A, B, C, 15, 10, 0xfe2ce6e0); + OP (FI, C, D, A, B, 6, 15, 0xa3014314); + OP (FI, B, C, D, A, 13, 21, 0x4e0811a1); + OP (FI, A, B, C, D, 4, 6, 0xf7537e82); + OP (FI, D, A, B, C, 11, 10, 0xbd3af235); + OP (FI, C, D, A, B, 2, 15, 0x2ad7d2bb); + OP (FI, B, C, D, A, 9, 21, 0xeb86d391); + + /* Add the starting values of the context. */ + A += A_save; + B += B_save; + C += C_save; + D += D_save; + } + + /* Put checksum in context given as argument. */ + ctx->A = A; + ctx->B = B; + ctx->C = C; + ctx->D = D; +} diff --git a/trunk/src/md5.h b/trunk/src/md5.h new file mode 100644 index 0000000..55f6195 --- /dev/null +++ b/trunk/src/md5.h @@ -0,0 +1,105 @@ +/* md5.h - Declaration of functions and data types used for MD5 sum + computing library functions. + Copyright (C) 1995, 1996, 1999 Free Software Foundation, Inc. + NOTE: The canonical source of this file is maintained with the GNU C + Library. Bugs can be reported to bug-glibc@prep.ai.mit.edu. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef _MD5_H +#define _MD5_H 1 + +#include <limits.h> +#include <stdint.h> +typedef uint32_t md5_uint32; +typedef uintptr_t md5_uintptr; + +/* Structure to save state of computation between the single steps. */ +struct md5_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; +}; + +/* + * The following three functions are build up the low level used in + * the function `md5_buffer'. + */ + +/* Initialize structure containing state of computation. + (RFC 1321, 3.3: Step 3) */ +extern void md5_init_ctx (struct md5_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void md5_process_block __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void md5_process_bytes __P ((const void *buffer, size_t len, + struct md5_ctx *ctx)); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF be correctly + aligned for a 32 bits value. */ +extern void *md5_finish_ctx (struct md5_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *md5_read_ctx (const struct md5_ctx *ctx, void *resbuf); + + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *md5_buffer (const char *buffer, size_t len, void *resblock); + +/* The following is from gnupg-1.0.2's cipher/bithelp.h. */ +/* Rotate a 32 bit integer by n bytes */ +#if defined __GNUC__ && defined __i386__ +static inline md5_uint32 +rol(md5_uint32 x, int n) +{ + __asm__("roll %%cl,%0" + :"=r" (x) + :"0" (x),"c" (n)); + return x; +} +#else +# define rol(x,n) ( ((x) << (n)) | ((x) >> (32-(n))) ) +#endif + +#endif diff --git a/trunk/src/mdebug.c b/trunk/src/mdebug.c new file mode 100644 index 0000000..4c22d2f --- /dev/null +++ b/trunk/src/mdebug.c @@ -0,0 +1,692 @@ +/* Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <byteswap.h> +#include <endian.h> +#include <error.h> +#include <stddef.h> + +#include "prelink.h" + +#define F8(x) unsigned char x[1]; +#define F16(x) unsigned char x[2]; +#define F24(x) unsigned char x[3]; +#define F32(x) unsigned char x[4]; +#define F64(x) unsigned char x[8]; + +typedef struct +{ + F16(magic) + F16(vstamp) + F32(ilineMax) + F32(cbLine) + F32(cbLineOffset) + F32(idnMax) + F32(cbDnOffset) + F32(ipdMax) + F32(cbPdOffset) + F32(isymMax) + F32(cbSymOffset) + F32(ioptMax) + F32(cbOptOffset) + F32(iauxMax) + F32(cbAuxOffset) + F32(issMax) + F32(cbSsOffset) + F32(issExtMax) + F32(cbSsExtOffset) + F32(ifdMax) + F32(cbFdOffset) + F32(crfd) + F32(cbRfdOffset) + F32(iextMax) + F32(cbExtOffset) +} mdebug_hdr_32; + +typedef struct +{ + F16(magic) + F16(vstamp) + F32(ilineMax) + F32(idnMax) + F32(ipdMax) + F32(isymMax) + F32(ioptMax) + F32(iauxMax) + F32(issMax) + F32(issExtMax) + F32(ifdMax) + F32(crfd) + F32(iextMax) + F64(cbLine) + F64(cbLineOffset) + F64(cbDnOffset) + F64(cbPdOffset) + F64(cbSymOffset) + F64(cbOptOffset) + F64(cbAuxOffset) + F64(cbSsOffset) + F64(cbSsExtOffset) + F64(cbFdOffset) + F64(cbRfdOffset) + F64(cbExtOffset) +} mdebug_hdr_64; + +typedef struct +{ + F32(adr) + F32(rss) + F32(issBase) + F32(cbSs) + F32(isymBase) + F32(csym) + F32(ilineBase) + F32(cline) + F32(ioptBase) + F32(copt) + F16(ipdFirst) + F16(cpd) + F32(iauxBase) + F32(caux) + F32(rfdBase) + F32(crfd) + F8(bits1) + F24(bits2) + F32(cbLineOffset) + F32(cbLine) +} mdebug_fdr_32; + +typedef struct +{ + F64(adr) + F64(cbLineOffset) + F64(cbLine) + F64(cbSs) + F32(rss) + F32(issBase) + F32(isymBase) + F32(csym) + F32(ilineBase) + F32(cline) + F32(ioptBase) + F32(copt) + F32(ipdFirst) + F32(cpd) + F32(iauxBase) + F32(caux) + F32(rfdBase) + F32(crfd) + F8(bits1) + F24(bits2) + F32(padding) +} mdebug_fdr_64; + +typedef struct +{ + F32(iss) + F32(value) + F8(bits1) + F8(bits2) + F8(bits3) + F8(bits4) +} mdebug_sym_32; + +typedef struct +{ + F64(value) + F32(iss) + F8(bits1) + F8(bits2) + F8(bits3) + F8(bits4) +} mdebug_sym_64; + +typedef struct +{ + F8(bits1) + F8(bits2) + F16(fd) + mdebug_sym_32 asym; +} mdebug_ext_32; + +typedef struct +{ + mdebug_sym_64 asym; + F8(bits1) + F24(bits2) + F32(fd) +} mdebug_ext_64; + +typedef struct +{ + F32(adr) + F32(isym) + F32(iline) + F32(regmask) + F32(regoffset) + F32(iopt) + F32(fregmask) + F32(fregoffset) + F32(frameoffset) + F16(framereg) + F16(pcreg) + F32(lnLow) + F32(lnHigh) + F32(cbLineOffset) +} mdebug_pdr_32; + +typedef struct +{ + F64(adr) + F64(cbLineOffset) + F32(isym) + F32(iline) + F32(regmask) + F32(regoffset) + F32(iopt) + F32(fregmask) + F32(fregoffset) + F32(frameoffset) + F32(lnLow) + F32(lnHigh) + F8(gp_prologue) + F8(bits1) + F8(bits2) + F8(localoff) + F16(framereg) + F16(pcreg) +} mdebug_pdr_64; + +typedef struct +{ + F32(bits); +} mdebug_rndx; + +typedef struct +{ + F8(bits1) + F8(bits2) + F8(bits3) + F8(bits4) + mdebug_rndx rndx; + F32(offset) +} mdebug_opt; + +typedef struct +{ + F32(rfd) + F32(index) +} mdebug_dnr; + +typedef struct +{ + F32(rfd) +} mdebug_rfd; + +#define scNil 0 +#define scText 1 +#define scData 2 +#define scBss 3 +#define scRegister 4 +#define scAbs 5 +#define scUndefined 6 +#define scCdbLocal 7 +#define scBits 8 +#define scCdbSystem 9 +#define scDbx 9 +#define scRegImage 10 +#define scInfo 11 +#define scUserStruct 12 +#define scSData 13 +#define scSBss 14 +#define scRData 15 +#define scVar 16 +#define scCommon 17 +#define scSCommon 18 +#define scVarRegister 19 +#define scVariant 20 +#define scSUndefined 21 +#define scInit 22 +#define scBasedVar 23 +#define scXData 24 +#define scPData 25 +#define scFini 26 +#define scRConst 27 +#define scMax 32 + +#define stNil 0 +#define stGlobal 1 +#define stStatic 2 +#define stParam 3 +#define stLocal 4 +#define stLabel 5 +#define stProc 6 +#define stBlock 7 +#define stEnd 8 +#define stMember 9 +#define stTypedef 10 +#define stFile 11 +#define stRegReloc 12 +#define stForward 13 +#define stStaticProc 14 +#define stConstant 15 +#define stStaParam 16 +#define stStruct 26 +#define stUnion 27 +#define stEnum 28 +#define stIndirect 34 +#define stMax 64 + +struct mdebug +{ + uint32_t (*read_32) (char *); + GElf_Addr (*read_ptr) (char *); + void (*write_ptr) (char *, GElf_Addr); + void (*adjust_sym) (struct mdebug *, unsigned char *, GElf_Addr, GElf_Addr); + unsigned char *buf; + DSO *dso; +}; + +static uint32_t +read_native_32 (char *p) +{ + return *(uint32_t *)p; +} + +static uint32_t +read_swap_32 (char *p) +{ + return bswap_32 (*(uint32_t *)p); +} + +static GElf_Addr +read_native_ptr32 (char *p) +{ + return *(uint32_t *)p; +} + +static GElf_Addr +read_swap_ptr32 (char *p) +{ + return bswap_32 (*(uint32_t *)p); +} + +static void +write_native_ptr32 (char *p, GElf_Addr v) +{ + *(uint32_t *)p = v; +} + +static void +write_swap_ptr32 (char *p, GElf_Addr v) +{ + *(uint32_t *)p = bswap_32 (v); +} + +static GElf_Addr +read_native_ptr64 (char *p) +{ + return *(uint64_t *)p; +} + +static GElf_Addr +read_swap_ptr64 (char *p) +{ + return bswap_64 (*(uint64_t *)p); +} + +static void +write_native_ptr64 (char *p, GElf_Addr v) +{ + *(uint64_t *)p = v; +} + +static void +write_swap_ptr64 (char *p, GElf_Addr v) +{ + *(uint64_t *)p = bswap_64 (v); +} + +static inline int +mdebug_sym_relocate (unsigned int st, unsigned int sc) +{ + switch (sc) + { + case scData: + case scBss: + case scAbs: + case scSData: + case scSBss: + case scRData: + case scXData: + case scPData: + return 1; + case scText: + case scInit: + case scFini: + case scRConst: + if (st != stBlock && st != stEnd && st != stFile) + return 1; + default: + return 0; + } +} + +static void +adjust_mdebug_sym_le32 (struct mdebug *mdebug, mdebug_sym_32 *symptr, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned int st, sc; + GElf_Addr addr; + + st = symptr->bits1[0] & 0x3f; + sc = (symptr->bits1[0] >> 6) | ((symptr->bits2[0] & 7) << 2); + if (mdebug_sym_relocate (st, sc)) + { + addr = mdebug->read_ptr (symptr->value); + if (addr >= start && (addr || sc != scAbs)) + mdebug->write_ptr (symptr->value, addr + adjust); + } +} + +static void +adjust_mdebug_sym_be32 (struct mdebug *mdebug, mdebug_sym_32 *symptr, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned int st, sc; + GElf_Addr addr; + + st = symptr->bits1[0] >> 2; + sc = ((symptr->bits1[0] & 3) << 3) | (symptr->bits2[0] >> 5); + if (mdebug_sym_relocate (st, sc)) + { + addr = mdebug->read_ptr (symptr->value); + if (addr >= start && (addr || sc != scAbs)) + mdebug->write_ptr (symptr->value, addr + adjust); + } +} + +static void +adjust_mdebug_sym_le64 (struct mdebug *mdebug, mdebug_sym_64 *symptr, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned int st, sc; + GElf_Addr addr; + + st = symptr->bits1[0] & 0x3f; + sc = (symptr->bits1[0] >> 6) | ((symptr->bits2[0] & 7) << 2); + if (mdebug_sym_relocate (st, sc)) + { + addr = mdebug->read_ptr (symptr->value); + if (addr >= start && (addr || sc != scAbs)) + mdebug->write_ptr (symptr->value, addr + adjust); + } +} + +static void +adjust_mdebug_sym_be64 (struct mdebug *mdebug, mdebug_sym_64 *symptr, + GElf_Addr start, GElf_Addr adjust) +{ + unsigned int st, sc; + GElf_Addr addr; + + st = symptr->bits1[0] >> 2; + sc = ((symptr->bits1[0] & 3) << 3) | (symptr->bits2[0] >> 5); + if (mdebug_sym_relocate (st, sc)) + { + addr = mdebug->read_ptr (symptr->value); + if (addr >= start && (addr || sc != scAbs)) + mdebug->write_ptr (symptr->value, addr + adjust); + } +} + +#define SIZEOf(x) \ + (dso->arch->class == ELFCLASS32 ? sizeof (x##_32) : sizeof (x##_64)) +#define SIZEOF(x) SIZEOf(x) +#define OFFSETOf(x,y) \ + (dso->arch->class == ELFCLASS32 ? offsetof (x##_32, y) : offsetof (x##_64, y)) +#define OFFSETOF(x,y) OFFSETOf(x,y) + +static int +start_mdebug (DSO *dso, int n, struct mdebug *mdebug) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + + data = elf_getdata (scn, NULL); + mdebug->buf = data->d_buf; + mdebug->dso = dso; + assert (data != NULL && data->d_buf != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0 && data->d_size == dso->shdr[n].sh_size); + if (dso->mdebug_orig_offset == 0) + dso->mdebug_orig_offset = dso->shdr[n].sh_offset; +#if __BYTE_ORDER == __BIG_ENDIAN + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) +#elif __BYTE_ORDER == __LITTLE_ENDIAN + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) +#else +# error Not supported host endianess +#endif + { + mdebug->read_32 = read_native_32; + if (dso->arch->class == ELFCLASS32) + { + mdebug->read_ptr = read_native_ptr32; + mdebug->write_ptr = write_native_ptr32; + } + else + { + mdebug->read_ptr = read_native_ptr64; + mdebug->write_ptr = write_native_ptr64; + } + } +#if __BYTE_ORDER == __BIG_ENDIAN + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) +#elif __BYTE_ORDER == __LITTLE_ENDIAN + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) +#endif + { + mdebug->read_32 = read_swap_32; + if (dso->arch->class == ELFCLASS32) + { + mdebug->read_ptr = read_swap_ptr32; + mdebug->write_ptr = write_swap_ptr32; + } + else + { + mdebug->read_ptr = read_swap_ptr64; + mdebug->write_ptr = write_swap_ptr64; + } + } + else + { + error (0, 0, "%s: Wrong ELF data enconding", dso->filename); + return 1; + } + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) + { + if (dso->arch->class == ELFCLASS32) + mdebug->adjust_sym = (void *) adjust_mdebug_sym_le32; + else + mdebug->adjust_sym = (void *) adjust_mdebug_sym_le64; + } + else + { + if (dso->arch->class == ELFCLASS32) + mdebug->adjust_sym = (void *) adjust_mdebug_sym_be32; + else + mdebug->adjust_sym = (void *) adjust_mdebug_sym_be64; + } + + if (dso->shdr[n].sh_size < SIZEOF (mdebug_hdr)) + { + error (0, 0, "%s: .mdebug section too small", dso->filename); + return 1; + } + return 0; +} + +int +adjust_mdebug (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + struct mdebug mdebug; + struct { GElf_Off offset; GElf_Off size; size_t entsize; } regions [11]; + int i = 0; + unsigned char *symptr, *endptr; + + if (start_mdebug (dso, n, &mdebug)) + return 1; + +#define READ(x, y, longsize, sz) \ +do { \ + unsigned char *tmp; \ + tmp = mdebug.buf + OFFSETOF (mdebug_hdr, x); \ + regions[i].offset = mdebug.read_ptr (tmp); \ + tmp = mdebug.buf + OFFSETOF (mdebug_hdr, y); \ + if (longsize) \ + regions[i].size = mdebug.read_ptr (tmp); \ + else \ + regions[i].size = mdebug.read_32 (tmp); \ + regions[i].entsize = sz; \ + ++i; \ +} while (0) + + READ (cbLineOffset, cbLine, 1, sizeof (char)); + READ (cbDnOffset, idnMax, 0, sizeof (mdebug_dnr)); + READ (cbPdOffset, ipdMax, 0, SIZEOF (mdebug_pdr)); + READ (cbSymOffset, isymMax, 0, SIZEOF (mdebug_sym)); + READ (cbOptOffset, ioptMax, 0, sizeof (mdebug_opt)); + READ (cbAuxOffset, iauxMax, 0, 4 * sizeof (char)); + READ (cbSsOffset, issMax, 0, sizeof (char)); + READ (cbSsExtOffset, issExtMax, 0, sizeof (char)); + READ (cbFdOffset, ifdMax, 0, SIZEOF (mdebug_fdr)); + READ (cbRfdOffset, crfd, 0, sizeof (mdebug_rfd)); + READ (cbExtOffset, iextMax, 0, SIZEOF (mdebug_ext)); + +#undef READ + + for (i = 0; i < 11; ++i) + { + if (regions[i].offset) + regions[i].offset -= dso->mdebug_orig_offset; + regions[i].size *= regions[i].entsize; + if (regions[i].offset >= dso->shdr[n].sh_size + || regions[i].offset + regions[i].size > dso->shdr[n].sh_size) + { + error (0, 0, "%s: File offsets in .mdebug header point outside of .mdebug section", + dso->filename); + return 1; + } + } + + /* Adjust symbols. */ + if (regions[3].offset) + for (symptr = mdebug.buf + regions[3].offset, + endptr = symptr + regions[3].size; + symptr < endptr; + symptr += regions[3].entsize) + mdebug.adjust_sym (&mdebug, symptr, start, adjust); + + /* Adjust file descriptor's addresses. */ + if (regions[8].offset) + for (symptr = mdebug.buf + regions[8].offset, + endptr = symptr + regions[8].size; + symptr < endptr; + symptr += regions[8].entsize) + { + GElf_Addr addr; + + assert (offsetof (mdebug_fdr_32, adr) == 0); + assert (offsetof (mdebug_fdr_64, adr) == 0); + addr = mdebug.read_ptr (symptr); + if (addr >= start) + mdebug.write_ptr (symptr, addr + adjust); + } + + /* Adjust extended symbols. */ + if (regions[10].offset) + for (symptr = mdebug.buf + regions[10].offset + + OFFSETOF (mdebug_ext, asym), + endptr = symptr + regions[10].size; + symptr < endptr; + symptr += regions[10].entsize) + mdebug.adjust_sym (&mdebug, symptr, start, adjust); + + return 0; +} + +int +finalize_mdebug (DSO *dso) +{ + int i; + struct mdebug mdebug; + GElf_Addr adj; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + if ((dso->arch->machine == EM_ALPHA + && dso->shdr[i].sh_type == SHT_ALPHA_DEBUG) + || (dso->arch->machine == EM_MIPS + && dso->shdr[i].sh_type == SHT_MIPS_DEBUG)) + break; + + assert (i < dso->ehdr.e_shnum); + + /* If .mdebug's file position did not change, there is nothing to do. */ + adj = dso->shdr[i].sh_offset - dso->mdebug_orig_offset; + if (! adj) + return 0; + + if (start_mdebug (dso, i, &mdebug)) + return 1; + +#define ADJUST(x) \ +do { \ + unsigned char *tmp; \ + GElf_Addr val; \ + tmp = mdebug.buf + OFFSETOF (mdebug_hdr, x); \ + val = mdebug.read_ptr (tmp); \ + if (! val) \ + break; \ + val += adj; \ + if (val < dso->shdr[i].sh_offset \ + || val >= dso->shdr[i].sh_offset + dso->shdr[i].sh_size) \ + { \ + error (0, 0, "%s: File offsets in .mdebug header point outside of .mdebug section", \ + dso->filename); \ + return 1; \ + } \ + mdebug.write_ptr (tmp, val); \ +} while (0) + + ADJUST (cbLineOffset); + ADJUST (cbDnOffset); + ADJUST (cbPdOffset); + ADJUST (cbSymOffset); + ADJUST (cbOptOffset); + ADJUST (cbAuxOffset); + ADJUST (cbSsOffset); + ADJUST (cbSsExtOffset); + ADJUST (cbFdOffset); + ADJUST (cbRfdOffset); + ADJUST (cbExtOffset); + +#undef ADJUST + return 0; +} diff --git a/trunk/src/prelink.c b/trunk/src/prelink.c new file mode 100644 index 0000000..1a2260e --- /dev/null +++ b/trunk/src/prelink.c @@ -0,0 +1,972 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" + +static GElf_Addr +resolve_ldso (struct prelink_info *info, GElf_Word r_sym, + int reloc_type __attribute__((unused))) +{ + /* Dynamic linker does not depend on any other library, + all symbols resolve to themselves with the exception + of SHN_UNDEF symbols which resolve to 0. */ + if (info->symtab[r_sym].st_shndx == SHN_UNDEF) + { + info->resolveent = NULL; + info->resolvetls = NULL; + return 0; + } + else + { + /* As the dynamic linker is relocated first, + l_addr will be 0. */ + info->resolveent = info->ent; + info->resolvetls = NULL; + return 0 + info->symtab[r_sym].st_value; + } +} + +static GElf_Addr +resolve_dso (struct prelink_info *info, GElf_Word r_sym, + int reloc_type) +{ + struct prelink_symbol *s; + int reloc_class = info->dso->arch->reloc_class (reloc_type); + + for (s = & info->symbols[r_sym]; s; s = s->next) + if (s->reloc_class == reloc_class) + break; + + info->resolveent = NULL; + info->resolvetls = NULL; + + if (s == NULL || s->u.ent == NULL) + return 0; + + if (reloc_class == RTYPE_CLASS_TLS) + { + info->resolvetls = s->u.tls; + return s->value; + } + + info->resolveent = s->u.ent; + return s->u.ent->base + s->value; +} + +static int +prelink_rel (DSO *dso, int n, struct prelink_info *info) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec; + + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + switch (dso->arch->prelink_rel (info, &rel, addr)) + { + case 2: + gelfx_update_rel (dso->elf, data, ndx, &rel); + break; + case 0: + break; + default: + return 1; + } + } + } + return 0; +} + +static int +prelink_rela (DSO *dso, int n, struct prelink_info *info) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec; + + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + switch (dso->arch->prelink_rela (info, &rela, addr)) + { + case 2: + gelfx_update_rela (dso->elf, data, ndx, &rela); + break; + case 0: + break; + default: + return 1; + } + } + } + return 0; +} + +int +prelink_prepare (DSO *dso) +{ + struct reloc_info rinfo; + int liblist = 0, libstr = 0, newlibstr = 0, undo = 0, newundo = 0; + int i; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + const char *name + = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".gnu.liblist")) + liblist = i; + else if (! strcmp (name, ".gnu.libstr")) + libstr = i; + else if (! strcmp (name, ".gnu.prelink_undo")) + undo = i; + } + + if (undo == 0) + { + Elf32_Shdr *shdr32; + Elf64_Shdr *shdr64; + Elf_Data src, dst; + + dso->undo.d_size = gelf_fsize (dso->elf, ELF_T_EHDR, 1, EV_CURRENT) + + gelf_fsize (dso->elf, ELF_T_PHDR, + dso->ehdr.e_phnum, EV_CURRENT) + + gelf_fsize (dso->elf, ELF_T_SHDR, + dso->ehdr.e_shnum - 1, EV_CURRENT); + dso->undo.d_buf = malloc (dso->undo.d_size); + if (dso->undo.d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not create .gnu.prelink_undo section", + dso->filename); + return 1; + } + dso->undo.d_type = ELF_T_BYTE; + dso->undo.d_off = 0; + dso->undo.d_align = gelf_fsize (dso->elf, ELF_T_ADDR, 1, EV_CURRENT); + dso->undo.d_version = EV_CURRENT; + src = dso->undo; + src.d_type = ELF_T_EHDR; + src.d_size = gelf_fsize (dso->elf, ELF_T_EHDR, 1, EV_CURRENT); + dst = src; + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + src.d_buf = elf32_getehdr (dso->elf); + if (elf32_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + case ELFCLASS64: + src.d_buf = elf64_getehdr (dso->elf); + if (elf64_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + default: + return 1; + } + src.d_buf = dst.d_buf + src.d_size; + src.d_type = ELF_T_PHDR; + src.d_size = gelf_fsize (dso->elf, ELF_T_PHDR, dso->ehdr.e_phnum, + EV_CURRENT); + dst = src; + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + src.d_buf = elf32_getphdr (dso->elf); + if (elf32_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + case ELFCLASS64: + src.d_buf = elf64_getphdr (dso->elf); + if (elf64_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + } + src.d_buf = dst.d_buf + src.d_size; + src.d_type = ELF_T_SHDR; + src.d_size = gelf_fsize (dso->elf, ELF_T_SHDR, + dso->ehdr.e_shnum - 1, EV_CURRENT); + dst = src; + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + shdr32 = (Elf32_Shdr *) src.d_buf; + /* Note: cannot use dso->scn[i] below, since we want to save the + original section order before non-alloced sections were + sorted by sh_offset. */ + for (i = 1; i < dso->ehdr.e_shnum; ++i) + shdr32[i - 1] = *elf32_getshdr (elf_getscn (dso->elf, i)); + if (elf32_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + case ELFCLASS64: + shdr64 = (Elf64_Shdr *) src.d_buf; + /* Note: cannot use dso->scn[i] below, since we want to save the + original section order before non-alloced sections were + sorted by sh_offset. */ + for (i = 1; i < dso->ehdr.e_shnum; ++i) + shdr64[i - 1] = *elf64_getshdr (elf_getscn (dso->elf, i)); + if (elf64_xlatetof (&dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Failed to create .gnu.prelink_undo section", + dso->filename); + return 1; + } + break; + } + } + + if (dso->ehdr.e_type != ET_DYN) + return 0; + + if (find_reloc_sections (dso, &rinfo)) + return 1; + + if (is_ldso_soname (dso->soname)) + { + liblist = -1; + libstr = -1; + } + + if (liblist && libstr && undo + && ! rinfo.rel_to_rela && ! rinfo.rel_to_rela_plt) + return 0; + + if (! liblist || ! libstr || ! undo) + { + struct section_move *move; + + move = init_section_move (dso); + if (move == NULL) + return 1; + + if (! liblist) + { + liblist = move->old_to_new [dso->ehdr.e_shstrndx]; + add_section (move, liblist); + } + else + liblist = 0; + + if (! libstr) + { + add_section (move, liblist + 1); + libstr = liblist + 1; + newlibstr = 1; + } + else if (libstr != -1) + libstr = move->old_to_new[libstr]; + + if (! undo) + { + if (libstr == -1) + { + undo = move->old_to_new [dso->ehdr.e_shstrndx]; + add_section (move, undo); + } + else + { + add_section (move, libstr + 1); + undo = libstr + 1; + } + newundo = 1; + } + else + undo = move->old_to_new[undo]; + + if (reopen_dso (dso, move, NULL)) + { + free (move); + return 1; + } + + free (move); + if (liblist) + { + memset (&dso->shdr[liblist], 0, sizeof (GElf_Shdr)); + dso->shdr[liblist].sh_name = shstrtabadd (dso, ".gnu.liblist"); + if (dso->shdr[liblist].sh_name == 0) + return 1; + dso->shdr[liblist].sh_type = SHT_GNU_LIBLIST; + dso->shdr[liblist].sh_offset = dso->shdr[liblist - 1].sh_offset; + if (dso->shdr[liblist - 1].sh_type != SHT_NOBITS) + dso->shdr[liblist].sh_offset += dso->shdr[liblist - 1].sh_size; + dso->shdr[liblist].sh_link = libstr; + dso->shdr[liblist].sh_addralign = sizeof (GElf_Word); + dso->shdr[liblist].sh_entsize = sizeof (Elf32_Lib); + } + + if (newlibstr) + { + memset (&dso->shdr[libstr], 0, sizeof (GElf_Shdr)); + dso->shdr[libstr].sh_name = shstrtabadd (dso, ".gnu.libstr"); + if (dso->shdr[libstr].sh_name == 0) + return 1; + dso->shdr[libstr].sh_type = SHT_STRTAB; + dso->shdr[libstr].sh_offset = dso->shdr[libstr - 1].sh_offset; + if (dso->shdr[libstr - 1].sh_type != SHT_NOBITS) + dso->shdr[libstr].sh_offset += dso->shdr[libstr - 1].sh_size; + dso->shdr[libstr].sh_addralign = 1; + } + + if (newundo) + { + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr newoffset; + + memset (&dso->shdr[undo], 0, sizeof (GElf_Shdr)); + dso->shdr[undo].sh_name = shstrtabadd (dso, ".gnu.prelink_undo"); + if (dso->shdr[undo].sh_name == 0) + return 1; + dso->shdr[undo].sh_type = SHT_PROGBITS; + dso->shdr[undo].sh_offset = dso->shdr[undo - 1].sh_offset; + if (dso->shdr[undo - 1].sh_type != SHT_NOBITS) + dso->shdr[undo].sh_offset += dso->shdr[undo - 1].sh_size; + dso->shdr[undo].sh_addralign = dso->undo.d_align; + dso->shdr[undo].sh_entsize = 1; + dso->shdr[undo].sh_size = dso->undo.d_size; + newoffset = dso->shdr[undo].sh_offset + dso->undo.d_align - 1; + newoffset &= ~(dso->shdr[undo].sh_addralign - 1); + if (adjust_dso_nonalloc (dso, undo + 1, dso->shdr[undo].sh_offset, + dso->undo.d_size + newoffset + - dso->shdr[undo].sh_offset)) + return 1; + dso->shdr[undo].sh_offset = newoffset; + scn = dso->scn[undo]; + data = elf_getdata (scn, NULL); + assert (data != NULL && elf_getdata (scn, data) == NULL); + free (data->d_buf); + *data = dso->undo; + dso->undo.d_buf = NULL; + } + } + else if (reopen_dso (dso, NULL, NULL)) + return 1; + + if (rinfo.rel_to_rela || rinfo.rel_to_rela_plt) + { + /* On REL architectures, we might need to convert some REL + relocations to RELA relocs. */ + + int safe = 1, align = 0, last; + GElf_Addr start, adjust, adjust1, adjust2; + + for (i = 1; i < (rinfo.plt ? rinfo.plt : rinfo.first); i++) + switch (dso->shdr[i].sh_type) + { + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_DYNSYM: + case SHT_REL: + case SHT_RELA: + case SHT_STRTAB: + case SHT_NOTE: + case SHT_GNU_verdef: + case SHT_GNU_verneed: + case SHT_GNU_versym: + /* These sections are safe, no relocations should point + to it, therefore enlarging a section after sections + from this set only (and SHT_REL) in ET_DYN just needs + adjusting the rest of the library. */ + break; + case SHT_DYNAMIC: + case SHT_MIPS_REGINFO: + /* The same applies to these sections on MIPS. The convention + is to put .dynamic and .reginfo near the beginning of the + read-only segment, before the program text. No relocations + may refer to them. */ + if (dso->ehdr.e_machine == EM_MIPS) + break; + /* FALLTHROUGH */ + default: + /* The rest of sections are not safe. */ + safe = 0; + break; + } + + if (! safe) + { + error (0, 0, "%s: Cannot safely convert %s' section from REL to RELA", + dso->filename, strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[rinfo.rel_to_rela + ? rinfo.first : rinfo.plt].sh_name)); + return 1; + } + + for (i = rinfo.plt ? rinfo.plt : rinfo.first; i < dso->ehdr.e_shnum; i++) + { + if (dso->shdr[i].sh_addralign > align) + align = dso->shdr[i].sh_addralign; + } + + if (rinfo.plt) + start = dso->shdr[rinfo.plt].sh_addr + dso->shdr[rinfo.plt].sh_size; + else + start = dso->shdr[rinfo.last].sh_addr + dso->shdr[rinfo.last].sh_size; + + adjust1 = 0; + adjust2 = 0; + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + if (rinfo.rel_to_rela) + { + for (i = rinfo.first; i <= rinfo.last; ++i) + { + GElf_Addr size = dso->shdr[i].sh_size / 2 * 3; + adjust1 += size - dso->shdr[i].sh_size; + if (convert_rel_to_rela (dso, i)) + return 1; + } + } + if (rinfo.rel_to_rela_plt) + { + GElf_Addr size = dso->shdr[rinfo.plt].sh_size / 2 * 3; + adjust2 = size - dso->shdr[rinfo.plt].sh_size; + if (convert_rel_to_rela (dso, rinfo.plt)) + return 1; + } + + adjust = adjust1 + adjust2; + + /* Need to make sure that all the remaining sections are properly + aligned. */ + if (align) + adjust = (adjust + align - 1) & ~(align - 1); + + /* Need to make sure adjust doesn't cause different Phdr segments + to overlap on the same page. */ + last = -1; + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz >= start) + { + if (last != -1 + && (((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz - 1) + ^ dso->phdr[i].p_vaddr) + & ~(dso->arch->max_page_size - 1)) + && !(((dso->phdr[last].p_vaddr + dso->phdr[last].p_memsz + + adjust - 1) + ^ (dso->phdr[i].p_vaddr + adjust)) + & ~(dso->arch->max_page_size - 1))) + { + if (align >= dso->arch->max_page_size) + { + error (0, 0, "%s: Cannot grow reloc sections", dso->filename); + return 1; + } + adjust = (adjust + dso->arch->max_page_size - 1) + & ~(dso->arch->max_page_size - 1); + } + last = i; + } + + /* Adjust all addresses pointing into remaining sections. */ + if (adjust_dso (dso, start - 1, adjust)) + return 1; + + if (rinfo.rel_to_rela) + { + GElf_Addr adjust3 = 0; + for (i = rinfo.first; i <= rinfo.last; ++i) + { + GElf_Addr size = dso->shdr[i].sh_size / 2 * 3; + + dso->shdr[i].sh_addr += adjust3; + dso->shdr[i].sh_offset += adjust3; + adjust3 += size - dso->shdr[i].sh_size; + dso->shdr[i].sh_size = size; + } + assert (adjust1 == adjust3); + if (rinfo.plt) + { + dso->shdr[rinfo.plt].sh_addr += adjust1; + dso->shdr[rinfo.plt].sh_offset += adjust1; + } + } + if (rinfo.rel_to_rela_plt) + dso->shdr[rinfo.plt].sh_size += adjust2; + + if (update_dynamic_rel (dso, &rinfo)) + return 1; + } + + return 0; +} + +static int +prelink_dso (struct prelink_info *info) +{ + int liblist = 0, libstr = 0, nobits_plt = 0; + int i, ndeps = info->ent->ndepends + 1; + DSO *dso = info->dso; + Elf32_Lib *list = NULL; + Elf_Scn *scn; + Elf_Data *data; + GElf_Addr oldsize, oldoffset; + size_t strsize; + + if (dso->ehdr.e_type != ET_DYN) + return 0; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + const char *name + = strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[i].sh_name); + if (! strcmp (name, ".gnu.liblist")) + liblist = i; + else if (! strcmp (name, ".gnu.libstr")) + libstr = i; + else if (! strcmp (name, ".plt") && dso->shdr[i].sh_type == SHT_NOBITS) + nobits_plt = i; +#if 0 + else if (dso->arch->create_opd && ! strcmp (name, ".opd")) + opd = i; +#endif + } + + if (nobits_plt) + { + int j, first; + GElf_Addr adj, last_offset; + + for (i = 0; i < dso->ehdr.e_phnum; ++i) + if (dso->phdr[i].p_type == PT_LOAD + && dso->phdr[i].p_vaddr <= dso->shdr[nobits_plt].sh_addr + && dso->phdr[i].p_vaddr + dso->phdr[i].p_memsz + >= dso->shdr[nobits_plt].sh_addr + + dso->shdr[nobits_plt].sh_size) + break; + + if (i == dso->ehdr.e_phnum) + { + error (0, 0, "%s: .plt section not contained within a segment", + dso->filename); + return 1; + } + + for (j = i + 1; j < dso->ehdr.e_phnum; ++j) + if (dso->phdr[j].p_type == PT_LOAD) + { + error (0, 0, "%s: library's NOBITS .plt section not in loadable last segment", + dso->filename); + return 1; + } + + for (j = nobits_plt - 1; j > 0; --j) + if (dso->shdr[j].sh_addr < dso->phdr[i].p_vaddr + || dso->shdr[j].sh_type != SHT_NOBITS) + break; + first = j + 1; + + for (j = first; j <= nobits_plt; ++j) + { + Elf_Data *data = elf_getdata (dso->scn[j], NULL); + + assert (data->d_buf == NULL); + assert (data->d_size == dso->shdr[j].sh_size); + if (data->d_size) + { + data->d_buf = calloc (data->d_size, 1); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not convert NOBITS section into PROGBITS", + dso->filename); + return 1; + } + } + data->d_type = ELF_T_BYTE; + dso->shdr[j].sh_type = SHT_PROGBITS; + dso->shdr[j].sh_offset = dso->phdr[i].p_offset + dso->shdr[j].sh_addr + - dso->phdr[i].p_vaddr; + } + + adj = dso->shdr[nobits_plt].sh_offset + dso->shdr[nobits_plt].sh_size + - dso->phdr[i].p_offset; + assert (adj <= dso->phdr[i].p_memsz); + if (adj > dso->phdr[i].p_filesz) + { + adj -= dso->phdr[i].p_filesz; + dso->phdr[i].p_filesz += adj; + if (adjust_dso_nonalloc (dso, nobits_plt + 1, + dso->shdr[first].sh_offset, adj)) + return 1; + } + + last_offset = dso->shdr[nobits_plt].sh_offset + + dso->shdr[nobits_plt].sh_size; + for (j = nobits_plt + 1; j < dso->ehdr.e_shnum; ++j) + if (!(dso->shdr[j].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR))) + break; + else + { + last_offset += dso->shdr[j].sh_addralign - 1; + last_offset &= ~(dso->shdr[j].sh_addralign - 1); + if (last_offset > dso->phdr[i].p_offset + dso->phdr[i].p_filesz) + last_offset = dso->phdr[i].p_offset + dso->phdr[i].p_filesz; + dso->shdr[j].sh_offset = last_offset; + } + } + + if (ndeps <= 1) + return 0; + + assert (liblist != 0); + assert (libstr != 0); + + list = calloc (ndeps - 1, sizeof (Elf32_Lib)); + if (list == NULL) + { + error (0, ENOMEM, "%s: Cannot build .gnu.liblist section", + dso->filename); + goto error_out; + } + + strsize = 1; + for (i = 0; i < ndeps - 1; ++i) + { + struct prelink_entry *ent = info->ent->depends[i]; + + strsize += strlen (info->sonames[i + 1]) + 1; + list[i].l_time_stamp = ent->timestamp; + list[i].l_checksum = ent->checksum; + } + + scn = dso->scn[libstr]; + data = elf_getdata (scn, NULL); + if (data == NULL) + data = elf_newdata (scn); + assert (elf_getdata (scn, data) == NULL); + + data->d_type = ELF_T_BYTE; + data->d_size = 1; + data->d_off = 0; + data->d_align = 1; + data->d_version = EV_CURRENT; + data->d_buf = realloc (data->d_buf, strsize); + if (data->d_buf == NULL) + { + error (0, ENOMEM, "%s: Could not build .gnu.libstr section", + dso->filename); + goto error_out; + } + + oldsize = dso->shdr[libstr].sh_size; + dso->shdr[libstr].sh_size = 1; + *(char *)data->d_buf = '\0'; + for (i = 0; i < ndeps - 1; ++i) + { + const char *name = info->sonames[i + 1]; + + list[i].l_name = strtabfind (dso, liblist, name); + if (list[i].l_name == 0) + { + size_t len = strlen (name) + 1; + + memcpy (data->d_buf + data->d_size, name, len); + list[i].l_name = data->d_size; + data->d_size += len; + dso->shdr[libstr].sh_size += len; + } + } + if (oldsize != dso->shdr[libstr].sh_size) + { + GElf_Addr adjust = dso->shdr[libstr].sh_size - oldsize; + + oldoffset = dso->shdr[libstr].sh_offset; + if (adjust_dso_nonalloc (dso, libstr + 1, oldoffset, adjust)) + goto error_out; + } + + scn = dso->scn[liblist]; + data = elf_getdata (scn, NULL); + if (data == NULL) + data = elf_newdata (scn); + assert (elf_getdata (scn, data) == NULL); + + data->d_type = ELF_T_WORD; + data->d_size = (ndeps - 1) * sizeof (Elf32_Lib); + data->d_off = 0; + data->d_align = sizeof (GElf_Word); + data->d_version = EV_CURRENT; + free (data->d_buf); + data->d_buf = list; + list = NULL; + + if (data->d_size != dso->shdr[liblist].sh_size) + { + GElf_Addr adjust = data->d_size - dso->shdr[liblist].sh_size; + GElf_Addr newoffset; + + oldoffset = dso->shdr[liblist].sh_offset; + newoffset = oldoffset; + if (newoffset & (data->d_align - 1)) + { + newoffset = (newoffset + data->d_align - 1) & ~(data->d_align - 1); + adjust += newoffset - dso->shdr[liblist].sh_offset; + } + if (adjust_dso_nonalloc (dso, liblist + 1, oldoffset, adjust)) + goto error_out; + dso->shdr[liblist].sh_offset = newoffset; + dso->shdr[liblist].sh_size = data->d_size; + } + + recompute_nonalloc_offsets (dso); + return 0; + +error_out: + free (list); + return 1; +} + +static int +prelink_set_timestamp (struct prelink_info *info) +{ + DSO *dso = info->dso; + + if (! verify) + info->ent->timestamp = getenv ("PRELINK_TIMESTAMP") ? + atoi (getenv ("PRELINK_TIMESTAMP")) + : (GElf_Word) time (NULL); + dso->info_DT_GNU_PRELINKED = info->ent->timestamp; + if (prelink_set_checksum (dso)) + return 1; + info->ent->checksum = dso->info_DT_CHECKSUM; + return 0; +} + +static void +free_info (struct prelink_info *info) +{ + int i; + + free (info->symtab); + free (info->dynbss); + free (info->sdynbss); + free (info->conflict_rela); + if (info->conflicts) + { + for (i = 0; i < info->ent->ndepends + 1; ++i) + { + struct prelink_conflict *c = info->conflicts[i]; + void *f; + + while (c != NULL) + { + f = c; + c = c->next; + free (f); + } + } + free (info->conflicts); + } + if (info->sonames) + { + for (i = 0; i < info->ent->ndepends + 1; ++i) + free ((char *) info->sonames[i]); + free (info->sonames); + } + free (info->tls); + if (info->symbols) + { + for (i = 0; i < info->symbol_count; ++i) + { + struct prelink_symbol *s = info->symbols[i].next; + void *f; + + while (s != NULL) + { + f = s; + s = s->next; + free (f); + } + } + free (info->symbols); + } +} + +int +prelink (DSO *dso, struct prelink_entry *ent) +{ + int i; + Elf_Scn *scn; + Elf_Data *data; + struct prelink_info info; + + ent->pltgot = dso->info[DT_PLTGOT]; + + if (! dso->info[DT_SYMTAB]) + return 0; + + if (! dso_is_rdwr (dso) && dso->ehdr.e_type == ET_DYN) + { + if (reopen_dso (dso, NULL, NULL)) + return 1; + } + + i = addr_to_sec (dso, dso->info[DT_SYMTAB]); + /* DT_SYMTAB should be found and should point to + start of .dynsym section. */ + if (i == -1 + || dso->info[DT_SYMTAB] != dso->shdr[i].sh_addr) + { + error (0, 0, "%s: Bad symtab", dso->filename); + return 1; + } + + memset (&info, 0, sizeof (info)); + info.ent = ent; + info.symtab_entsize = dso->shdr[i].sh_entsize; + info.symtab = calloc (dso->shdr[i].sh_size / dso->shdr[i].sh_entsize, + sizeof (GElf_Sym)); + if (info.symtab == NULL) + { + error (0, ENOMEM, "%s: Cannot convert .dynsym section", dso->filename); + return 1; + } + + scn = dso->scn[i]; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx, loc; + + loc = data->d_off / info.symtab_entsize; + maxndx = data->d_size / info.symtab_entsize; + for (ndx = 0; ndx < maxndx; ++ndx) + gelfx_getsym (dso->elf, data, ndx, info.symtab + loc + ndx); + } + info.symtab_start = + adjust_new_to_old (dso, dso->shdr[i].sh_addr - dso->base); + info.symtab_end = info.symtab_start + dso->shdr[i].sh_size; + info.dso = dso; + switch (prelink_get_relocations (&info)) + { + case 0: + goto error_out; + case 1: + info.resolve = resolve_ldso; + break; + case 2: + info.resolve = resolve_dso; + break; + } + + if (dso->arch->arch_pre_prelink && dso->arch->arch_pre_prelink (dso)) + goto error_out; + + if (dso->ehdr.e_type == ET_EXEC) + { + if (prelink_exec (&info)) + goto error_out; + } + else if (prelink_dso (&info)) + goto error_out; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + { + if (! (dso->shdr[i].sh_flags & SHF_ALLOC)) + continue; + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".gnu.conflict")) + continue; + switch (dso->shdr[i].sh_type) + { + case SHT_REL: + if (prelink_rel (dso, i, &info)) + goto error_out; + break; + case SHT_RELA: + if (prelink_rela (dso, i, &info)) + goto error_out; + break; + } + } + + if (dso->arch->arch_prelink && dso->arch->arch_prelink (&info)) + goto error_out; + + if (dso->arch->read_opd && dso->arch->read_opd (dso, ent)) + goto error_out; + + /* Must be last. */ + if (dso->ehdr.e_type == ET_DYN + && prelink_set_timestamp (&info)) + goto error_out; + + free_info (&info); + return 0; + +error_out: + free_info (&info); + return 1; +} diff --git a/trunk/src/prelink.h b/trunk/src/prelink.h new file mode 100644 index 0000000..0118602 --- /dev/null +++ b/trunk/src/prelink.h @@ -0,0 +1,527 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef PRELINK_H +#define PRELINK_H + +#include <elf.h> +#include <libelf.h> +#include <gelfx.h> +#include <ftw.h> +#include <stdint.h> +#include <stdlib.h> +#include <stdio.h> +#include <sys/stat.h> +#include <utime.h> + +#ifndef DT_GNU_LIBLIST +#define DT_GNU_LIBLIST 0x6ffffef9 +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 +#define DT_GNU_CONFLICT 0x6ffffef8 +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 +#define DT_GNU_PRELINKED 0x6ffffdf5 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#endif + +#if DT_GNU_LIBLIST == 0x6ffffef7 +#undef DT_GNU_LIBLIST +#undef DT_GNU_CONFLICT +#undef SHT_GNU_LIBLIST +#define DT_GNU_LIBLIST 0x6ffffef9 +#define DT_GNU_CONFLICT 0x6ffffef8 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#endif + +#ifndef DT_GNU_HASH +#define DT_GNU_HASH 0x6ffffef5 +#define SHT_GNU_HASH 0x6ffffff6 +#endif + +#ifndef DT_MIPS_RLD_VERSION +#define DT_MIPS_RLD_VERSION 0x70000001 +#define DT_MIPS_TIME_STAMP 0x70000002 +#define DT_MIPS_ICHECKSUM 0x70000003 +#define DT_MIPS_IVERSION 0x70000004 +#define DT_MIPS_FLAGS 0x70000005 +#define DT_MIPS_BASE_ADDRESS 0x70000006 +#define DT_MIPS_CONFLICT 0x70000008 +#define DT_MIPS_LIBLIST 0x70000009 +#define DT_MIPS_LOCAL_GOTNO 0x7000000a +#define DT_MIPS_CONFLICTNO 0x7000000b +#define DT_MIPS_LIBLISTNO 0x70000010 +#define DT_MIPS_SYMTABNO 0x70000011 +#define DT_MIPS_UNREFEXTNO 0x70000012 +#define DT_MIPS_GOTSYM 0x70000013 +#define DT_MIPS_HIPAGENO 0x70000014 +#define DT_MIPS_RLD_MAP 0x70000016 +#endif + +#ifndef R_MIPS_TLS_DTPMOD32 +#define R_MIPS_TLS_DTPMOD32 38 +#define R_MIPS_TLS_DTPREL32 39 +#define R_MIPS_TLS_TPREL32 47 +#endif + +#ifndef R_MIPS_GLOB_DAT +#define R_MIPS_GLOB_DAT 51 +#endif + +struct prelink_entry; +struct prelink_info; +struct PLArch; +struct opd_lib; + +struct PLAdjust +{ + GElf_Addr start; + GElf_Addr adjust; +}; + +struct section_move +{ + int old_shnum; + int new_shnum; + int *old_to_new; + int *new_to_old; +}; + +typedef struct +{ + Elf *elf, *elfro; + GElf_Ehdr ehdr; + GElf_Phdr *phdr; + Elf_Scn **scn; + GElf_Addr base, end, align; + GElf_Addr mask; + GElf_Addr info[DT_NUM]; + GElf_Addr info_DT_GNU_PRELINKED; + GElf_Addr info_DT_CHECKSUM; + GElf_Addr info_DT_VERNEED, info_DT_VERDEF, info_DT_VERSYM; + GElf_Addr info_DT_GNU_HASH; + GElf_Addr info_DT_MIPS_LOCAL_GOTNO; + GElf_Addr info_DT_MIPS_GOTSYM; + GElf_Addr info_DT_MIPS_SYMTABNO; +#define DT_GNU_PRELINKED_BIT 50 +#define DT_CHECKSUM_BIT 51 +#define DT_VERNEED_BIT 52 +#define DT_VERDEF_BIT 53 +#define DT_VERSYM_BIT 54 +#define DT_FILTER_BIT 55 +#define DT_AUXILIARY_BIT 56 +#define DT_LOPROC_BIT 57 +#define DT_GNU_HASH_BIT 58 + uint64_t info_set_mask; + int fd, fdro; + int lastscn, dynamic; + const char *soname; + const char *filename, *temp_filename; + struct PLArch *arch; + struct PLAdjust *adjust; + /* .mdebug has absolute file offsets in it. */ + GElf_Off mdebug_orig_offset; + Elf_Data undo; + int nadjust; + int permissive; + struct section_move *move; + GElf_Shdr shdr[0]; +} DSO; + +#define dynamic_info_is_set(dso,bit) ((dso)->info_set_mask & (1ULL << (bit))) + +struct layout_libs; + +struct PLArch +{ + const char *name; + int class; + int machine; + int alternate_machine[3]; + int max_reloc_size; + const char *dynamic_linker; + const char *dynamic_linker_alt; + int R_COPY; + int R_JMP_SLOT; + int R_RELATIVE; + int (*arch_adjust) (DSO *dso, GElf_Addr start, GElf_Addr adjust); + int (*adjust_section) (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust); + int (*adjust_dyn) (DSO *dso, int n, GElf_Dyn *dyn, GElf_Addr start, + GElf_Addr adjust); + int (*adjust_rel) (DSO *dso, GElf_Rel *rel, GElf_Addr start, + GElf_Addr adjust); + int (*adjust_rela) (DSO *dso, GElf_Rela *rela, GElf_Addr start, + GElf_Addr adjust); + int (*prelink_rel) (struct prelink_info *info, GElf_Rel *rel, + GElf_Addr reladdr); + int (*prelink_rela) (struct prelink_info *info, GElf_Rela *rela, + GElf_Addr relaaddr); + int (*prelink_conflict_rel) (DSO *dso, struct prelink_info *info, + GElf_Rel *rel, GElf_Addr reladdr); + int (*prelink_conflict_rela) (DSO *dso, struct prelink_info *info, + GElf_Rela *rela, GElf_Addr relaaddr); + int (*arch_prelink_conflict) (DSO *dso, struct prelink_info *info); + int (*apply_conflict_rela) (struct prelink_info *info, GElf_Rela *rela, + char *buf); + int (*apply_rel) (struct prelink_info *info, GElf_Rel *rel, char *buf); + int (*apply_rela) (struct prelink_info *info, GElf_Rela *rela, char *buf); + int (*rel_to_rela) (DSO *dso, GElf_Rel *rel, GElf_Rela *rela); + int (*rela_to_rel) (DSO *dso, GElf_Rela *rela, GElf_Rel *rel); + int (*need_rel_to_rela) (DSO *dso, int first, int last); + GElf_Addr (*create_opd) (struct prelink_info *info, int first, int last, + int plt); + int (*read_opd) (DSO *dso, struct prelink_entry *ent); + int (*free_opd) (struct prelink_entry *ent); + /* Return reloc size in bytes for given non-COPY reloc type. */ + int (*reloc_size) (int); +#define RTYPE_CLASS_VALID 8 +#define RTYPE_CLASS_PLT (8|1) +#define RTYPE_CLASS_COPY (8|2) +#define RTYPE_CLASS_TLS (8|4) + int (*reloc_class) (int); + int (*arch_pre_prelink) (DSO *dso); + int (*arch_prelink) (struct prelink_info *info); + int (*arch_undo_prelink) (DSO *dso); + int (*undo_prelink_rel) (DSO *dso, GElf_Rel *rel, GElf_Addr reladdr); + int (*undo_prelink_rela) (DSO *dso, GElf_Rela *rela, GElf_Addr relaaddr); + int (*layout_libs_init) (struct layout_libs *l); + int (*layout_libs_pre) (struct layout_libs *l); + int (*layout_libs_post) (struct layout_libs *l); + GElf_Addr mmap_base, mmap_end; + /* max_page_size is the ELF page size (ELF_MAXPAGESIZE in bfd), + page_size is PAGE_SIZE the architecture typically has, + or if there are more typical sizes, the smallest one. + It doesn't need to be the absolutely smallest supported one, + prelink only optimizes for such page_size. */ + GElf_Addr max_page_size, page_size; +} __attribute__((aligned(64))); + +DSO * open_dso (const char *name); +DSO * fdopen_dso (int fd, const char *name); +struct section_move *init_section_move (DSO *dso); +void add_section (struct section_move *move, int sec); +void remove_section (struct section_move *move, int sec); +int reopen_dso (DSO *dso, struct section_move *move, const char *); +int adjust_symbol_p (DSO *dso, GElf_Sym *sym); +int check_dso (DSO *dso); +int dso_is_rdwr (DSO *dso); +void read_dynamic (DSO *dso); +int set_dynamic (DSO *dso, GElf_Word tag, GElf_Addr value, int fatal); +int addr_to_sec (DSO *dso, GElf_Addr addr); +int adjust_dso (DSO *dso, GElf_Addr start, GElf_Addr adjust); +int adjust_nonalloc (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int first, + GElf_Addr start, GElf_Addr adjust); +int adjust_dso_nonalloc (DSO *dso, int first, GElf_Addr start, + GElf_Addr adjust); +int recompute_nonalloc_offsets (DSO *dso); +int adjust_stabs (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust); +int adjust_dwarf2 (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust); +int adjust_mdebug (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust); +int finalize_mdebug (DSO *dso); +int relocate_dso (DSO *dso, GElf_Addr base); +int update_dso (DSO *dso, const char *); +int prepare_write_dso (DSO *dso); +int write_dso (DSO *dso); +int close_dso (DSO *dso); +GElf_Addr adjust_old_to_new (DSO *dso, GElf_Addr addr); +GElf_Addr adjust_new_to_old (DSO *dso, GElf_Addr addr); +int strtabfind (DSO *dso, int strndx, const char *name); +int shstrtabadd (DSO *dso, const char *name); + +/* data.c */ + +/* Used for reading consecutive blocks of data from a DSO. */ +struct data_iterator { + /* The DSO that is being read. */ + DSO *dso; + + /* The data block that contained the last byte to be read. + NULL if no data has been read yet or if the end of the + DSO has been reached. */ + Elf_Data *data; + + /* The section that contains DATA, when DATA is nonnull. */ + int sec; + + /* The address of the next byte. */ + GElf_Addr addr; + + /* The offset of the next byte from the start of SEC, when DATA + is nonnull. */ + GElf_Addr sec_offset; +}; + +unsigned char * get_data (DSO *dso, GElf_Addr addr, int *scnp, Elf_Type *typep); +#define READWRITEPROTO(le,nn) \ +uint##nn##_t buf_read_u##le##nn (unsigned char *data); \ +uint##nn##_t read_u##le##nn (DSO *dso, GElf_Addr addr); \ +void buf_write_##le##nn (unsigned char *data, uint##nn##_t val);\ +int write_##le##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val); +#define READWRITEPROTOSIZE(nn) \ +READWRITEPROTO(le,nn) \ +READWRITEPROTO(be,nn) \ +uint##nn##_t buf_read_une##nn (DSO *dso, unsigned char *data); \ +uint##nn##_t read_une##nn (DSO *dso, GElf_Addr addr); \ +void buf_write_ne##nn (DSO *dso, unsigned char *data, \ + uint##nn##_t val); \ +void write_ne##nn (DSO *dso, GElf_Addr addr, uint##nn##_t val); +READWRITEPROTO(,8) +READWRITEPROTOSIZE(16) +READWRITEPROTOSIZE(32) +READWRITEPROTOSIZE(64) +#undef READWRITEPROTO +#undef READWRITEPROTOSIZE +const char * strptr (DSO *dso, int sec, off_t offset); +void init_data_iterator (struct data_iterator *it, DSO *dso, GElf_Addr addr); +unsigned char *get_data_from_iterator (struct data_iterator *it, + GElf_Addr size); +int get_sym_from_iterator (struct data_iterator *it, GElf_Sym *sym); + +#define PL_ARCH \ +static struct PLArch plarch __attribute__((section("pl_arch"),used)) + +#define addr_adjust(addr, start, adjust) \ + do { \ + if (addr >= start) \ + addr += adjust; \ + } while (0) + +struct prelink_cache_entry +{ + uint32_t filename; + uint32_t depends; + uint32_t checksum; +#define PCF_UNPRELINKABLE 0x40000 +#define PCF_PRELINKED 0x20000 +#define PCF_ELF64 0x10000 +#define PCF_MACHINE 0x0ffff + uint32_t flags; + uint32_t ctime; + uint32_t mtime; + uint64_t base; + uint64_t end; +}; + +struct prelink_cache +{ +#define PRELINK_CACHE_NAME "prelink-ELF" +#define PRELINK_CACHE_VER "0.3.2" +#define PRELINK_CACHE_MAGIC PRELINK_CACHE_NAME PRELINK_CACHE_VER + const char magic [sizeof (PRELINK_CACHE_MAGIC) - 1]; + uint32_t nlibs; + uint32_t ndeps; + uint32_t len_strings; + uint32_t unused[9]; + struct prelink_cache_entry entry[0]; + /* uint32_t depends [ndeps]; */ + /* const char strings [len_strings]; */ +}; + +struct prelink_link +{ + struct prelink_link *next; + const char *canon_filename; +}; + +struct prelink_entry +{ + const char *filename; + const char *canon_filename; + const char *soname; + struct prelink_link *hardlink; + GElf_Word timestamp; + GElf_Word checksum; + GElf_Addr base, end, layend, pltgot; + dev_t dev; + ino64_t ino; +#define ET_BAD (ET_NUM) +#define ET_CACHE_EXEC (ET_NUM + 1) +#define ET_CACHE_DYN (ET_NUM + 2) +#define ET_UNPRELINKABLE (ET_NUM + 3) + int type, done, ndepends, refs, flags; + union + { + int explicit; + int tmp; + } u; + uint32_t ctime, mtime; + struct prelink_entry **depends; + struct prelink_entry *prev, *next; + struct opd_lib *opd; +}; + +struct prelink_dir +{ + dev_t dev; + struct prelink_dir *next; + size_t len; + int flags; + char dir[0]; +}; + +struct prelink_tls +{ + GElf_Addr modid; + GElf_Addr offset; +}; + +struct prelink_symbol +{ + union + { + struct prelink_entry *ent; + struct prelink_tls *tls; + } u; + struct prelink_symbol *next; + GElf_Addr value; + int reloc_class; +}; + +struct prelink_conflict +{ + struct prelink_conflict *next; + /* Object which it was relocated to. */ + union + { + struct prelink_entry *ent; + struct prelink_tls *tls; + } lookup, + /* Object which the relocation was prelinked to. */ + conflict; + /* Offset from start of owner to owner's symbol. */ + GElf_Addr symoff; + /* Value it has in lookup.ent. */ + GElf_Addr lookupval; + /* Value it has in conflict.ent. */ + GElf_Addr conflictval; + int reloc_class; + int used; +}; + +#define conflict_lookup_value(cfl) \ + (((cfl)->reloc_class != RTYPE_CLASS_TLS ? (cfl)->lookup.ent->base : 0) \ + + (cfl)->lookupval) + +struct prelink_info +{ + DSO *dso; + DSO **dsos; + struct prelink_entry *ent; + struct prelink_symbol *symbols; + struct prelink_conflict **conflicts; + struct prelink_conflict *curconflicts; + struct prelink_tls *tls, *curtls; + const char **sonames; + char *dynbss, *sdynbss; + GElf_Addr dynbss_base, sdynbss_base; + size_t dynbss_size, sdynbss_size, symtab_entsize; + int symbol_count; + GElf_Sym *symtab; + GElf_Rela *conflict_rela; + size_t conflict_rela_alloced, conflict_rela_size; + GElf_Addr symtab_start, symtab_end; + GElf_Addr (*resolve) (struct prelink_info *info, GElf_Word r_sym, + int reloc_type); + struct prelink_entry *resolveent; + struct prelink_tls *resolvetls; +}; + +int prelink_prepare (DSO *dso); +int prelink (DSO *dso, struct prelink_entry *ent); +int prelink_init_cache (void); +int prelink_load_cache (void); +int prelink_print_cache (void); +int prelink_save_cache (int do_warn); +struct prelink_entry * + prelink_find_entry (const char *filename, const struct stat64 *stp, + int insert); +struct prelink_conflict * + prelink_conflict (struct prelink_info *info, GElf_Word r_sym, + int reloc_type); +GElf_Rela *prelink_conflict_add_rela (struct prelink_info *info); +int prelink_get_relocations (struct prelink_info *info); +int prelink_build_conflicts (struct prelink_info *info); +int update_dynamic_tags (DSO *dso, GElf_Shdr *shdr, GElf_Shdr *old_shdr, + struct section_move *move); +int prelink_exec (struct prelink_info *info); +int prelink_set_checksum (DSO *dso); +int is_ldso_soname (const char *soname); + +int prelink_undo (DSO *dso); + +int prelink_verify (const char *filename); + +int gather_object (const char *dir, int deref, int onefs); +int gather_config (const char *config); +int gather_check_libs (void); +int add_to_blacklist (const char *name, int deref, int onefs); +int blacklist_from_config (const char *config); + +FILE *execve_open (const char *path, char *const argv[], char *const envp[]); +int execve_close (FILE *f); + +int remove_redundant_cxx_conflicts (struct prelink_info *info); +int get_relocated_mem (struct prelink_info *info, DSO *dso, GElf_Addr addr, + char *buf, GElf_Word size); + +int layout_libs (void); + +void prelink_all (void); + +int undo_all (void); + +char *prelink_canonicalize (const char *name, struct stat64 *stp); + +extern const char *dynamic_linker; +extern const char *ld_library_path; +extern const char *prelink_cache; +extern const char *prelink_conf; +extern const char *undo_output; +extern int all; +extern int force; +extern int random_base; +extern int conserve_memory; +extern int verbose; +extern int dry_run; +extern int libs_only; +extern int enable_cxx_optimizations; +extern int exec_shield; +extern int undo; +extern int verify; +extern int print_cache; +enum verify_method_t { VERIFY_CONTENT, VERIFY_MD5, VERIFY_SHA }; +extern enum verify_method_t verify_method; +extern int quick; +extern long long seed; +extern GElf_Addr mmap_reg_start, mmap_reg_end; + +extern const char *sysroot; + +char *wrap_prelink_canonicalize (const char *name, struct stat64 *stp); +int wrap_lstat64 (const char *file, struct stat64 *buf); +int wrap_stat64 (const char *file, struct stat64 *buf); +int wrap_open (const char *file, int mode, ...); +int wrap_access (const char *file, int mode); +int wrap_rename (const char *old, const char *new); +int wrap_link (const char *old, const char *new); +int wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag); +int wrap_utime (const char *file, struct utimbuf *file_times); +int wrap_mkstemp (char *filename); +int wrap_unlink (const char *filename); + +extern const char *prelink_rtld; + +#endif /* PRELINK_H */ diff --git a/trunk/src/prelinktab.h b/trunk/src/prelinktab.h new file mode 100644 index 0000000..f41c79c --- /dev/null +++ b/trunk/src/prelinktab.h @@ -0,0 +1,27 @@ +/* Copyright (C) 2001 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef PRELINKTAB_H +#define PRELINKTAB_H + +#include "hashtab.h" +#include "prelink.h" + +extern htab_t prelink_devino_htab, prelink_filename_htab; +extern int prelink_entry_count; + +#endif /* PRELINKTAB_H */ diff --git a/trunk/src/reloc.c b/trunk/src/reloc.c new file mode 100644 index 0000000..70b4dbc --- /dev/null +++ b/trunk/src/reloc.c @@ -0,0 +1,422 @@ +/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" + +int +find_reloc_sections (DSO *dso, struct reloc_info *rinfo) +{ + int first, last, rela, i; + GElf_Addr start, end, pltstart, pltend; + + memset (rinfo, 0, sizeof (*rinfo)); + + if (dynamic_info_is_set (dso, DT_REL) + && dynamic_info_is_set (dso, DT_RELA)) + { + error (0, 0, "%s: Cannot prelink object with both DT_REL and DT_RELA tags", + dso->filename); + return 1; + } + + rela = dynamic_info_is_set (dso, DT_RELA); + + if (rela) + { + start = dso->info[DT_RELA]; + end = dso->info[DT_RELA] + dso->info[DT_RELASZ]; + } + else + { + start = dso->info[DT_REL]; + end = dso->info[DT_REL] + dso->info[DT_RELSZ]; + } + rinfo->reldyn_rela = rela; + + if (dso->info[DT_JMPREL]) + { + pltstart = dso->info[DT_JMPREL]; + pltend = dso->info[DT_JMPREL] + dso->info[DT_PLTRELSZ]; + first = addr_to_sec (dso, pltstart); + last = addr_to_sec (dso, pltend - 1); + if (first == -1 + || last == -1 + || first != last + || dso->shdr[first].sh_addr != pltstart + || dso->shdr[first].sh_addr + dso->shdr[first].sh_size != pltend + || (dso->info[DT_PLTREL] != DT_REL + && dso->info[DT_PLTREL] != DT_RELA) + || dso->shdr[first].sh_type + != (dso->info[DT_PLTREL] == DT_RELA ? SHT_RELA : SHT_REL) + || strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[first].sh_name), + dso->info[DT_PLTREL] == DT_RELA + ? ".rela.plt" : ".rel.plt")) + { + error (0, 0, "%s: DT_JMPREL tags don't surround .rel%s.plt section", + dso->filename, dso->info[DT_PLTREL] == DT_RELA ? "a" : ""); + return 1; + } + rinfo->plt = first; + rinfo->plt_rela = (dso->shdr[first].sh_type == SHT_RELA); + if (dso->shdr[first].sh_type == SHT_REL + && dso->arch->need_rel_to_rela != NULL + && dso->arch->need_rel_to_rela (dso, first, first)) + rinfo->rel_to_rela_plt = 1; + } + else + { + pltstart = end; + pltend = end; + } + + if (start == 0 && end == 0) + { + /* No non-PLT relocations. */ + return 0; + } + + if (start == end) + { + first = 0; + last = 0; + } + else + { + first = addr_to_sec (dso, start); + last = addr_to_sec (dso, end - 1); + + if (first == -1 + || last == -1 + || dso->shdr[first].sh_addr != start + || dso->shdr[last].sh_addr + dso->shdr[last].sh_size != end) + { + error (0, 0, "%s: DT_REL%s tags don't surround whole relocation sections", + dso->filename, rela ? "A" : ""); + return 1; + } + + for (i = first; i <= last; i++) + if (dso->shdr[i].sh_type != (rela ? SHT_RELA : SHT_REL)) + { + error (0, 0, "%s: DT_REL%s tags don't surround relocation sections of expected type", + dso->filename, rela ? "A" : ""); + return 1; + } + } + + if (pltstart != end && pltend != end) + { + error (0, 0, "%s: DT_JMPREL tag not adjacent to DT_REL%s relocations", + dso->filename, rela ? "A" : ""); + return 1; + } + + if (pltstart == start && pltend == end) + { + /* No non-PLT relocations. */ + rinfo->overlap = 1; + return 0; + } + + if (pltstart != end && pltend == end) + { + rinfo->overlap = 1; + --last; + } + + rinfo->first = first; + rinfo->last = last; + if (! rela + && first + && dso->arch->need_rel_to_rela != NULL + && dso->arch->need_rel_to_rela (dso, first, last)) + rinfo->rel_to_rela = 1; + return 0; +} + +int +convert_rel_to_rela (DSO *dso, int i) +{ + Elf_Data d1, d2, *d; + Elf_Scn *scn; + GElf_Rel rel; + GElf_Rela rela; + int ndx, maxndx; + + scn = dso->scn[i]; + d = elf_getdata (scn, NULL); + assert (elf_getdata (scn, d) == NULL); + assert (d->d_off == 0); + assert (d->d_size == dso->shdr[i].sh_size); + d1 = *d; + d2 = *d; + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + d1.d_size = d->d_size / 2 * 3; + d1.d_buf = malloc (d1.d_size); + d1.d_type = ELF_T_RELA; + if (d1.d_buf == NULL) + { + error (0, ENOMEM, "Cannot convert REL section to RELA"); + return 1; + } + + maxndx = d->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + if (gelfx_getrel (dso->elf, d, ndx, &rel) == 0 + || dso->arch->rel_to_rela (dso, &rel, &rela)) + { + free (d1.d_buf); + return 1; + } + /* gelf_update_rel etc. should have Elf * argument, so that + we don't have to do this crap. */ + *d = d1; + if (gelfx_update_rela (dso->elf, d, ndx, &rela) == 0) + { + *d = d2; + free (d1.d_buf); + return 1; + } + *d = d2; + } + + free (d2.d_buf); + *d = d1; + dso->shdr[i].sh_entsize + = gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + dso->shdr[i].sh_type = SHT_RELA; + return 0; +} + +int +convert_rela_to_rel (DSO *dso, int i) +{ + Elf_Data d1, d2, *d; + Elf_Scn *scn; + GElf_Rel rel; + GElf_Rela rela; + int ndx, maxndx; + + scn = dso->scn[i]; + d = elf_getdata (scn, NULL); + assert (elf_getdata (scn, d) == NULL); + assert (d->d_off == 0); + assert (d->d_size == dso->shdr[i].sh_size); + d1 = *d; + d2 = *d; + assert (sizeof (Elf32_Rel) * 3 == sizeof (Elf32_Rela) * 2); + assert (sizeof (Elf64_Rel) * 3 == sizeof (Elf64_Rela) * 2); + d1.d_size = d->d_size / 3 * 2; + d1.d_buf = malloc (d1.d_size); + d1.d_type = ELF_T_REL; + if (d1.d_buf == NULL) + { + error (0, ENOMEM, "Cannot convert RELA section to REL"); + return 1; + } + + maxndx = d->d_size / dso->shdr[i].sh_entsize; + for (ndx = 0; ndx < maxndx; ndx++) + { + if (gelfx_getrela (dso->elf, d, ndx, &rela) == 0 + || dso->arch->rela_to_rel (dso, &rela, &rel)) + { + free (d1.d_buf); + return 1; + } + /* gelf_update_rela etc. should have Elf * argument, so that + we don't have to do this crap. */ + *d = d1; + if (gelfx_update_rel (dso->elf, d, ndx, &rel) == 0) + { + *d = d2; + free (d1.d_buf); + return 1; + } + *d = d2; + } + + free (d2.d_buf); + *d = d1; + dso->shdr[i].sh_entsize + = gelf_fsize (dso->elf, ELF_T_REL, 1, EV_CURRENT); + dso->shdr[i].sh_type = SHT_REL; + return 0; +} + +int +update_dynamic_rel (DSO *dso, struct reloc_info *rinfo) +{ + GElf_Dyn *info[DT_NUM], *info_DT_RELCOUNT, *info_DT_RELACOUNT; + GElf_Dyn *dynamic = NULL; + int rel = rinfo->first, plt = rinfo->plt, overlap = rinfo->overlap; + int dynsec, count = 0, loc; + Elf_Data *data; + Elf_Scn *scn = NULL; + + memset (&info, 0, sizeof (info)); + info_DT_RELCOUNT = NULL; + info_DT_RELACOUNT = NULL; + for (dynsec = 0; dynsec < dso->ehdr.e_shnum; dynsec++) + if (dso->shdr[dynsec].sh_type == SHT_DYNAMIC) + { + scn = dso->scn[dynsec]; + dynamic = alloca (dso->shdr[dynsec].sh_size + / dso->shdr[dynsec].sh_entsize * sizeof (GElf_Dyn)); + loc = 0; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[dynsec].sh_entsize; + for (ndx = 0; ndx < maxndx; ++ndx, ++loc) + { + gelfx_getdyn (dso->elf, data, ndx, dynamic + loc); + if (dynamic[loc].d_tag == DT_NULL) + break; + else if ((GElf_Xword) dynamic[loc].d_tag < DT_NUM) + info[dynamic[loc].d_tag] = dynamic + loc; + else if (dynamic[loc].d_tag == DT_RELCOUNT) + info_DT_RELCOUNT = dynamic + loc; + else if (dynamic[loc].d_tag == DT_RELACOUNT) + info_DT_RELACOUNT = dynamic + loc; + } + if (ndx < maxndx) + break; + } + count = loc; + break; + } + + if (rel && plt && overlap) + { + if (dso->shdr[rel].sh_type != dso->shdr[plt].sh_type) + overlap = 0; + } + + if (rel || (plt && overlap)) + { + int dt_RELENT, dt_REL, dt_RELSZ; + + if (rinfo->reldyn_rela) + { + dt_RELENT = DT_RELAENT; + dt_REL = DT_RELA; + dt_RELSZ = DT_RELASZ; + } + else + { + dt_RELENT = DT_RELENT; + dt_REL = DT_REL; + dt_RELSZ = DT_RELSZ; + } + + assert (dso->info[dt_RELENT] + == gelf_fsize (dso->elf, rinfo->reldyn_rela + ? ELF_T_RELA : ELF_T_REL, 1, EV_CURRENT)); + assert (dso->info[dt_REL] != 0); + assert (dso->info[dt_RELSZ] != 0); + + info[dt_REL]->d_un.d_ptr = dso->shdr[rel ?: plt].sh_addr; + if (plt && overlap) + info[dt_RELSZ]->d_un.d_val = + dso->shdr[plt].sh_addr + dso->shdr[plt].sh_size; + else + info[dt_RELSZ]->d_un.d_val = + dso->shdr[rinfo->last].sh_addr + dso->shdr[rinfo->last].sh_size; + info[dt_RELSZ]->d_un.d_val -= info[dt_REL]->d_un.d_ptr; + + if (!rinfo->reldyn_rela && dso->shdr[rel ?: plt].sh_type == SHT_RELA) + { + info[DT_RELENT]->d_un.d_val = + gelf_fsize (dso->elf, ELF_T_RELA, 1, EV_CURRENT); + info[DT_REL]->d_tag = DT_RELA; + info[DT_RELSZ]->d_tag = DT_RELASZ; + info[DT_RELENT]->d_tag = DT_RELAENT; + if (info_DT_RELCOUNT) + info_DT_RELCOUNT->d_tag = DT_RELACOUNT; + } + else if (rinfo->reldyn_rela && dso->shdr[rel ?: plt].sh_type == SHT_REL) + { + info[DT_RELAENT]->d_un.d_val = + gelf_fsize (dso->elf, ELF_T_REL, 1, EV_CURRENT); + info[DT_RELA]->d_tag = DT_REL; + info[DT_RELASZ]->d_tag = DT_RELSZ; + info[DT_RELAENT]->d_tag = DT_RELENT; + if (info_DT_RELACOUNT) + info_DT_RELACOUNT->d_tag = DT_RELCOUNT; + } + } + + if (plt) + { + assert (dso->info[DT_JMPREL] != 0); + assert (dso->info[DT_PLTREL] == rinfo->plt_rela ? DT_RELA : DT_REL); + + info[DT_JMPREL]->d_un.d_ptr = dso->shdr[plt].sh_addr; + if (!rinfo->plt_rela && dso->shdr[plt].sh_type == SHT_RELA) + { + info[DT_PLTREL]->d_un.d_val = DT_RELA; + info[DT_PLTRELSZ]->d_un.d_val = dso->shdr[plt].sh_size; + } + else if (rinfo->plt_rela && dso->shdr[plt].sh_type == SHT_REL) + { + info[DT_PLTREL]->d_un.d_val = DT_REL; + info[DT_PLTRELSZ]->d_un.d_val = dso->shdr[plt].sh_size; + } + + if (!rel && !overlap) + { + int dt_REL = rinfo->reldyn_rela ? DT_RELA : DT_REL; + + if (info[dt_REL] && info[dt_REL]->d_un.d_ptr) + info[dt_REL]->d_un.d_ptr = info[DT_JMPREL]->d_un.d_ptr; + } + } + + loc = 0; + data = NULL; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + + maxndx = data->d_size / dso->shdr[dynsec].sh_entsize; + for (ndx = 0; ndx < maxndx && loc < count; ++ndx, ++loc) + if ((GElf_Xword) dynamic[loc].d_tag < DT_NUM + || dynamic[loc].d_tag == DT_RELCOUNT + || dynamic[loc].d_tag == DT_RELACOUNT) + gelfx_update_dyn (dso->elf, data, ndx, dynamic + loc); + if (ndx < maxndx) + break; + } + + read_dynamic (dso); + return 0; +} diff --git a/trunk/src/reloc.h b/trunk/src/reloc.h new file mode 100644 index 0000000..a2ceff9 --- /dev/null +++ b/trunk/src/reloc.h @@ -0,0 +1,44 @@ +/* Copyright (C) 2001, 2002 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef RELOC_H +#define RELOC_H + +#include "prelink.h" + +struct reloc_info +{ + int first; /* First dynamic SHT_REL* section. */ + int last; /* Last dynamic SHT_REL* section not counting .rel*.plt. */ + int plt; /* .rel*.plt section. */ + int overlap; /* 1 if DT_REL{,A}SZ range includes DT_PLTRELSZ range. */ + int reldyn_rela; /* first..last sections were originally RELA. */ + int plt_rela; /* plt section was originally RELA. */ + int rel_to_rela; /* first..last sections have to be converted REL->RELA. */ + int rel_to_rela_plt; /* plt section has to be converted REL->RELA. */ + int relcount; /* DT_RELCOUNT resp. DT_RELACOUNT. */ +}; + +int find_reloc_sections (DSO *dso, struct reloc_info *rinfo); +int convert_rel_to_rela (DSO *dso, int i); +int convert_rela_to_rel (DSO *dso, int i); +int update_dynamic_rel (DSO *dso, struct reloc_info *rinfo); +int undo_sections (DSO *dso, int undo, struct section_move *move, + struct reloc_info *rinfo, GElf_Ehdr *ehdr, + GElf_Phdr *phdr, GElf_Shdr *shdr); + +#endif /* RELOC_H */ diff --git a/trunk/src/sha.c b/trunk/src/sha.c new file mode 100644 index 0000000..cfbc956 --- /dev/null +++ b/trunk/src/sha.c @@ -0,0 +1,331 @@ +/* sha.c - Functions to compute the SHA1 hash (message-digest) of files + or blocks of memory. Complies to the NIST specification FIPS-180-1. + + Copyright (C) 2000, 2001, 2003 Scott G. Miller + + Credits: + Robert Klep <robert@ilse.nl> -- Expansion function fix + NOTE: The canonical source of this file is maintained in GNU coreutils. +*/ + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <byteswap.h> +#include "md5.h" +#include "sha.h" + +/* + Not-swap is a macro that does an endian swap on architectures that are + big-endian, as SHA needs some data in a little-endian format +*/ + +#if __BYTE_ORDER == __BIG_ENDIAN +# define SWAP(n) bswap_32 (n) +# define NOTSWAP(n) (n) +#else +# define SWAP(n) (n) +# define NOTSWAP(n) bswap_32 (n) +#endif + +/* This array contains the bytes used to pad the buffer to the next + 64-byte boundary. (RFC 1321, 3.1: Step 1) */ +static const unsigned char fillbuf[64] = { 0x80, 0 /* , 0, 0, ... */ }; + + +/* + Takes a pointer to a 160 bit block of data (five 32 bit ints) and + intializes it to the start constants of the SHA1 algorithm. This + must be called before using hash in the call to sha_hash +*/ +void +sha_init_ctx (struct sha_ctx *ctx) +{ + ctx->A = 0x67452301; + ctx->B = 0xefcdab89; + ctx->C = 0x98badcfe; + ctx->D = 0x10325476; + ctx->E = 0xc3d2e1f0; + + ctx->total[0] = ctx->total[1] = 0; + ctx->buflen = 0; +} + +/* Put result from CTX in first 20 bytes following RESBUF. The result + must be in little endian byte order. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha_read_ctx (const struct sha_ctx *ctx, void *resbuf) +{ + ((md5_uint32 *) resbuf)[0] = NOTSWAP (ctx->A); + ((md5_uint32 *) resbuf)[1] = NOTSWAP (ctx->B); + ((md5_uint32 *) resbuf)[2] = NOTSWAP (ctx->C); + ((md5_uint32 *) resbuf)[3] = NOTSWAP (ctx->D); + ((md5_uint32 *) resbuf)[4] = NOTSWAP (ctx->E); + + return resbuf; +} + +/* Process the remaining bytes in the internal buffer and the usual + prolog according to the standard and write the result to RESBUF. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +void * +sha_finish_ctx (struct sha_ctx *ctx, void *resbuf) +{ + /* Take yet unprocessed bytes into account. */ + md5_uint32 bytes = ctx->buflen; + size_t pad; + + /* Now count remaining bytes. */ + ctx->total[0] += bytes; + if (ctx->total[0] < bytes) + ++ctx->total[1]; + + pad = bytes >= 56 ? 64 + 56 - bytes : 56 - bytes; + memcpy (&ctx->buffer[bytes], fillbuf, pad); + + /* Put the 64-bit file length in *bits* at the end of the buffer. */ + *(md5_uint32 *) &ctx->buffer[bytes + pad + 4] = NOTSWAP (ctx->total[0] << 3); + *(md5_uint32 *) &ctx->buffer[bytes + pad] = NOTSWAP ((ctx->total[1] << 3) | + (ctx->total[0] >> 29)); + + /* Process last bytes. */ + sha_process_block (ctx->buffer, bytes + pad + 8, ctx); + + return sha_read_ctx (ctx, resbuf); +} + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +void * +sha_buffer (const char *buffer, size_t len, void *resblock) +{ + struct sha_ctx ctx; + + /* Initialize the computation context. */ + sha_init_ctx (&ctx); + + /* Process whole buffer but last len % 64 bytes. */ + sha_process_bytes (buffer, len, &ctx); + + /* Put result in desired memory area. */ + return sha_finish_ctx (&ctx, resblock); +} + +void +sha_process_bytes (const void *buffer, size_t len, struct sha_ctx *ctx) +{ + /* When we already have some bits in our internal buffer concatenate + both inputs first. */ + if (ctx->buflen != 0) + { + size_t left_over = ctx->buflen; + size_t add = 128 - left_over > len ? len : 128 - left_over; + + memcpy (&ctx->buffer[left_over], buffer, add); + ctx->buflen += add; + + if (ctx->buflen > 64) + { + sha_process_block (ctx->buffer, ctx->buflen & ~63, ctx); + + ctx->buflen &= 63; + /* The regions in the following copy operation cannot overlap. */ + memcpy (ctx->buffer, &ctx->buffer[(left_over + add) & ~63], + ctx->buflen); + } + + buffer = (const char *) buffer + add; + len -= add; + } + + /* Process available complete blocks. */ + if (len >= 64) + { +#define UNALIGNED_P(p) (((md5_uintptr) p) % __alignof__ (md5_uint32) != 0) + if (UNALIGNED_P (buffer)) + while (len > 64) + { + sha_process_block (memcpy (ctx->buffer, buffer, 64), 64, ctx); + buffer = (const char *) buffer + 64; + len -= 64; + } + else + { + sha_process_block (buffer, len & ~63, ctx); + buffer = (const char *) buffer + (len & ~63); + len &= 63; + } + } + + /* Move remaining bytes in internal buffer. */ + if (len > 0) + { + size_t left_over = ctx->buflen; + + memcpy (&ctx->buffer[left_over], buffer, len); + left_over += len; + if (left_over >= 64) + { + sha_process_block (ctx->buffer, 64, ctx); + left_over -= 64; + memcpy (ctx->buffer, &ctx->buffer[64], left_over); + } + ctx->buflen = left_over; + } +} + +/* --- Code below is the primary difference between md5.c and sha.c --- */ + +/* SHA1 round constants */ +#define K1 0x5a827999L +#define K2 0x6ed9eba1L +#define K3 0x8f1bbcdcL +#define K4 0xca62c1d6L + +/* Round functions. Note that F2 is the same as F4. */ +#define F1(B,C,D) ( D ^ ( B & ( C ^ D ) ) ) +#define F2(B,C,D) (B ^ C ^ D) +#define F3(B,C,D) ( ( B & C ) | ( D & ( B | C ) ) ) +#define F4(B,C,D) (B ^ C ^ D) + +/* Process LEN bytes of BUFFER, accumulating context into CTX. + It is assumed that LEN % 64 == 0. + Most of this code comes from GnuPG's cipher/sha1.c. */ + +void +sha_process_block (const void *buffer, size_t len, struct sha_ctx *ctx) +{ + const md5_uint32 *words = buffer; + size_t nwords = len / sizeof (md5_uint32); + const md5_uint32 *endp = words + nwords; + md5_uint32 x[16]; + md5_uint32 a = ctx->A; + md5_uint32 b = ctx->B; + md5_uint32 c = ctx->C; + md5_uint32 d = ctx->D; + md5_uint32 e = ctx->E; + + /* First increment the byte count. RFC 1321 specifies the possible + length of the file up to 2^64 bits. Here we only compute the + number of bytes. Do a double word increment. */ + ctx->total[0] += len; + if (ctx->total[0] < len) + ++ctx->total[1]; + +#define M(I) ( tm = x[I&0x0f] ^ x[(I-14)&0x0f] \ + ^ x[(I-8)&0x0f] ^ x[(I-3)&0x0f] \ + , (x[I&0x0f] = rol(tm, 1)) ) + +#define R(A,B,C,D,E,F,K,M) do { E += rol( A, 5 ) \ + + F( B, C, D ) \ + + K \ + + M; \ + B = rol( B, 30 ); \ + } while(0) + + while (words < endp) + { + md5_uint32 tm; + int t; + /* FIXME: see sha1.c for a better implementation. */ + for (t = 0; t < 16; t++) + { + x[t] = NOTSWAP (*words); + words++; + } + + R( a, b, c, d, e, F1, K1, x[ 0] ); + R( e, a, b, c, d, F1, K1, x[ 1] ); + R( d, e, a, b, c, F1, K1, x[ 2] ); + R( c, d, e, a, b, F1, K1, x[ 3] ); + R( b, c, d, e, a, F1, K1, x[ 4] ); + R( a, b, c, d, e, F1, K1, x[ 5] ); + R( e, a, b, c, d, F1, K1, x[ 6] ); + R( d, e, a, b, c, F1, K1, x[ 7] ); + R( c, d, e, a, b, F1, K1, x[ 8] ); + R( b, c, d, e, a, F1, K1, x[ 9] ); + R( a, b, c, d, e, F1, K1, x[10] ); + R( e, a, b, c, d, F1, K1, x[11] ); + R( d, e, a, b, c, F1, K1, x[12] ); + R( c, d, e, a, b, F1, K1, x[13] ); + R( b, c, d, e, a, F1, K1, x[14] ); + R( a, b, c, d, e, F1, K1, x[15] ); + R( e, a, b, c, d, F1, K1, M(16) ); + R( d, e, a, b, c, F1, K1, M(17) ); + R( c, d, e, a, b, F1, K1, M(18) ); + R( b, c, d, e, a, F1, K1, M(19) ); + R( a, b, c, d, e, F2, K2, M(20) ); + R( e, a, b, c, d, F2, K2, M(21) ); + R( d, e, a, b, c, F2, K2, M(22) ); + R( c, d, e, a, b, F2, K2, M(23) ); + R( b, c, d, e, a, F2, K2, M(24) ); + R( a, b, c, d, e, F2, K2, M(25) ); + R( e, a, b, c, d, F2, K2, M(26) ); + R( d, e, a, b, c, F2, K2, M(27) ); + R( c, d, e, a, b, F2, K2, M(28) ); + R( b, c, d, e, a, F2, K2, M(29) ); + R( a, b, c, d, e, F2, K2, M(30) ); + R( e, a, b, c, d, F2, K2, M(31) ); + R( d, e, a, b, c, F2, K2, M(32) ); + R( c, d, e, a, b, F2, K2, M(33) ); + R( b, c, d, e, a, F2, K2, M(34) ); + R( a, b, c, d, e, F2, K2, M(35) ); + R( e, a, b, c, d, F2, K2, M(36) ); + R( d, e, a, b, c, F2, K2, M(37) ); + R( c, d, e, a, b, F2, K2, M(38) ); + R( b, c, d, e, a, F2, K2, M(39) ); + R( a, b, c, d, e, F3, K3, M(40) ); + R( e, a, b, c, d, F3, K3, M(41) ); + R( d, e, a, b, c, F3, K3, M(42) ); + R( c, d, e, a, b, F3, K3, M(43) ); + R( b, c, d, e, a, F3, K3, M(44) ); + R( a, b, c, d, e, F3, K3, M(45) ); + R( e, a, b, c, d, F3, K3, M(46) ); + R( d, e, a, b, c, F3, K3, M(47) ); + R( c, d, e, a, b, F3, K3, M(48) ); + R( b, c, d, e, a, F3, K3, M(49) ); + R( a, b, c, d, e, F3, K3, M(50) ); + R( e, a, b, c, d, F3, K3, M(51) ); + R( d, e, a, b, c, F3, K3, M(52) ); + R( c, d, e, a, b, F3, K3, M(53) ); + R( b, c, d, e, a, F3, K3, M(54) ); + R( a, b, c, d, e, F3, K3, M(55) ); + R( e, a, b, c, d, F3, K3, M(56) ); + R( d, e, a, b, c, F3, K3, M(57) ); + R( c, d, e, a, b, F3, K3, M(58) ); + R( b, c, d, e, a, F3, K3, M(59) ); + R( a, b, c, d, e, F4, K4, M(60) ); + R( e, a, b, c, d, F4, K4, M(61) ); + R( d, e, a, b, c, F4, K4, M(62) ); + R( c, d, e, a, b, F4, K4, M(63) ); + R( b, c, d, e, a, F4, K4, M(64) ); + R( a, b, c, d, e, F4, K4, M(65) ); + R( e, a, b, c, d, F4, K4, M(66) ); + R( d, e, a, b, c, F4, K4, M(67) ); + R( c, d, e, a, b, F4, K4, M(68) ); + R( b, c, d, e, a, F4, K4, M(69) ); + R( a, b, c, d, e, F4, K4, M(70) ); + R( e, a, b, c, d, F4, K4, M(71) ); + R( d, e, a, b, c, F4, K4, M(72) ); + R( c, d, e, a, b, F4, K4, M(73) ); + R( b, c, d, e, a, F4, K4, M(74) ); + R( a, b, c, d, e, F4, K4, M(75) ); + R( e, a, b, c, d, F4, K4, M(76) ); + R( d, e, a, b, c, F4, K4, M(77) ); + R( c, d, e, a, b, F4, K4, M(78) ); + R( b, c, d, e, a, F4, K4, M(79) ); + + a = ctx->A += a; + b = ctx->B += b; + c = ctx->C += c; + d = ctx->D += d; + e = ctx->E += e; + } +} diff --git a/trunk/src/sha.h b/trunk/src/sha.h new file mode 100644 index 0000000..13583e3 --- /dev/null +++ b/trunk/src/sha.h @@ -0,0 +1,69 @@ +/* sha.h - Declaration of functions and datatypes for SHA1 sum computing + library functions. + + Copyright (C) 1999, Scott G. Miller +*/ + +#ifndef _SHA_H +# define _SHA_H 1 + +# include "md5.h" + +/* Structure to save state of computation between the single steps. */ +struct sha_ctx +{ + md5_uint32 A; + md5_uint32 B; + md5_uint32 C; + md5_uint32 D; + md5_uint32 E; + + md5_uint32 total[2]; + md5_uint32 buflen; + char buffer[128]; +}; + + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is necessary that LEN is a multiple of 64!!! */ +extern void sha_process_block (const void *buffer, size_t len, + struct sha_ctx *ctx); + +/* Starting with the result of former calls of this function (or the + initialization function update the context for the next LEN bytes + starting at BUFFER. + It is NOT required that LEN is a multiple of 64. */ +extern void sha_process_bytes (const void *buffer, size_t len, + struct sha_ctx *ctx); + +/* Initialize structure containing state of computation. */ +extern void sha_init_ctx (struct sha_ctx *ctx); + +/* Process the remaining bytes in the buffer and put result from CTX + in first 16 bytes following RESBUF. The result is always in little + endian byte order, so that a byte-wise output yields to the wanted + ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *sha_finish_ctx (struct sha_ctx *ctx, void *resbuf); + + +/* Put result from CTX in first 16 bytes following RESBUF. The result is + always in little endian byte order, so that a byte-wise output yields + to the wanted ASCII representation of the message digest. + + IMPORTANT: On some systems it is required that RESBUF is correctly + aligned for a 32 bits value. */ +extern void *sha_read_ctx (const struct sha_ctx *ctx, void *resbuf); + + +/* Compute MD5 message digest for LEN bytes beginning at BUFFER. The + result is always in little endian byte order, so that a byte-wise + output yields to the wanted ASCII representation of the message + digest. */ +extern void *sha_buffer (const char *buffer, size_t len, void *resblock); + +#endif diff --git a/trunk/src/space.c b/trunk/src/space.c new file mode 100644 index 0000000..4fea7c7 --- /dev/null +++ b/trunk/src/space.c @@ -0,0 +1,692 @@ +/* Copyright (C) 2001, 2002, 2003, 2004, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" +#include "space.h" + +#define DEBUG_SECTIONS + +#ifdef DEBUG_SECTIONS +void +print_sections (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr) +{ + int elf64 = ehdr->e_ident[EI_CLASS] == ELFCLASS64; + int i, j, shf, flag; + char buf[32], *q; + const char *p; + static struct { int sh_type; const char *type_name; } types[] = + { + { SHT_NULL, "NULL" }, + { SHT_PROGBITS, "PROGBITS" }, + { SHT_SYMTAB, "SYMTAB" }, + { SHT_STRTAB, "STRTAB" }, + { SHT_RELA, "RELA" }, + { SHT_HASH, "HASH" }, + { SHT_DYNAMIC, "DYNAMIC" }, + { SHT_NOTE, "NOTE" }, + { SHT_NOBITS, "NOBITS" }, + { SHT_REL, "REL" }, + { SHT_SHLIB, "SHLIB" }, + { SHT_DYNSYM, "DYNSYM" }, + { SHT_INIT_ARRAY, "INIT_ARRAY" }, + { SHT_FINI_ARRAY, "FINI_ARRAY" }, + { SHT_PREINIT_ARRAY, "PREINIT_ARRAY" }, + { SHT_GROUP, "GROUP" }, + { SHT_SYMTAB_SHNDX, "SYMTAB SECTION INDICIES" }, + { SHT_GNU_verdef, "VERDEF" }, + { SHT_GNU_verneed, "VERNEED" }, + { SHT_GNU_versym, "VERSYM" }, + { SHT_GNU_LIBLIST, "LIBLIST" }, + { SHT_GNU_HASH, "GNU_HASH" }, + { 0, NULL } + }; + + if (elf64) + printf (" [Nr] Name Type Address Off Size ES Flg Lk Inf Al\n"); + else + printf (" [Nr] Name Type Addr Off Size ES Flg Lk Inf Al\n"); + for (i = 0; i < ehdr->e_shnum; ++i) + { + p = NULL; + for (j = 0; types[j].type_name; ++j) + if (types[j].sh_type == shdr[i].sh_type) + { + p = types[j].type_name; + break; + } + + if (p == NULL) + { + if (shdr[i].sh_type >= SHT_LOPROC && shdr[i].sh_type <= SHT_HIPROC) + sprintf (buf, "LOPROC+%x", shdr[i].sh_type - SHT_LOPROC); + else if (shdr[i].sh_type >= SHT_LOOS && shdr[i].sh_type <= SHT_HIOS) + sprintf (buf, "LOOS+%x", shdr[i].sh_type - SHT_LOOS); + else if (shdr[i].sh_type >= SHT_LOUSER && shdr[i].sh_type <= SHT_HIUSER) + sprintf (buf, "LOUSER+%x", shdr[i].sh_type - SHT_LOUSER); + else + sprintf (buf, "Unknown: %x", shdr[i].sh_type); + p = buf; + } + + printf (" [%2d] %-17.17s %-15.15s ", i, + strptr (dso, ehdr->e_shstrndx, shdr[i].sh_name), p); + + q = buf; + shf = shdr[i].sh_flags; + while (shf) + { + flag = shf & -shf; + shf &= ~flag; + switch (flag) + { + case SHF_WRITE: *q++ = 'W'; break; + case SHF_ALLOC: *q++ = 'A'; break; + case SHF_EXECINSTR: *q++ = 'X'; break; + case SHF_MERGE: *q++ = 'M'; break; + case SHF_STRINGS: *q++ = 'S'; break; + case SHF_INFO_LINK: *q++ = 'I'; break; + case SHF_LINK_ORDER: *q++ = 'L'; break; + case SHF_OS_NONCONFORMING: *q++ = 'O'; break; + case SHF_TLS: *q++ = 'T'; break; + default: + if (flag & SHF_MASKOS) + *q++ = 'o', shf &= ~SHF_MASKOS; + else if (flag & SHF_MASKPROC) + *q++ = 'p', shf &= ~SHF_MASKPROC; + else + *q++ = 'x'; + break; + } + } + *q = '\0'; + if (elf64) + printf (" %16.16llx %6.6llx %6.6llx %2.2lx %3s %2ld %3lx %2ld\n", + (long long) shdr[i].sh_addr, (long long) shdr[i].sh_offset, + (long long) shdr[i].sh_size, (long) shdr[i].sh_entsize, + buf, (long) shdr[i].sh_link, (long) shdr[i].sh_info, + (long) shdr[i].sh_addralign); + else + printf (" %8.8lx %6.6lx %6.6lx %2.2lx %3s %2ld %3lx %2ld\n", + (long) shdr[i].sh_addr, (long) shdr[i].sh_offset, + (long) shdr[i].sh_size, (long) shdr[i].sh_entsize, + buf, (long) shdr[i].sh_link, (long) shdr[i].sh_info, + (long) shdr[i].sh_addralign); + } +} +#endif + +void +insert_readonly_section (GElf_Ehdr *ehdr, GElf_Shdr *shdr, int n, + struct readonly_adjust *adjust) +{ + int i; + + memmove (&shdr[n + 1], &shdr[n], + (ehdr->e_shnum - n) * sizeof (GElf_Shdr)); + ++ehdr->e_shnum; + for (i = 0; i < adjust->newcount; ++i) + if (adjust->new[i] >= n) + ++adjust->new[i]; +} + +int +remove_readonly_section (GElf_Ehdr *ehdr, GElf_Shdr *shdr, int n, + struct readonly_adjust *adjust) +{ + int i, ret = -1; + + memmove (&shdr[n], &shdr[n + 1], + (ehdr->e_shnum - n) * sizeof (GElf_Shdr)); + --ehdr->e_shnum; + for (i = 0; i < adjust->newcount; ++i) + if (adjust->new[i] > n) + --adjust->new[i]; + else if (adjust->new[i] == n) + { + adjust->new[i] = -1; + ret = i; + } + + return ret; +} + +static inline int +readonly_is_movable (DSO *dso, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int k) +{ + if (! (shdr[k].sh_flags & (SHF_ALLOC | SHF_WRITE))) + return 0; + + switch (shdr[k].sh_type) + { + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_DYNSYM: + case SHT_REL: + case SHT_RELA: + case SHT_STRTAB: + case SHT_NOTE: + case SHT_GNU_verdef: + case SHT_GNU_verneed: + case SHT_GNU_versym: + case SHT_GNU_LIBLIST: + return 1; + default: + if (strcmp (strptr (dso, ehdr->e_shstrndx, + shdr[k].sh_name), ".interp") == 0) + return 1; + return 0; + } +} + +int +find_readonly_space (DSO *dso, GElf_Shdr *add, GElf_Ehdr *ehdr, + GElf_Phdr *phdr, GElf_Shdr *shdr, + struct readonly_adjust *adjust) +{ + int i, j; + GElf_Addr addr; + GElf_Off p_filesz; + + if (add->sh_addr) + { + /* Prefer the current address if possible. */ + for (i = 0; i < ehdr->e_phnum; ++i) + if (phdr[i].p_type == PT_LOAD + && (phdr[i].p_flags & (PF_R | PF_W)) == PF_R + && phdr[i].p_vaddr <= add->sh_addr + && phdr[i].p_vaddr + phdr[i].p_filesz + >= add->sh_addr + add->sh_size) + break; + + if (i < ehdr->e_phnum) + for (j = 1; j < ehdr->e_shnum; ++j) + if ((shdr[j].sh_flags & SHF_ALLOC) + && shdr[j].sh_addr >= add->sh_addr) + { + if (shdr[j].sh_addr >= add->sh_addr + add->sh_size + && shdr[j - 1].sh_addr + shdr[j - 1].sh_size <= add->sh_addr) + { + insert_readonly_section (ehdr, shdr, j, adjust); + shdr[j] = *add; + shdr[j].sh_offset = (shdr[j].sh_addr - phdr[i].p_vaddr) + + phdr[i].p_offset; + return j; + } + break; + } + } + + for (i = 0; i < ehdr->e_phnum; ++i) + if (phdr[i].p_type == PT_LOAD + && (phdr[i].p_flags & (PF_R | PF_W)) == PF_R) + { + GElf_Addr start = phdr[i].p_vaddr; + int after = -1, min; + + if (phdr[i].p_offset < ehdr->e_phoff) + { + for (j = 0; j < ehdr->e_phnum; j++) + if (phdr[j].p_type == PT_PHDR + && phdr[j].p_offset == ehdr->e_phoff + && phdr[j].p_filesz >= ehdr->e_phnum * ehdr->e_phentsize) + break; + start += ehdr->e_phoff; + if (j < ehdr->e_phnum) + start += phdr[j].p_filesz; + else + start += ehdr->e_phnum * ehdr->e_phentsize; + start -= phdr[i].p_offset; + } + start = (start + add->sh_addralign - 1) & ~(add->sh_addralign - 1); + for (j = 1; j < ehdr->e_shnum; ++j) + if ((shdr[j].sh_flags & SHF_ALLOC) + && shdr[j].sh_addr >= phdr[i].p_vaddr + && shdr[j].sh_addr + shdr[j].sh_size + <= phdr[i].p_vaddr + phdr[i].p_filesz) + { + if (after == -1) + after = j - 1; + if (start + add->sh_size > shdr[j].sh_addr) + { + start = shdr[j].sh_addr + shdr[j].sh_size; + start = (start + add->sh_addralign - 1) + & ~(add->sh_addralign - 1); + after = j; + } + } + + min = -1; + for (j = i + 1; j < ehdr->e_phnum; ++j) + if (phdr[j].p_offset >= phdr[i].p_offset + phdr[i].p_filesz + && (min == -1 || phdr[min].p_offset > phdr[j].p_offset)) + min = j; + + if (after != -1 + && (start + add->sh_size <= phdr[i].p_vaddr + phdr[i].p_filesz + || (phdr[i].p_filesz == phdr[i].p_memsz + && (min == -1 + || start + add->sh_size - phdr[i].p_vaddr + <= phdr[min].p_offset)))) + { + insert_readonly_section (ehdr, shdr, after + 1, adjust); + shdr[after + 1] = *add; + shdr[after + 1].sh_addr = start; + shdr[after + 1].sh_offset = (start - phdr[i].p_vaddr) + + phdr[i].p_offset; + if (start + add->sh_size > phdr[i].p_vaddr + phdr[i].p_filesz) + { + adjust_nonalloc (dso, ehdr, shdr, 0, 0, + start + add->sh_size - phdr[i].p_vaddr + - phdr[i].p_filesz); + phdr[i].p_filesz = start + add->sh_size - phdr[i].p_vaddr; + phdr[i].p_memsz = phdr[i].p_filesz; + } + return after + 1; + } + } + + /* If SHT_NOBITS sections are small, just extend the last PT_LOAD + segment. Small enough here means that the whole .bss fits into + the same CPU page as the alloced part of it. */ + for (i = -1, j = 0; j < ehdr->e_phnum; ++j) + if (phdr[j].p_type == PT_LOAD) + i = j; + p_filesz = phdr[i].p_filesz; + + /* If we'll be converting NOBITS .plt to PROGBITS, account for that in the + calculation. */ + for (j = 1; j < ehdr->e_shnum; ++j) + { + if (shdr[j].sh_type == SHT_NOBITS + && shdr[j].sh_addr >= phdr[i].p_vaddr + && shdr[j].sh_addr + shdr[j].sh_size + <= phdr[i].p_vaddr + phdr[i].p_memsz + && !strcmp (strptr (dso, ehdr->e_shstrndx, shdr[j].sh_name), ".plt")) + { + if (shdr[j].sh_addr + shdr[j].sh_size - phdr[i].p_vaddr > p_filesz) + p_filesz = shdr[j].sh_addr + shdr[j].sh_size - phdr[i].p_vaddr; + break; + } + } + + if (phdr[i].p_filesz + && p_filesz <= phdr[i].p_memsz + && !(((phdr[i].p_vaddr + phdr[i].p_memsz - 1) + ^ (phdr[i].p_vaddr + p_filesz - 1)) & ~(dso->arch->page_size - 1))) + { + for (j = 1; j < ehdr->e_shnum; ++j) + { + if (!(shdr[j].sh_flags & (SHF_ALLOC | SHF_WRITE | SHF_ALLOC))) + break; + if (shdr[j].sh_type == SHT_NOBITS + && (shdr[j].sh_flags & SHF_TLS) == 0 + && shdr[j].sh_addr >= phdr[i].p_vaddr) + shdr[j].sh_type = SHT_PROGBITS; + } + + insert_readonly_section (ehdr, shdr, j, adjust); + shdr[j] = *add; + shdr[j].sh_addr = (shdr[j - 1].sh_addr + shdr[j - 1].sh_size + + add->sh_addralign - 1) & ~(add->sh_addralign - 1); + shdr[j].sh_offset = (shdr[j].sh_addr - phdr[i].p_vaddr) + + phdr[i].p_offset; + phdr[i].p_filesz = shdr[j].sh_addr + add->sh_size - phdr[i].p_vaddr; + phdr[i].p_memsz = phdr[i].p_filesz; + adjust_nonalloc (dso, ehdr, shdr, 0, 0, phdr[i].p_offset + + phdr[i].p_filesz - shdr[j + 1].sh_offset); + return j; + } + + /* See if we can decrease binary's base VMA and thus gain space. + This trick is mainly useful for IA-32. */ + for (i = 0; i < ehdr->e_phnum; ++i) + if (phdr[i].p_type == PT_LOAD) + break; + + addr = (add->sh_size + add->sh_addralign - 1 + phdr[i].p_align - 1) + & ~(phdr[i].p_align - 1); + if (phdr[i].p_align <= dso->arch->page_size + && phdr[i].p_flags == (PF_R | PF_X) + && phdr[i].p_filesz == phdr[i].p_memsz + && phdr[i].p_vaddr - addr + && ! (((phdr[i].p_vaddr - addr) ^ phdr[i].p_vaddr) + & ~(phdr[i].p_align * 256 - 1))) + { + int moveend; + if (! adjust->basemove_end) + { + for (moveend = 1; moveend < ehdr->e_shnum; ++moveend) + if (strcmp (strptr (dso, ehdr->e_shstrndx, + shdr[moveend].sh_name), ".interp") + && shdr[moveend].sh_type != SHT_NOTE) + break; + if (moveend < ehdr->e_shnum && moveend > 1) + { + adjust->basemove_end = shdr[moveend].sh_addr; + adjust->moveend = moveend; + } + } + else + moveend = adjust->moveend; + if (moveend < ehdr->e_shnum && moveend > 1 + && (shdr[moveend].sh_flags & (SHF_ALLOC | SHF_WRITE))) + { + int k = moveend; + GElf_Addr adj = addr; + + if (add->sh_addr && ! adjust->move2 + && phdr[i].p_vaddr <= add->sh_addr + && phdr[i].p_vaddr + phdr[i].p_filesz > add->sh_addr) + { + for (k = moveend; k < ehdr->e_shnum; ++k) + { + if (! (shdr[k].sh_flags & (SHF_ALLOC | SHF_WRITE))) + { + k = ehdr->e_shnum; + break; + } + + if (shdr[k].sh_addr > add->sh_addr) + { + /* Don't allow inserting in between reloc sections + if they are adjacent. */ + if (shdr[k].sh_type != SHT_REL + && shdr[k].sh_type != SHT_RELA) + break; + if (shdr[k - 1].sh_type != SHT_REL + && shdr[k - 1].sh_type != SHT_RELA) + break; + if (shdr[k - 1].sh_addr + shdr[k - 1].sh_size + != shdr[k].sh_addr) + break; + } + + if (! readonly_is_movable (dso, ehdr, shdr, k)) + { + k = ehdr->e_shnum; + break; + } + } + + if (k < ehdr->e_shnum) + { + GElf_Addr a; + + a = shdr[k].sh_addr; + a -= shdr[k - 1].sh_addr + shdr[k - 1].sh_size; + assert (add->sh_addralign <= phdr[i].p_align); + assert (add->sh_size > a); + a = (add->sh_size - a + phdr[i].p_align - 1) + & ~(phdr[i].p_align - 1); + if (a < adj) + { + adjust->move2 = 1; + adj = a; + } + else + k = moveend; + } + else + k = moveend; + } + + for (j = 1; j < k; ++j) + shdr[j].sh_addr -= adj; + phdr[i].p_vaddr -= adj; + phdr[i].p_paddr -= adj; + phdr[i].p_filesz += adj; + phdr[i].p_memsz += adj; + for (j = 0; j < ehdr->e_phnum; ++j) + { + if (j == i) + continue; + /* Leave STACK segment alone, it has p_vaddr == p_paddr == 0 + and p_offset == p_filesz == p_memsz == 0. */ + if (phdr[j].p_type == PT_GNU_STACK) + continue; + if (phdr[j].p_vaddr + < adjust->basemove_end - adjust->basemove_adjust) + { + phdr[j].p_vaddr -= adj; + phdr[j].p_paddr -= adj; + } + else + phdr[j].p_offset += adj; + } + adjust->basemove_adjust += adj; + insert_readonly_section (ehdr, shdr, k, adjust); + shdr[k] = *add; + if (k == moveend) + { + addr = shdr[k - 1].sh_addr + shdr[k - 1].sh_size; + addr = (addr + add->sh_addralign - 1) & ~(add->sh_addralign - 1); + } + else + { + addr = (shdr[k + 1].sh_addr - add->sh_size) + & ~(add->sh_addralign - 1); + } + + shdr[k].sh_addr = addr; + shdr[k].sh_offset = (addr - phdr[i].p_vaddr) + phdr[i].p_offset; + adjust_nonalloc (dso, ehdr, shdr, 0, 0, adj); + return k; + } + } + + /* We have to create new PT_LOAD if at all possible. */ + addr = ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize; + for (j = 1; j < ehdr->e_shnum; ++j) + { + if (addr > shdr[j].sh_offset) + { + GElf_Addr start, addstart, endaddr, *old_addr; + GElf_Addr minsize = ~(GElf_Addr) 0; + int movesec = -1, last, k, e; + + if (ehdr->e_phoff < phdr[i].p_offset + || ehdr->e_phoff + (ehdr->e_phnum + 1) * ehdr->e_phentsize + > phdr[i].p_offset + phdr[i].p_filesz + || ! readonly_is_movable (dso, ehdr, shdr, j) + || shdr[j].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz) + { + error (0, 0, "%s: No space in ELF segment table to add new ELF segment", + dso->filename); + return 0; + } + + start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff + + (ehdr->e_phnum + 1) * ehdr->e_phentsize; + for (last = 1; last < ehdr->e_shnum; ++last) + if (! readonly_is_movable (dso, ehdr, shdr, last) + || shdr[last].sh_addr >= phdr[i].p_vaddr + phdr[i].p_filesz) + break; + for (j = 1; j < last; ++j) + { + addstart = (start + add->sh_addralign - 1) + & ~(add->sh_addralign - 1); + start = (start + shdr[j].sh_addralign - 1) + & ~(shdr[j].sh_addralign - 1); + endaddr = -1; + if (j + 1 < ehdr->e_shnum) + endaddr = shdr[j + 1].sh_addr; + if (phdr[i].p_vaddr + phdr[i].p_filesz < endaddr) + endaddr = phdr[i].p_vaddr + phdr[i].p_filesz; + + switch (shdr[j].sh_type) + { + case SHT_HASH: + case SHT_GNU_HASH: + case SHT_DYNSYM: + case SHT_STRTAB: + case SHT_GNU_verdef: + case SHT_GNU_verneed: + case SHT_GNU_versym: + case SHT_GNU_LIBLIST: + if (endaddr >= start + && endaddr - start < minsize) + { + minsize = endaddr - start; + movesec = j; + } + if (endaddr > addstart + && endaddr - addstart > add->sh_size + && endaddr - addstart - add->sh_size + < minsize) + { + minsize = endaddr - addstart - add->sh_size; + movesec = j; + } + break; + } + + if (start + shdr[j].sh_size <= endaddr) + { + movesec = j + 1; + break; + } + start += shdr[j].sh_size; + } + + if (movesec == -1) + { + error (0, 0, "%s: No space in ELF segment table to add new ELF segment", + dso->filename); + return 0; + } + + start = phdr[i].p_vaddr - phdr[i].p_offset + ehdr->e_phoff + + (ehdr->e_phnum + 1) * ehdr->e_phentsize; + old_addr = (GElf_Addr *) alloca (movesec * sizeof (GElf_Addr)); + for (k = 1; k < movesec; ++k) + { + start = (start + shdr[k].sh_addralign - 1) + & ~(shdr[k].sh_addralign - 1); + old_addr[k] = shdr[k].sh_addr; + shdr[k].sh_addr = start; + shdr[k].sh_offset = start + phdr[i].p_offset + - phdr[i].p_vaddr; + start += shdr[k].sh_size; + } + + for (e = 0; e < ehdr->e_phnum; ++e) + if (phdr[e].p_type != PT_LOAD + && phdr[e].p_type != PT_GNU_STACK) + for (k = 1; k < movesec; ++k) + if (old_addr[k] == phdr[e].p_vaddr) + { + if (phdr[e].p_filesz != shdr[k].sh_size + || phdr[e].p_memsz != shdr[k].sh_size) + { + error (0, 0, "%s: Non-PT_LOAD segment spanning more than one section", + dso->filename); + return 0; + } + phdr[e].p_vaddr += shdr[k].sh_addr - old_addr[k]; + phdr[e].p_paddr += shdr[k].sh_addr - old_addr[k]; + phdr[e].p_offset += shdr[k].sh_addr - old_addr[k]; + break; + } + + if (j < last) + /* Now continue as if there was place for a new PT_LOAD + in ElfW(Phdr) table initially. */ + break; + else + { + GElf_Shdr moveshdr; + int newidx, ret, movedidx, oldidx; + + moveshdr = shdr[movesec]; + newidx = remove_readonly_section (ehdr, shdr, movesec, adjust); + oldidx = adjust->move->new_to_old[movesec]; + remove_section (adjust->move, movesec); + ret = find_readonly_space (dso, add, ehdr, phdr, shdr, adjust); + if (ret == 0) + return 0; + movedidx = find_readonly_space (dso, &moveshdr, ehdr, phdr, + shdr, adjust); + if (movedidx == 0) + return 0; + if (newidx != -1) + adjust->new[newidx] = movedidx; + add_section (adjust->move, movedidx); + if (oldidx != -1) + { + adjust->move->old_to_new[oldidx] = movedidx; + adjust->move->new_to_old[movedidx] = oldidx; + } + if (movedidx <= ret) + ++ret; + return ret; + } + } + } + + for (i = 0, j = 0; i < ehdr->e_phnum; ++i) + if (phdr[i].p_type == PT_LOAD) + j = i; + else if (phdr[i].p_type == PT_PHDR) + { + if (phdr[i].p_filesz == ehdr->e_phnum * ehdr->e_phentsize) + phdr[i].p_filesz += ehdr->e_phentsize; + if (phdr[i].p_memsz == ehdr->e_phnum * ehdr->e_phentsize) + phdr[i].p_memsz += ehdr->e_phentsize; + } + + memmove (&phdr[j + 2], &phdr[j + 1], + (ehdr->e_phnum - j - 1) * sizeof (GElf_Phdr)); + ++ehdr->e_phnum; + phdr[++j].p_type = PT_LOAD; + phdr[j].p_offset = phdr[j - 1].p_offset + phdr[j - 1].p_filesz; + phdr[j].p_offset = (phdr[j].p_offset + add->sh_addralign - 1) + & ~(add->sh_addralign - 1); + phdr[j].p_align = phdr[j - 1].p_align; + phdr[j].p_vaddr = phdr[j - 1].p_vaddr + phdr[j - 1].p_memsz; + phdr[j].p_vaddr += (phdr[j].p_align - 1); + phdr[j].p_vaddr &= ~(phdr[j].p_align - 1); + phdr[j].p_vaddr += (phdr[j].p_offset & (phdr[j].p_align - 1)); + phdr[j].p_paddr = phdr[j].p_vaddr; + /* Although the content of the segment is read-only, unless it ends on + a page boundary, we must make it writeable. This is because the rest of + the last page in the segment will be used as sbrk area which is assumed + to be writeable. */ + phdr[j].p_flags = (PF_R | PF_W); + phdr[j].p_filesz = add->sh_size; + phdr[j].p_memsz = add->sh_size; + for (i = 1; i < ehdr->e_shnum; ++i) + if (! (shdr[i].sh_flags & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR))) + break; + assert (i < ehdr->e_shnum); + insert_readonly_section (ehdr, shdr, i, adjust); + shdr[i] = *add; + shdr[i].sh_addr = phdr[j].p_vaddr; + shdr[i].sh_offset = phdr[j].p_offset; + adjust_nonalloc (dso, ehdr, shdr, 0, 0, + phdr[j].p_offset + phdr[j].p_filesz - phdr[j - 1].p_offset + - phdr[j - 1].p_filesz); + return i; +} diff --git a/trunk/src/space.h b/trunk/src/space.h new file mode 100644 index 0000000..5c9f725 --- /dev/null +++ b/trunk/src/space.h @@ -0,0 +1,39 @@ +/* Copyright (C) 2001, 2004 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef SPACE_H +#define SPACE_H + +struct readonly_adjust +{ + off_t basemove_adjust; + GElf_Addr basemove_end; + int moveend; + int move2; + int newcount, *new; + struct section_move *move; +}; + +void insert_readonly_section (GElf_Ehdr *ehdr, GElf_Shdr *shdr, int n, + struct readonly_adjust *adjust); +int remove_readonly_section (GElf_Ehdr *ehdr, GElf_Shdr *shdr, int n, + struct readonly_adjust *adjust); +int find_readonly_space (DSO *dso, GElf_Shdr *add, GElf_Ehdr *ehdr, + GElf_Phdr *phdr, GElf_Shdr *shdr, + struct readonly_adjust *adjust); + +#endif /* SPACE_H */ diff --git a/trunk/src/stabs.c b/trunk/src/stabs.c new file mode 100644 index 0000000..c0a5a6a --- /dev/null +++ b/trunk/src/stabs.c @@ -0,0 +1,188 @@ +/* Copyright (C) 2001, 2005, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <byteswap.h> +#include <endian.h> +#include <error.h> + +#include "prelink.h" + +#define N_ZERO 0x00 +#define N_GSYM 0x20 +#define N_FNAME 0x22 +#define N_FUN 0x24 +#define N_STSYM 0x26 +#define N_LCSYM 0x28 +#define N_MAIN 0x2a +#define N_BNSYM 0x2e +#define N_PC 0x30 +#define N_NSYMS 0x32 +#define N_NOMAP 0x34 +#define N_OBJ 0x38 +#define N_OPT 0x3c +#define N_RSYM 0x40 +#define N_M2C 0x42 +#define N_SLINE 0x44 +#define N_DSLINE 0x46 +#define N_BSLINE 0x48 +#define N_BROWS 0x48 +#define N_DEFD 0x4a +#define N_ENSYM 0x4e +#define N_EHDECL 0x50 +#define N_MOD2 0x50 +#define N_CATCH 0x54 +#define N_SSYM 0x60 +#define N_SO 0x64 +#define N_LSYM 0x80 +#define N_BINCL 0x82 +#define N_SOL 0x84 +#define N_PSYM 0xa0 +#define N_EINCL 0xa2 +#define N_ENTRY 0xa4 +#define N_LBRAC 0xc0 +#define N_EXCL 0xc2 +#define N_SCOPE 0xc4 +#define N_RBRAC 0xe0 +#define N_BCOMM 0xe2 +#define N_ECOMM 0xe4 +#define N_ECOML 0xe8 +#define N_LENG 0xfe + +static uint32_t +read_native (char *p) +{ + return *(uint32_t *)p; +} + +static uint32_t +read_swap (char *p) +{ + return bswap_32 (*(uint32_t *)p); +} + +static void +write_native (char *p, uint32_t v) +{ + *(uint32_t *)p = v; +} + +static void +write_swap (char *p, uint32_t v) +{ + *(uint32_t *)p = bswap_32 (v); +} + +int +adjust_stabs (DSO *dso, int n, GElf_Addr start, GElf_Addr adjust) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + off_t off; + uint32_t (*read_32) (char *p); + void (*write_32) (char *p, uint32_t v); + uint32_t value; + int sec, type; + + assert (dso->shdr[n].sh_entsize == 12); + data = elf_getdata (scn, NULL); + assert (data != NULL && data->d_buf != NULL); + assert (elf_getdata (scn, data) == NULL); + assert (data->d_off == 0 && data->d_size == dso->shdr[n].sh_size); +#if __BYTE_ORDER == __BIG_ENDIAN + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) +#elif __BYTE_ORDER == __LITTLE_ENDIAN + if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) +#else +# error Not supported host endianess +#endif + { + read_32 = read_native; + write_32 = write_native; + } +#if __BYTE_ORDER == __BIG_ENDIAN + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2LSB) +#elif __BYTE_ORDER == __LITTLE_ENDIAN + else if (dso->ehdr.e_ident[EI_DATA] == ELFDATA2MSB) +#endif + { + read_32 = read_swap; + write_32 = write_swap; + } + else + { + error (0, 0, "%s: Wrong ELF data enconding", dso->filename); + return 1; + } + + for (off = 0; off < data->d_size; off += 12) + { + switch ((type = *(uint8_t *)(data->d_buf + off + 4))) + { + case N_FUN: + /* If string is "", N_FUN is function length, otherwise + it is function start address. */ + if (read_32 (data->d_buf + off) == 0) + break; + /* FALLTHROUGH */ + case N_STSYM: + case N_LCSYM: + case N_CATCH: + case N_SO: + case N_SOL: + case N_BNSYM: + case N_ENSYM: + value = read_32 (data->d_buf + off + 8); + sec = addr_to_sec (dso, value); + if (sec != -1) + { + addr_adjust (value, start, adjust); + write_32 (data->d_buf + off + 8, value); + } + break; + /* These should be always 0. */ + case N_GSYM: + case N_BINCL: + case N_EINCL: + case N_EXCL: + case N_BCOMM: + case N_ECOMM: + /* These contain other values. */ + case N_ZERO: + case N_NSYMS: + case N_NOMAP: + case N_RSYM: + case N_LSYM: + case N_PSYM: + case N_OPT: + /* These are relative. */ + case N_LBRAC: + case N_RBRAC: + case N_SLINE: + case N_BSLINE: + case N_DSLINE: + break; + default: + error (0, 0, "%s: Unknown stabs code 0x%02x\n", dso->filename, type); + return 1; + } + } + + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + return 0; +} diff --git a/trunk/src/undo.c b/trunk/src/undo.c new file mode 100644 index 0000000..f9b0bd3 --- /dev/null +++ b/trunk/src/undo.c @@ -0,0 +1,711 @@ +/* Copyright (C) 2001, 2002, 2003, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2001. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include "prelink.h" +#include "reloc.h" + +static int +undo_prelink_rel (DSO *dso, int n) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rel rel; + int sec; + + if (dso->arch->undo_prelink_rel == NULL) + return 0; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrel (dso->elf, data, ndx, &rel); + sec = addr_to_sec (dso, rel.r_offset); + if (sec == -1) + continue; + + switch (dso->arch->undo_prelink_rel (dso, &rel, addr)) + { + case 2: + gelfx_update_rel (dso->elf, data, ndx, &rel); + break; + case 0: + break; + default: + return 1; + } + } + } + return 0; +} + +static int +undo_prelink_rela (DSO *dso, int n) +{ + Elf_Data *data = NULL; + Elf_Scn *scn = dso->scn[n]; + GElf_Rela rela; + int sec; + + if (dso->arch->undo_prelink_rela == NULL) + return 0; + while ((data = elf_getdata (scn, data)) != NULL) + { + int ndx, maxndx; + GElf_Addr addr = dso->shdr[n].sh_addr + data->d_off; + + maxndx = data->d_size / dso->shdr[n].sh_entsize; + for (ndx = 0; ndx < maxndx; + ++ndx, addr += dso->shdr[n].sh_entsize) + { + gelfx_getrela (dso->elf, data, ndx, &rela); + sec = addr_to_sec (dso, rela.r_offset); + if (sec == -1) + continue; + + switch (dso->arch->undo_prelink_rela (dso, &rela, addr)) + { + case 2: + gelfx_update_rela (dso->elf, data, ndx, &rela); + break; + case 0: + break; + default: + return 1; + } + } + } + return 0; +} + +static int +remove_dynamic_prelink_tags (DSO *dso) +{ + Elf_Data *data; + Elf_Scn *scn; + GElf_Dyn dyn; + int ndx; + + assert (dso->shdr[dso->dynamic].sh_type == SHT_DYNAMIC); + scn = dso->scn[dso->dynamic]; + data = elf_getdata (scn, NULL); + assert (elf_getdata (scn, data) == NULL); + ndx = data->d_size / dso->shdr[dso->dynamic].sh_entsize; + while (--ndx >= 0) + { + gelfx_getdyn (dso->elf, data, ndx, &dyn); + switch (dyn.d_tag) + { + case DT_NULL: + continue; + case DT_CHECKSUM: + case DT_GNU_PRELINKED: + case DT_GNU_LIBLIST: + case DT_GNU_LIBLISTSZ: + case DT_GNU_CONFLICT: + case DT_GNU_CONFLICTSZ: + dyn.d_tag = DT_NULL; + dyn.d_un.d_val = 0; + gelfx_update_dyn (dso->elf, data, ndx, &dyn); + elf_flagscn (scn, ELF_C_SET, ELF_F_DIRTY); + break; + default: + ndx = 0; + break; + } + } + return 0; +} + +int +undo_sections (DSO *dso, int undo, struct section_move *move, + struct reloc_info *rinfo, GElf_Ehdr *ehdr, + GElf_Phdr *phdr, GElf_Shdr *shdr) +{ + Elf_Data src, dst, *d; + Elf_Scn *scn; + int i, j; + + scn = dso->scn[undo]; + d = elf_getdata (scn, NULL); + assert (d != NULL && elf_getdata (scn, d) == NULL); + + src = *d; + src.d_type = ELF_T_EHDR; + src.d_align = dso->shdr[undo].sh_addralign; + src.d_size = gelf_fsize (dso->elf, ELF_T_EHDR, 1, EV_CURRENT); + dst = src; + if (src.d_size > d->d_size) + { + error (0, 0, "%s: .gnu.prelink_undo section too small", + dso->filename); + return 1; + } + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + dst.d_buf = alloca (dst.d_size); + break; + case ELFCLASS64: + dst.d_buf = ehdr; + break; + default: + return 1; + } + if (gelf_xlatetom (dso->elf, &dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Could not read .gnu.prelink_undo section", + dso->filename); + return 1; + } + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + Elf32_Ehdr *ehdr32 = (Elf32_Ehdr *) dst.d_buf; + + memcpy (ehdr->e_ident, ehdr32->e_ident, sizeof (ehdr->e_ident)); +#define COPY(name) ehdr->name = ehdr32->name + COPY (e_type); + COPY (e_machine); + COPY (e_version); + COPY (e_entry); + COPY (e_phoff); + COPY (e_shoff); + COPY (e_flags); + COPY (e_ehsize); + COPY (e_phentsize); + COPY (e_phnum); + COPY (e_shentsize); + COPY (e_shnum); + COPY (e_shstrndx); +#undef COPY + } + + if (memcmp (ehdr->e_ident, dso->ehdr.e_ident, sizeof (ehdr->e_ident)) + || ehdr->e_type != dso->ehdr.e_type + || ehdr->e_machine != dso->ehdr.e_machine + || ehdr->e_version != dso->ehdr.e_version + || ehdr->e_flags != dso->ehdr.e_flags + || ehdr->e_ehsize != dso->ehdr.e_ehsize + || ehdr->e_phentsize != dso->ehdr.e_phentsize + || ehdr->e_shentsize != dso->ehdr.e_shentsize) + { + error (0, 0, "%s: ELF headers changed since prelinking", + dso->filename); + return 1; + } + + if (ehdr->e_phnum > dso->ehdr.e_phnum) + { + error (0, 0, "%s: Number of program headers is less than before prelinking", + dso->filename); + return 1; + } + + if (d->d_size != (src.d_size + + gelf_fsize (dso->elf, ELF_T_PHDR, ehdr->e_phnum, + EV_CURRENT) + + gelf_fsize (dso->elf, ELF_T_SHDR, ehdr->e_shnum - 1, + EV_CURRENT))) + { + error (0, 0, "%s: Incorrect size of .gnu.prelink_undo section", + dso->filename); + return 1; + } + + src.d_type = ELF_T_PHDR; + src.d_buf += src.d_size; + src.d_size = gelf_fsize (dso->elf, ELF_T_PHDR, ehdr->e_phnum, EV_CURRENT); + dst = src; + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + dst.d_buf = alloca (dst.d_size); + break; + case ELFCLASS64: + dst.d_buf = phdr; + break; + } + if (gelf_xlatetom (dso->elf, &dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Could not read .gnu.prelink_undo section", + dso->filename); + return 1; + } + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + Elf32_Phdr *phdr32 = (Elf32_Phdr *) dst.d_buf; + + for (i = 0; i < ehdr->e_phnum; ++i) + { +#define COPY(name) phdr[i].name = phdr32[i].name + COPY(p_type); + COPY(p_flags); + COPY(p_offset); + COPY(p_vaddr); + COPY(p_paddr); + COPY(p_filesz); + COPY(p_memsz); + COPY(p_align); +#undef COPY + } + } + + memset (shdr, 0, sizeof (GElf_Shdr)); + src.d_type = ELF_T_SHDR; + src.d_buf += src.d_size; + src.d_size = gelf_fsize (dso->elf, ELF_T_SHDR, ehdr->e_shnum - 1, EV_CURRENT); + dst = src; + switch (gelf_getclass (dso->elf)) + { + case ELFCLASS32: + dst.d_buf = alloca (dst.d_size); + break; + case ELFCLASS64: + dst.d_buf = shdr + 1; + break; + default: + return 1; + } + if (gelf_xlatetom (dso->elf, &dst, &src, dso->ehdr.e_ident[EI_DATA]) == NULL) + { + error (0, 0, "%s: Could not read .gnu.prelink_undo section", + dso->filename); + return 1; + } + + if (gelf_getclass (dso->elf) == ELFCLASS32) + { + Elf32_Shdr *shdr32 = (Elf32_Shdr *) dst.d_buf; + + for (i = 1; i < ehdr->e_shnum; ++i) + { +#define COPY(name) shdr[i].name = shdr32[i - 1].name + COPY (sh_name); + COPY (sh_type); + COPY (sh_flags); + COPY (sh_addr); + COPY (sh_offset); + COPY (sh_size); + COPY (sh_link); + COPY (sh_info); + COPY (sh_addralign); + COPY (sh_entsize); +#undef COPY + } + } + + move->new_shnum = ehdr->e_shnum; + for (i = 1; i < move->old_shnum; ++i) + move->old_to_new[i] = -1; + for (i = 1; i < move->new_shnum; ++i) + move->new_to_old[i] = -1; + + for (i = 1; i < move->old_shnum; ++i) + { + for (j = 1; j < move->new_shnum; ++j) + if (dso->shdr[i].sh_name == shdr[j].sh_name + && dso->shdr[i].sh_type == shdr[j].sh_type + && dso->shdr[i].sh_flags == shdr[j].sh_flags + && dso->shdr[i].sh_addralign == shdr[j].sh_addralign + && dso->shdr[i].sh_entsize == shdr[j].sh_entsize + && dso->shdr[i].sh_size == shdr[j].sh_size + && move->new_to_old[j] == -1) + break; + + if (j == move->new_shnum) + continue; + + move->old_to_new[i] = j; + move->new_to_old[j] = i; + } + + for (i = 1; i < move->old_shnum; ++i) + if (move->old_to_new[i] == -1) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name); + + if (! strcmp (name, ".gnu.prelink_undo") + || ! strcmp (name, ".gnu.conflict") + || ! strcmp (name, ".gnu.liblist") + || ! strcmp (name, ".gnu.libstr") + || ((! strcmp (name, ".dynbss") || ! strcmp (name, ".sdynbss")) + && dso->ehdr.e_type == ET_EXEC)) + continue; + + if ((! strcmp (name, ".dynstr") && dso->ehdr.e_type == ET_EXEC) + || i == dso->ehdr.e_shstrndx) + { + for (j = 1; j < move->new_shnum; ++j) + if (dso->shdr[i].sh_name == shdr[j].sh_name + && dso->shdr[i].sh_type == shdr[j].sh_type + && dso->shdr[i].sh_flags == shdr[j].sh_flags + && dso->shdr[i].sh_addralign == shdr[j].sh_addralign + && dso->shdr[i].sh_entsize == shdr[j].sh_entsize + && dso->shdr[i].sh_size > shdr[j].sh_size + && move->new_to_old[j] == -1) + break; + + if (j < move->new_shnum) + { + move->old_to_new[i] = j; + move->new_to_old[j] = i; + continue; + } + } + + if (((i >= rinfo->first && i <= rinfo->last) || i == rinfo->plt) + && dso->shdr[i].sh_type == SHT_RELA) + { + for (j = 1; j < move->new_shnum; ++j) + if (dso->shdr[i].sh_name == shdr[j].sh_name + && shdr[j].sh_type == SHT_REL + && dso->shdr[i].sh_flags == shdr[j].sh_flags + && dso->shdr[i].sh_addralign == shdr[j].sh_addralign + && 2 * dso->shdr[i].sh_entsize == 3 * shdr[j].sh_entsize + && 2 * dso->shdr[i].sh_size == 3 * shdr[j].sh_size + && move->new_to_old[j] == -1) + break; + + if (j < move->new_shnum) + { + move->old_to_new[i] = j; + move->new_to_old[j] = i; + continue; + } + } + + if (! strcmp (name, ".bss") + || ! strcmp (name, ".sbss") + || (! strcmp (name, ".plt") + && dso->shdr[i].sh_type == SHT_PROGBITS)) + { + int is_plt = ! strcmp (name, ".plt"); + + for (j = 1; j < move->new_shnum; ++j) + if (dso->shdr[i].sh_name == shdr[j].sh_name + && dso->shdr[i].sh_flags == shdr[j].sh_flags + && dso->shdr[i].sh_addralign == shdr[j].sh_addralign + && (is_plt || dso->shdr[i].sh_entsize == shdr[j].sh_entsize) + && move->new_to_old[j] == -1) + { + if (is_plt) + { + if (dso->shdr[i].sh_size != shdr[j].sh_size) + continue; + if (shdr[j].sh_type == SHT_NOBITS + && dso->shdr[i].sh_entsize == shdr[j].sh_entsize) + break; + /* On Alpha prelink fixes bogus sh_entsize of .plt + sections. */ + if (shdr[j].sh_type == SHT_PROGBITS) + break; + } + else + { + const char *pname; + + if (dso->shdr[i].sh_type != shdr[j].sh_type + && (dso->shdr[i].sh_type != SHT_PROGBITS + || shdr[j].sh_type != SHT_NOBITS)) + continue; + + if (dso->shdr[i].sh_size == shdr[j].sh_size) + break; + + pname = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i - 1].sh_name); + if (strcmp (pname, ".dynbss") + && strcmp (pname, ".sdynbss")) + continue; + + if (dso->shdr[i].sh_size + dso->shdr[i - 1].sh_size + == shdr[j].sh_size) + break; + } + } + + if (j < move->new_shnum) + { + move->old_to_new[i] = j; + move->new_to_old[j] = i; + continue; + } + } + + error (0, 0, "%s: Section %s created after prelinking", + dso->filename, name); + return 1; + } + + for (i = 1; i < move->new_shnum; ++i) + if (move->new_to_old[i] == -1) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, shdr[i].sh_name); + + error (0, 0, "%s: Section %s removed after prelinking", dso->filename, + name); + return 1; + } + + return 0; +} + +int +prelink_undo (DSO *dso) +{ + GElf_Ehdr ehdr; + GElf_Shdr shdr[dso->ehdr.e_shnum + 20], old_shdr[dso->ehdr.e_shnum]; + GElf_Phdr phdr[dso->ehdr.e_phnum]; + Elf_Scn *scn; + Elf_Data *d; + int undo, i; + struct section_move *move; + struct reloc_info rinfo; + + for (undo = 1; undo < dso->ehdr.e_shnum; ++undo) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[undo].sh_name), + ".gnu.prelink_undo")) + break; + + if (undo == dso->ehdr.e_shnum) + { + if (undo_output) + return reopen_dso (dso, NULL, undo_output); + error (0, 0, "%s does not have .gnu.prelink_undo section", dso->filename); + return 1; + } + + memcpy (old_shdr, dso->shdr, sizeof (GElf_Shdr) * dso->ehdr.e_shnum); + move = init_section_move (dso); + if (move == NULL) + return 1; + + if (find_reloc_sections (dso, &rinfo)) + goto error_out; + + if (undo_sections (dso, undo, move, &rinfo, &ehdr, phdr, shdr)) + goto error_out; + + if (reopen_dso (dso, move, undo_output)) + goto error_out; + + if (find_reloc_sections (dso, &rinfo)) + goto error_out; + + for (i = 1; i < dso->ehdr.e_shnum; i++) + { + if (! (dso->shdr[i].sh_flags & SHF_ALLOC)) + continue; + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name), + ".gnu.conflict")) + continue; + switch (dso->shdr[i].sh_type) + { + case SHT_REL: + if (undo_prelink_rel (dso, i)) + goto error_out; + break; + case SHT_RELA: + if (undo_prelink_rela (dso, i)) + goto error_out; + break; + } + } + + if (dso->arch->arch_undo_prelink && dso->arch->arch_undo_prelink (dso)) + goto error_out; + + if (dso->ehdr.e_type == ET_DYN) + { + GElf_Addr adjust = 0, diff; + + for (i = dso->ehdr.e_shnum - 1; i > 0; --i) + if (shdr[i].sh_flags & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + { + adjust = shdr[i].sh_addr - dso->shdr[i].sh_addr; + break; + } + while (i > 0) + { + int nsec = 1, j; + /* Change here PROGBITS .plt into NOBITS if needed. */ + + /* Convert RELA to REL if needed. */ + if (dso->shdr[i].sh_type == SHT_RELA && shdr[i].sh_type == SHT_REL) + { + assert (dso->arch->rela_to_rel != NULL); + if (i == rinfo.plt) + { + if (convert_rela_to_rel (dso, i)) + goto error_out; + dso->shdr[i].sh_size = shdr[i].sh_size; + } + else if (i == rinfo.last) + { + GElf_Addr start = dso->shdr[rinfo.first].sh_addr; + + for (j = rinfo.first; j <= rinfo.last; ++j) + { + if (convert_rela_to_rel (dso, j)) + goto error_out; + dso->shdr[j].sh_addr = start; + dso->shdr[j].sh_size = shdr[j].sh_size; + start += dso->shdr[j].sh_size; + } + nsec = rinfo.last - rinfo.first + 1; + i = rinfo.first; + } + else + { + error (0, 0, "%s: Cannot convert RELA to REL", dso->filename); + goto error_out; + } + } + diff = shdr[i].sh_addr - dso->shdr[i].sh_addr; + if (diff != adjust) + { + assert (diff >= adjust); + if (adjust_dso (dso, dso->shdr[i + nsec].sh_addr, adjust - diff)) + goto error_out; + adjust = diff; + } + --i; + } + if (adjust && adjust_dso (dso, 0, adjust)) + goto error_out; + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (shdr[i].sh_flags & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + assert (shdr[i].sh_addr == dso->shdr[i].sh_addr); + } + else + { + /* Executable. */ + for (i = 1; i < dso->ehdr.e_shnum; ++i) + { + const char *name = strptr (dso, dso->ehdr.e_shstrndx, + dso->shdr[i].sh_name); + + if (dso->shdr[i].sh_type == SHT_PROGBITS + && shdr[i].sh_type == SHT_NOBITS) + { + assert (strcmp (name, ".bss") == 0 + || strcmp (name, ".sbss") == 0 + || strcmp (name, ".plt") == 0); + scn = dso->scn[i]; + d = elf_getdata (scn, NULL); + assert (d != NULL && elf_getdata (scn, d) == NULL); + assert (d->d_size == 0 || d->d_buf != NULL); + assert (d->d_size == dso->shdr[i].sh_size); + free (d->d_buf); + d->d_buf = NULL; + dso->shdr[i].sh_type = SHT_NOBITS; + } + else if (dso->shdr[i].sh_type == SHT_RELA + && shdr[i].sh_type == SHT_REL) + { + if (convert_rela_to_rel (dso, i)) + goto error_out; + dso->shdr[i].sh_size = shdr[i].sh_size; + } + else + assert (dso->shdr[i].sh_type == shdr[i].sh_type); + if (dso->shdr[i].sh_size != shdr[i].sh_size) + { + /* This is handled in code below for both ET_DYN and ET_EXEC. */ + if (i == dso->ehdr.e_shstrndx) + continue; + assert (shdr[i].sh_type == SHT_NOBITS + || shdr[i].sh_size < dso->shdr[i].sh_size); + assert (strcmp (name, ".dynstr") == 0 + || strcmp (name, ".bss") == 0 + || strcmp (name, ".sbss") == 0); + scn = dso->scn[i]; + d = elf_getdata (scn, NULL); + assert (d != NULL && elf_getdata (scn, d) == NULL); + d->d_size = shdr[i].sh_size; + } + } + + if (update_dynamic_tags (dso, shdr, old_shdr, move)) + goto error_out; + + for (i = 1; i < dso->ehdr.e_shnum; ++i) + if (shdr[i].sh_flags & (SHF_WRITE | SHF_ALLOC | SHF_EXECINSTR)) + dso->shdr[i].sh_addr = shdr[i].sh_addr; + } + + /* Clear .dynamic entries added by prelink, update others. */ + if (remove_dynamic_prelink_tags (dso) + || update_dynamic_rel (dso, &rinfo)) + goto error_out; + + /* Shrink .shstrtab. */ + i = dso->ehdr.e_shstrndx; + if (shdr[i].sh_size < dso->shdr[i].sh_size) + { + scn = dso->scn[i]; + d = elf_getdata (scn, NULL); + assert (d != NULL && elf_getdata (scn, d) == NULL); + assert (d->d_size == dso->shdr[i].sh_size); + d->d_size = shdr[i].sh_size; + } + + /* Now restore the rest. */ + for (i = 1; i < dso->ehdr.e_shnum; ++i) + dso->shdr[i] = shdr[i]; + if (dso->ehdr.e_phnum != ehdr.e_phnum) + { + assert (ehdr.e_phnum < dso->ehdr.e_phnum); + if (gelf_newphdr (dso->elf, ehdr.e_phnum) == 0) + { + error (0, 0, "Could not create new ELF headers"); + goto error_out; + } + } + for (i = 0; i < ehdr.e_phnum; ++i) + dso->phdr[i] = phdr[i]; + dso->permissive = 1; + assert (dso->ehdr.e_entry == ehdr.e_entry); + assert (dso->ehdr.e_shnum == ehdr.e_shnum); + assert (dso->ehdr.e_shstrndx == ehdr.e_shstrndx); + dso->ehdr.e_phoff = ehdr.e_phoff; + dso->ehdr.e_shoff = ehdr.e_shoff; + dso->ehdr.e_phnum = ehdr.e_phnum; + free (move); + return 0; + +error_out: + free (move); + return 1; +} diff --git a/trunk/src/undoall.c b/trunk/src/undoall.c new file mode 100644 index 0000000..90e9240 --- /dev/null +++ b/trunk/src/undoall.c @@ -0,0 +1,173 @@ +/* Copyright (C) 2002, 2005 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <alloca.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <string.h> +#include <sys/stat.h> +#include <time.h> +#include <unistd.h> +#include "prelinktab.h" + +static int +undo_one (void **p, void *info) +{ + struct prelink_entry *ent = * (struct prelink_entry **) p; + DSO *dso; + struct stat64 st; + struct prelink_link *hardlink; + char *move = NULL; + size_t movelen = 0; + + if (ent->done != 2) + return 1; + + if (ent->type != ET_DYN + && (ent->type != ET_EXEC || libs_only)) + return 1; + + dso = open_dso (ent->canon_filename); + if (dso == NULL) + goto error_out; + + if (fstat64 (dso->fd, &st) < 0) + { + error (0, errno, "%s changed during prelinking", ent->filename); + goto error_out; + } + + if (st.st_dev != ent->dev || st.st_ino != ent->ino) + { + error (0, 0, "%s changed during prelinking", ent->filename); + goto error_out; + } + + if (verbose) + { + if (dry_run) + printf ("Would undo %s\n", ent->canon_filename); + else + printf ("Undoing %s\n", ent->canon_filename); + } + + if (prelink_undo (dso)) + goto error_out; + + if (dry_run) + close_dso (dso); + else + { + if (update_dso (dso, NULL)) + { + dso = NULL; + goto error_out; + } + } + + dso = NULL; + + /* Redo hardlinks. */ + for (hardlink = ent->hardlink; hardlink; hardlink = hardlink->next) + { + size_t len; + + if (wrap_lstat64 (hardlink->canon_filename, &st) < 0) + { + error (0, 0, "Could not stat %s (former hardlink to %s)", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (st.st_dev != ent->dev || st.st_ino != ent->ino) + { + error (0, 0, "%s is no longer hardlink to %s", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (verbose) + { + if (dry_run) + printf ("Would link %s to %s\n", hardlink->canon_filename, + ent->canon_filename); + else + printf ("Linking %s to %s\n", hardlink->canon_filename, + ent->canon_filename); + } + + len = strlen (hardlink->canon_filename); + if (len + sizeof (".#prelink#") > movelen) + { + movelen = len + sizeof (".#prelink#"); + move = realloc (move, movelen); + if (move == NULL) + { + error (0, ENOMEM, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + movelen = 0; + continue; + } + } + + memcpy (mempcpy (move, hardlink->canon_filename, len), ".#prelink#", + sizeof (".#prelink#")); + if (wrap_rename (hardlink->canon_filename, move) < 0) + { + error (0, errno, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + continue; + } + + if (wrap_link (ent->canon_filename, hardlink->canon_filename) < 0) + { + error (0, errno, "Could not hardlink %s to %s", + hardlink->canon_filename, ent->canon_filename); + + if (wrap_rename (move, hardlink->canon_filename) < 0) + { + error (0, errno, "Could not rename %s back to %s", + move, hardlink->canon_filename); + } + continue; + } + + if (wrap_unlink (move) < 0) + { + error (0, errno, "Could not unlink %s", move); + continue; + } + } + free (move); + return 1; + +error_out: + if (dso) + close_dso (dso); + (*(int *)info)++; + return 1; +} + +int +undo_all (void) +{ + int failures = 0; + htab_traverse (prelink_filename_htab, undo_one, &failures); + return failures != 0; +} diff --git a/trunk/src/verify.c b/trunk/src/verify.c new file mode 100644 index 0000000..8acecfb --- /dev/null +++ b/trunk/src/verify.c @@ -0,0 +1,442 @@ +/* Copyright (C) 2002, 2003, 2006 Red Hat, Inc. + Written by Jakub Jelinek <jakub@redhat.com>, 2002. + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <endian.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> +#include <time.h> +#include <unistd.h> +#include <sys/mman.h> +#include "prelink.h" +#include "md5.h" +#include "sha.h" + +static ssize_t +send_file (int outfd, int infd, off_t *poff, size_t count) +{ + char buf[65536], *b, *p, *q; + size_t todo = count, len; + ssize_t n; + + b = mmap (NULL, count, PROT_READ, MAP_PRIVATE, infd, *poff); + if (b != MAP_FAILED) + { + p = b; + q = p + count; + while (p != q) + { + n = TEMP_FAILURE_RETRY (write (outfd, p, q - p)); + if (n < 0) + { + munmap (b, count); + return -1; + } + p += n; + } + munmap (b, count); + return count; + } + + if (lseek (infd, *poff, SEEK_SET) != *poff) + return -1; + while (todo > 0) + { + len = todo > sizeof (buf) ? sizeof (buf) : todo; + p = buf; + q = buf + len; + while (p != q) + { + n = TEMP_FAILURE_RETRY (read (infd, p, q - p)); + if (n < 0) + return -1; + p += n; + } + p = buf; + while (p != q) + { + n = TEMP_FAILURE_RETRY (write (outfd, p, q - p)); + if (n < 0) + return -1; + p += n; + } + todo -= len; + } + return count; +} + +static int +checksum_file (int fd, size_t count, + void (*sum) (const void *, size_t, void *), void *arg) +{ + char buf[65536+64], *b, *p, *q; + size_t todo = count, len; + ssize_t n; + + b = mmap (NULL, count, PROT_READ, MAP_PRIVATE, fd, 0); + if (b != MAP_FAILED) + { + sum (b, count, arg); + munmap (b, count); + return 0; + } + + b = (char *) (((uintptr_t) buf + 63) & ~(uintptr_t) 63); + while (todo > 0) + { + len = todo > 65536 ? 65536 : todo; + p = b; + q = b + len; + while (p != q) + { + n = TEMP_FAILURE_RETRY (read (fd, p, q - p)); + if (n < 0) + return 1; + p += n; + } + sum (b, len, arg); + todo -= len; + } + return 0; +} + +static int +handle_verify (int fd, const char *filename) +{ + off_t off; + size_t cnt; + struct stat64 st; + + if (fstat64 (fd, &st) < 0) + { + error (0, errno, "%s: couldn't fstat temporary file", filename); + return 1; + } + + if (verify_method == VERIFY_CONTENT) + { + off = 0; + if (send_file (1, fd, &off, st.st_size) != st.st_size) + { + error (0, errno, "Couldn't write file to standard output"); + return 1; + } + } + else if (verify_method == VERIFY_MD5) + { + struct md5_ctx ctx; + unsigned char bin_buffer[16]; + + md5_init_ctx (&ctx); + if (checksum_file (fd, st.st_size, + (void (*) (const void *, size_t, void *)) + md5_process_bytes, &ctx)) + { + error (0, errno, "%s: Couldn't read temporary file", filename); + return 1; + } + + md5_finish_ctx (&ctx, bin_buffer); + for (cnt = 0; cnt < 16; ++cnt) + printf ("%02x", bin_buffer[cnt]); + printf (" %s\n", filename); + } + else if (verify_method == VERIFY_SHA) + { + struct sha_ctx ctx; + unsigned char bin_buffer[20]; + + sha_init_ctx (&ctx); + if (checksum_file (fd, st.st_size, + (void (*) (const void *, size_t, void *)) + sha_process_bytes, &ctx)) + { + error (0, errno, "%s: Couldn't read temporary file", filename); + return 1; + } + + sha_finish_ctx (&ctx, bin_buffer); + for (cnt = 0; cnt < 20; ++cnt) + printf ("%02x", bin_buffer[cnt]); + printf (" %s\n", filename); + } + return 0; +} + +int +prelink_verify (const char *filename) +{ + DSO *dso = NULL, *dso2 = NULL; + int fd = -1, fdorig = -1, fdundone = -1, undo, ret; + struct stat64 st, st2; + struct prelink_entry *ent; + GElf_Addr base; + char buffer[32768], buffer2[32768]; + size_t count; + char *p, *q; + + if (wrap_stat64 (filename, &st) < 0) + error (EXIT_FAILURE, errno, "Couldn't stat %s", filename); + + dso = open_dso (filename); + if (dso == NULL) + goto not_prelinked; + + if (dso->ehdr.e_type != ET_DYN && dso->ehdr.e_type != ET_EXEC) + { + error (0, 0, "%s is not an ELF shared library nor binary", filename); + goto not_prelinked; + } + + for (undo = 1; undo < dso->ehdr.e_shnum; ++undo) + if (! strcmp (strptr (dso, dso->ehdr.e_shstrndx, dso->shdr[undo].sh_name), + ".gnu.prelink_undo")) + break; + + if (undo == dso->ehdr.e_shnum) + goto not_prelinked; + + if (fstat64 (dso->fd, &st2) < 0) + { + error (0, errno, "Couldn't fstat %s", filename); + goto failure; + } + + if (st.st_dev != st2.st_dev || st.st_ino != st2.st_ino + || st.st_size != st2.st_size) + { + error (0, 0, "%s: changed during --verify", filename); + goto failure; + } + + if (gather_config (prelink_conf)) + goto failure; + + if (gather_object (filename, 0, 0)) + goto failure; + + ent = prelink_find_entry (filename, &st, 0); + if (ent == NULL) + { + error (0, 0, "%s disappeared while running --verify", filename); + goto failure; + } + + if (ent->done != 2) + { + error (0, 0, "%s: at least one of file's dependencies has changed since prelinking", + filename); + goto failure; + } + + base = dso->base; + ent->base = base; + + ret = prelink_undo (dso); + if (ret) + goto failure; + + switch (write_dso (dso)) + { + case 2: + error (0, 0, "Could not write temporary for %s: %s", filename, + elf_errmsg (-1)); + goto failure; + case 1: + goto failure; + case 0: + break; + } + + fd = wrap_open (dso->temp_filename, O_RDONLY); + if (fd < 0) + { + error (0, errno, "Could not verify %s", filename); + goto failure; + } + + fdorig = dup (dso->fdro); + if (fdorig < 0) + { + error (0, errno, "Could not verify %s", filename); + goto failure; + } + + ent->filename = dso->temp_filename; + dso->temp_filename = NULL; + close_dso (dso); + dso = NULL; + + fchmod (fd, 0700); + + dso2 = fdopen_dso (fd, filename); + if (dso2 == NULL) + goto failure_unlink; + fd = -1; + + if (prelink_prepare (dso2)) + goto failure_unlink; + + if (ent->type == ET_DYN && relocate_dso (dso2, base)) + goto failure_unlink; + + if (prelink (dso2, ent)) + goto failure_unlink; + + unlink (ent->filename); + + if (write_dso (dso2)) + goto failure; + + fd = dup (dso2->fd); + if (fd < 0) + { + error (0, errno, "Could not verify %s", filename); + goto failure; + } + + fdundone = dup (dso2->fdro); + if (fdundone < 0) + { + error (0, errno, "Could not verify %s", filename); + goto failure; + } + + close_dso (dso2); + dso2 = NULL; + + if (fstat64 (fdorig, &st2) < 0) + { + error (0, errno, "Couldn't fstat %s", filename); + goto failure; + } + + if (st.st_dev != st2.st_dev || st.st_ino != st2.st_ino + || st.st_size != st2.st_size) + { + error (0, 0, "%s: changed during --verify", filename); + goto failure; + } + + if (fstat64 (fd, &st2) < 0) + { + error (0, errno, "Couldn't fstat temporary file"); + goto failure; + } + + if (st.st_size != st2.st_size) + { + error (0, 0, "%s: prelinked file size differs", filename); + goto failure; + } + + q = MAP_FAILED; + p = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fdorig, 0); + if (p != MAP_FAILED) + { + q = mmap (NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); + if (q == MAP_FAILED) + { + munmap (p, st.st_size); + p = MAP_FAILED; + } + } + if (p != MAP_FAILED) + { + int ret = memcmp (p, q, st.st_size); + + munmap (p, st.st_size); + munmap (q, st.st_size); + if (ret != 0) + { + error (0, 0, "%s: prelinked file was modified", filename); + goto failure; + } + } + else + { + if (lseek (fdorig, 0, SEEK_SET) != 0 + || lseek (fd, 0, SEEK_SET) != 0) + { + error (0, errno, "%s: couldn't seek to start of files", filename); + goto failure; + } + + count = st.st_size; + while (count > 0) + { + size_t len = sizeof (buffer); + + if (len > count) + len = count; + if (read (fdorig, buffer, len) != len) + { + error (0, errno, "%s: couldn't read file", filename); + goto failure; + } + if (read (fd, buffer2, len) != len) + { + error (0, errno, "%s: couldn't read temporary file", filename); + goto failure; + } + if (memcmp (buffer, buffer2, len) != 0) + { + error (0, 0, "%s: prelinked file was modified", filename); + goto failure; + } + count -= len; + } + } + + if (handle_verify (fdundone, filename)) + goto failure; + + close (fd); + close (fdorig); + close (fdundone); + return 0; + +failure_unlink: + unlink (ent->filename); +failure: + if (fd != -1) + close (fd); + if (fdorig != -1) + close (fdorig); + if (fdundone != -1) + close (fdundone); + if (dso) + close_dso (dso); + if (dso2) + close_dso (dso2); + return EXIT_FAILURE; + +not_prelinked: + if (dso) + close_dso (dso); + fd = wrap_open (filename, O_RDONLY); + if (fd < 0) + error (EXIT_FAILURE, errno, "Couldn't open %s", filename); + if (handle_verify (fd, filename)) + return EXIT_FAILURE; + close (fd); + return 0; +} diff --git a/trunk/src/wrap-file.c b/trunk/src/wrap-file.c new file mode 100644 index 0000000..c631458 --- /dev/null +++ b/trunk/src/wrap-file.c @@ -0,0 +1,536 @@ +/* Copyright (C) 2003 MontaVista Software, Inc. + Written by Daniel Jacobowitz <drow@mvista.com>, 2003. + + The chroot_canon function is copied from the GNU C Library, + elf/chroot-canon.c, also licensed under the GPL: + Copyright (C) 1996,1997,1998,1999,2000,2001 Free Software Foundation, Inc. + [and then further modified.] + + 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, 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#include <config.h> +#include <assert.h> +#include <errno.h> +#include <error.h> +#include <fcntl.h> +#include <ftw.h> +#include <stdarg.h> +#include <stddef.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/time.h> +#include <time.h> +#include <unistd.h> +#include <utime.h> +#include "prelink.h" + +#ifndef PATH_MAX +#define PATH_MAX 1024 +#endif + +#ifndef MAXSYMLINKS +#define MAXSYMLINKS 20 +#endif + +/* Return the canonical absolute name of file NAME as if chroot(CHROOT) was + done first. A canonical name does not contain any `.', `..' components + nor any repeated path separators ('/') or symlinks. All path components + must exist and NAME must be absolute filename. The result is malloc'd. + The returned name includes the CHROOT prefix. + + If ALLOW_LAST_LINK, then symlinks in the last component won't be + resolved. */ + +static char * +chroot_canon_filename (const char * chroot, const char *name, int allow_last_link, struct stat64 *stp) +{ + char *rpath, *dest, *extra_buf = NULL; + char *rpath_root; + const char *start, *end, *rpath_limit; + long int path_max; + int num_links = 0; + int stp_initialized = 0; + size_t chroot_len = 0; + + if (name == NULL) + { + errno = EINVAL; + return NULL; + } + + if (name[0] == '\0') + { + errno = ENOENT; + return NULL; + } + + if (chroot == NULL) + { + errno = EINVAL; + return NULL; + } + + chroot_len = strlen (chroot); + +#ifdef PATH_MAX + path_max = PATH_MAX; +#else + path_max = pathconf (name, _PC_PATH_MAX); + if (path_max <= 0) + path_max = 1024; +#endif + + rpath = malloc (chroot_len + path_max); + if (rpath == NULL) + return NULL; + rpath_limit = rpath + chroot_len + path_max; + + rpath_root = (char *) mempcpy (rpath, chroot, chroot_len) - 1; + if (*rpath_root != '/') + *++rpath_root = '/'; + dest = rpath_root + 1; + + for (start = end = name; *start; start = end) + { + int n; + + /* Skip sequence of multiple path-separators. */ + while (*start == '/') + ++start; + + /* Find end of path component. */ + for (end = start; *end && *end != '/'; ++end) + /* Nothing. */; + + if (end - start == 0) + break; + else if (end - start == 1 && start[0] == '.') + /* nothing */; + else if (end - start == 2 && start[0] == '.' && start[1] == '.') + { + /* Back up to previous component, ignore if at root already. */ + if (dest > rpath_root + 1) + while ((--dest)[-1] != '/'); + stp_initialized = 0; + } + else + { + size_t new_size; + + if (dest[-1] != '/') + *dest++ = '/'; + + if (dest + (end - start) >= rpath_limit) + { + ptrdiff_t dest_offset = dest - rpath; + char *new_rpath; + + new_size = rpath_limit - rpath; + if (end - start + 1 > path_max) + new_size += end - start + 1; + else + new_size += path_max; + new_rpath = (char *) realloc (rpath, new_size); + if (new_rpath == NULL) + goto error; + rpath = new_rpath; + rpath_limit = rpath + new_size; + + dest = rpath + dest_offset; + } + + dest = mempcpy (dest, start, end - start); + *dest = '\0'; + + if (lstat64 (rpath, stp) < 0) + goto error; + + stp_initialized = 1; + + if (allow_last_link && *end == '\0') + goto done; + + if (S_ISLNK (stp->st_mode)) + { + char *buf = alloca (path_max); + size_t len; + + if (++num_links > MAXSYMLINKS) + { + errno = ELOOP; + goto error; + } + + n = readlink (rpath, buf, path_max); + if (n < 0) + goto error; + buf[n] = '\0'; + + if (!extra_buf) + extra_buf = alloca (path_max); + + len = strlen (end); + if ((long int) (n + len) >= path_max) + { + errno = ENAMETOOLONG; + goto error; + } + + /* Careful here, end may be a pointer into extra_buf... */ + memmove (&extra_buf[n], end, len + 1); + name = end = memcpy (extra_buf, buf, n); + + if (buf[0] == '/') + dest = rpath_root + 1; /* It's an absolute symlink */ + else + /* Back up to previous component, ignore if at root already: */ + if (dest > rpath_root + 1) + while ((--dest)[-1] != '/'); + } + else if (!S_ISDIR (stp->st_mode) && *end != '\0') + { + errno = ENOTDIR; + goto error; + } + } + } +done: + if (dest > rpath_root + 1 && dest[-1] == '/') + --dest; + *dest = '\0'; + + if (!stp_initialized && lstat64 (rpath, stp) < 0) + goto error; + + if (dest + 1 - rpath <= (rpath_limit - rpath) / 2) + { + char *new_rpath = realloc (rpath, dest + 1 - rpath); + + if (new_rpath != NULL) + return new_rpath; + } + return rpath; + +error: + free (rpath); + return NULL; +} + + +const char *sysroot; + +static char * +sysroot_file_name (const char *name, int allow_last_link, struct stat64 *stp) +{ + char *ret; + struct stat64 st; + + if (sysroot == NULL || name == NULL) + return (char *) name; + + if (name[0] != '/') + { + char *tmpname = malloc (strlen (name) + 2); + strcpy (tmpname, "/"); + strcat (tmpname, name); + ret = chroot_canon_filename (sysroot, tmpname, allow_last_link, stp ? stp : &st); + free (tmpname); + } + else + ret = chroot_canon_filename (sysroot, name, allow_last_link, stp ? stp : &st); + + if (ret == NULL) + { + char *ret_root; + + ret = malloc(strlen(sysroot) + strlen(name) + 1); + ret_root = mempcpy(ret, sysroot, strlen(sysroot)); + ret_root = mempcpy(ret_root, name, strlen(name)); + *ret_root='\0'; + } + return ret; +} + +static char * +unsysroot_file_name (const char *name) +{ + if (name == NULL) + return (char *)name; + + if (sysroot) + { + int sysroot_len = strlen (sysroot); + if (strncmp (name, sysroot, sysroot_len) == 0) + { + if (name[sysroot_len] == '/') + return strdup (name + sysroot_len); + else if (name[sysroot_len] == 0) + return strdup ("/"); + } + } + return (char *)name; +} + +char * +wrap_prelink_canonicalize (const char *name, struct stat64 *stp) +{ + if (sysroot) + { + struct stat64 st; + char *tmpname; + char *ret; + + /* Use chroot_canon_filename because we want a NULL return if it doesn't exist! */ + tmpname = chroot_canon_filename (sysroot, name, 0, stp ? stp : &st); + + if (tmpname == NULL) + return NULL; + + ret = unsysroot_file_name (tmpname); + + if (ret == tmpname) + ret = strdup (ret); + + if (tmpname != name) + free (tmpname); + + return ret; + } + else + return prelink_canonicalize(name, stp); +} + +int +wrap_lstat64 (const char *file, struct stat64 *buf) +{ + char *tmpname = sysroot_file_name (file, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = lstat64 (tmpname, buf); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_stat64 (const char *file, struct stat64 *buf) +{ + char* file_copy; + char *tmpname; + int ret; + int len; + + tmpname = sysroot_file_name (file, 0, NULL); + + if (tmpname == NULL) + return -1; + + file_copy = strdup (tmpname); + + if (tmpname != file) + free (tmpname); + + if (file_copy == NULL) + return -1; + + len = strlen (file_copy); + if (file_copy[len - 1] == '/') + file_copy[len - 1] = '\0'; + + ret = stat64 (file_copy, buf); + + free (file_copy); + + return ret; +} + +int +wrap_rename (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = rename (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +int +wrap_open (const char *name, int mode, ...) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + if (mode & O_CREAT) + { + va_list va; + int flags; + va_start (va, mode); + flags = va_arg (va, int); + va_end (va); + ret = open (tmpname, mode, flags); + } + else + ret = open (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_access (const char *name, int mode) +{ + char *tmpname = sysroot_file_name (name, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = access (tmpname, mode); + + if (tmpname != name) + free (tmpname); + return ret; +} + +int +wrap_link (const char *old, const char *new) +{ + char *tmpold = sysroot_file_name (old, 1, NULL); + char *tmpnew; + int ret; + + if (tmpold == NULL) + return -1; + + tmpnew = sysroot_file_name (new, 1, NULL); + if (tmpnew == NULL) + return -1; + + ret = link (tmpold, tmpnew); + + if (tmpold != old) + free (tmpold); + if (tmpnew != new) + free (tmpnew); + return ret; +} + +/* Note that this isn't recursive safe, since nftw64 doesn't + pass an opaque object around to use. But that fits our needs + for now. */ + +static __nftw64_func_t nftw64_cur_func; + +static int +wrap_nftw64_func (const char *filename, const struct stat64 *status, + int flag, struct FTW *info) +{ + char *tmpname = unsysroot_file_name (filename); + int ret = nftw64_cur_func (tmpname, status, flag, info); + + if (tmpname != filename) + free (tmpname); + return ret; +} + +int +wrap_nftw64 (const char *dir, __nftw64_func_t func, + int descriptors, int flag) +{ + char *tmpdir = sysroot_file_name (dir, 1, NULL); + int ret; + + if (tmpdir == NULL) + return -1; + + nftw64_cur_func = func; + ret = nftw64 (tmpdir, wrap_nftw64_func, descriptors, flag); + + if (tmpdir != dir) + free (tmpdir); + return ret; +} + +int +wrap_utime (const char *file, struct utimbuf *file_times) +{ + char *tmpname = sysroot_file_name (file, 0, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = utime (tmpname, file_times); + + if (tmpname != file) + free (tmpname); + return ret; +} + +int +wrap_mkstemp (char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = mkstemp (tmpname); + + if (tmpname != filename) + { + strcpy (filename, tmpname + strlen (sysroot)); + free (tmpname); + } + return ret; +} + +int +wrap_unlink (const char *filename) +{ + char *tmpname = sysroot_file_name (filename, 1, NULL); + int ret; + + if (tmpname == NULL) + return -1; + + ret = unlink (tmpname); + + if (tmpname != filename) + free (tmpname); + return ret; +} diff --git a/trunk/stamp-h.in b/trunk/stamp-h.in new file mode 100644 index 0000000..9788f70 --- /dev/null +++ b/trunk/stamp-h.in @@ -0,0 +1 @@ +timestamp diff --git a/trunk/testsuite/Makefile.am b/trunk/testsuite/Makefile.am new file mode 100644 index 0000000..3af929b --- /dev/null +++ b/trunk/testsuite/Makefile.am @@ -0,0 +1,56 @@ +## Process this file with automake to create Makefile.in + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall + +TESTS = movelibs.sh \ + reloc1.sh reloc2.sh reloc3.sh reloc4.sh reloc5.sh reloc6.sh \ + reloc7.sh reloc8.sh reloc9.sh reloc10.sh reloc11.sh \ + shuffle1.sh shuffle2.sh shuffle3.sh shuffle4.sh shuffle5.sh \ + shuffle6.sh shuffle7.sh shuffle8.sh undo1.sh \ + layout1.sh layout2.sh \ + tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \ + cxx1.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \ + deps1.sh deps2.sh \ + undosyslibs.sh +TESTS_ENVIRONMENT = \ + PRELINK="../src/prelink -c ./prelink.conf -C ./prelink.cache --ld-library-path=. --dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + CC="$(CC) $(LINKOPTS)" CCLINK="$(CC) -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + CXX="$(CXX) $(LINKOPTS)" CXXLINK="$(CXX) -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + $(SHELL) + +extra_DIST = $(TESTS) functions.sh + +CLEANFILES = *.so *.so.* *.nop syslib.list syslnk.list prelink.cache prelink.conf \ + $(TESTS:%.sh=%) $(TESTS:%.sh=%.log) $(TESTS:%.sh=%.lds) \ + *.orig *.new core* *.\#prelink\#* tlstest *.first *.second + +clean-am: clean-dirs + +clean-dirs: + rm -rf *.tree + +.NOTPARALLEL: + +check-cycle: + @optlist=.; \ + if [ "`uname -m | sed s/i.86/i.86/`" = i.86 ]; then \ + optlist="--no-exec-shield --exec-shield"; \ + fi; \ + for opts2 in $$optlist; do \ + for opts in -v -vm -vR -vmR; do \ + PRELINK_OPTS="$$opts"; \ + [ $$opts2 != . ] && PRELINK_OPTS="$$opts $$opts2"; \ + echo "Checking with $$PRELINK_OPTS"; \ + PRELINK_OPTS="$$PRELINK_OPTS" $(MAKE) $(AM_MAKEFLAGS) check || exit; \ + $(MAKE) $(AM_MAKEFLAGS) clean || exit; \ + done; \ + done; \ + echo "Checking with -Wl,-z,nocombreloc"; \ + LINKOPTS=-Wl,-z,nocombreloc $(MAKE) $(AM_MAKEFLAGS) check || exit; \ + $(MAKE) $(AM_MAKEFLAGS) clean || exit + +check-harder: + @CHECK_ME_HARDER=1 $(MAKE) $(AM_MAKEFLAGS) check || exit diff --git a/trunk/testsuite/Makefile.in b/trunk/testsuite/Makefile.in new file mode 100644 index 0000000..205f6e3 --- /dev/null +++ b/trunk/testsuite/Makefile.in @@ -0,0 +1,344 @@ +# Makefile.in generated by automake 1.6.3 from Makefile.am. +# @configure_input@ + +# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002 +# Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + +@SET_MAKE@ +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_DATA = @INSTALL_DATA@ +install_sh_DATA = $(install_sh) -c -m 644 +install_sh_PROGRAM = $(install_sh) -c +install_sh_SCRIPT = $(install_sh) -c +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_HEADER = $(INSTALL_DATA) +transform = @program_transform_name@ +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ + +EXEEXT = @EXEEXT@ +OBJEXT = @OBJEXT@ +PATH_SEPARATOR = @PATH_SEPARATOR@ +AMTAR = @AMTAR@ +AR = @AR@ +AS = @AS@ +AWK = @AWK@ +CC = @CC@ +CPP = @CPP@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +DEPDIR = @DEPDIR@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EGREP = @EGREP@ +F77 = @F77@ +GCJ = @GCJ@ +GCJFLAGS = @GCJFLAGS@ +GELFINCLUDE = @GELFINCLUDE@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LIBGELF = @LIBGELF@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +OBJDUMP = @OBJDUMP@ +PACKAGE = @PACKAGE@ +RANLIB = @RANLIB@ +RC = @RC@ +STRIP = @STRIP@ +VERSION = @VERSION@ +am__include = @am__include@ +am__quote = @am__quote@ +install_sh = @install_sh@ + +AUTOMAKE_OPTIONS = 1.4 gnu + +DEFS = -D_GNU_SOURCE -DHAVE_CONFIG_H -Wall +AM_CFLAGS = -Wall + +TESTS = movelibs.sh \ + reloc1.sh reloc2.sh reloc3.sh reloc4.sh reloc5.sh reloc6.sh \ + reloc7.sh reloc8.sh reloc9.sh reloc10.sh reloc11.sh \ + shuffle1.sh shuffle2.sh shuffle3.sh shuffle4.sh shuffle5.sh \ + shuffle6.sh shuffle7.sh shuffle8.sh undo1.sh \ + layout1.sh layout2.sh \ + tls1.sh tls2.sh tls3.sh tls4.sh tls5.sh tls6.sh tls7.sh \ + cxx1.sh quick1.sh quick2.sh quick3.sh cycle1.sh cycle2.sh \ + deps1.sh deps2.sh \ + undosyslibs.sh + +TESTS_ENVIRONMENT = \ + PRELINK="../src/prelink -c ./prelink.conf -C ./prelink.cache --ld-library-path=. --dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + CC="$(CC) $(LINKOPTS)" CCLINK="$(CC) -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + CXX="$(CXX) $(LINKOPTS)" CXXLINK="$(CXX) -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`" \ + $(SHELL) + + +extra_DIST = $(TESTS) functions.sh + +CLEANFILES = *.so *.so.* *.nop syslib.list syslnk.list prelink.cache prelink.conf \ + $(TESTS:%.sh=%) $(TESTS:%.sh=%.log) $(TESTS:%.sh=%.lds) \ + *.orig *.new core* *.\#prelink\#* tlstest *.first *.second + +subdir = testsuite +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +DIST_SOURCES = +DIST_COMMON = Makefile.am Makefile.in +all: all-am + +.SUFFIXES: +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && \ + $(AUTOMAKE) --gnu testsuite/Makefile +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + -rm -f libtool +uninstall-info-am: +tags: TAGS +TAGS: + + +check-TESTS: $(TESTS) + @failed=0; all=0; xfail=0; xpass=0; \ + srcdir=$(srcdir); export srcdir; \ + list='$(TESTS)'; \ + if test -n "$$list"; then \ + for tst in $$list; do \ + if test -f ./$$tst; then dir=./; \ + elif test -f $$tst; then dir=; \ + else dir="$(srcdir)/"; fi; \ + $(TESTS_ENVIRONMENT) $${dir}$$tst; \ + ret=$$?; \ + if test $$ret -eq 0; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xpass=`expr $$xpass + 1`; \ + failed=`expr $$failed + 1`; \ + echo "XPASS: $$tst"; \ + ;; \ + *) \ + echo "PASS: $$tst"; \ + ;; \ + esac; \ + elif test $$ret -ne 77; then \ + all=`expr $$all + 1`; \ + case " $(XFAIL_TESTS) " in \ + *" $$tst "*) \ + xfail=`expr $$xfail + 1`; \ + echo "XFAIL: $$tst ($$ret)"; \ + ;; \ + *) \ + failed=`expr $$failed + 1`; \ + echo "FAIL: $$tst ($$ret)"; \ + ;; \ + esac; \ + fi; \ + done; \ + if test "$$failed" -eq 0; then \ + if test "$$xfail" -eq 0; then \ + banner="All $$all tests passed"; \ + else \ + banner="All $$all tests behaved as expected ($$xfail expected failures)"; \ + fi; \ + else \ + if test "$$xpass" -eq 0; then \ + banner="$$failed of $$all tests failed"; \ + else \ + banner="$$failed of $$all tests did not behave as expected ($$xpass unexpected passes)"; \ + fi; \ + fi; \ + dashes=`echo "$$banner" | sed s/./=/g`; \ + echo "$$dashes"; \ + echo "$$banner"; \ + echo "$$dashes"; \ + test "$$failed" -eq 0; \ + else :; fi +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) + +top_distdir = .. +distdir = $(top_distdir)/$(PACKAGE)-$(VERSION) + +distdir: $(DISTFILES) + @list='$(DISTFILES)'; for file in $$list; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test "$$dir" != "$$file" && test "$$dir" != "."; then \ + dir="/$$dir"; \ + $(mkinstalldirs) "$(distdir)$$dir"; \ + else \ + dir=''; \ + fi; \ + if test -d $$d/$$file; then \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \ + fi; \ + cp -pR $$d/$$file $(distdir)$$dir || exit 1; \ + else \ + test -f $(distdir)/$$file \ + || cp -p $$d/$$file $(distdir)/$$file \ + || exit 1; \ + fi; \ + done +check-am: all-am + $(MAKE) $(AM_MAKEFLAGS) check-TESTS +check: check-am +all-am: Makefile + +installdirs: + +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ + INSTALL_STRIP_FLAG=-s \ + `test -z '$(STRIP)' || \ + echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install +mostlyclean-generic: + +clean-generic: + -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES) + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + +distclean-am: clean-am distclean-generic distclean-libtool + +dvi: dvi-am + +dvi-am: + +info: info-am + +info-am: + +install-data-am: + +install-exec-am: + +install-info: install-info-am + +install-man: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-generic mostlyclean-libtool + +uninstall-am: uninstall-info-am + +.PHONY: all all-am check check-TESTS check-am clean clean-generic \ + clean-libtool distclean distclean-generic distclean-libtool \ + distdir dvi dvi-am info info-am install install-am install-data \ + install-data-am install-exec install-exec-am install-info \ + install-info-am install-man install-strip installcheck \ + installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-generic \ + mostlyclean-libtool uninstall uninstall-am uninstall-info-am + + +clean-am: clean-dirs + +clean-dirs: + rm -rf *.tree + +.NOTPARALLEL: + +check-cycle: + @optlist=.; \ + if [ "`uname -m | sed s/i.86/i.86/`" = i.86 ]; then \ + optlist="--no-exec-shield --exec-shield"; \ + fi; \ + for opts2 in $$optlist; do \ + for opts in -v -vm -vR -vmR; do \ + PRELINK_OPTS="$$opts"; \ + [ $$opts2 != . ] && PRELINK_OPTS="$$opts $$opts2"; \ + echo "Checking with $$PRELINK_OPTS"; \ + PRELINK_OPTS="$$PRELINK_OPTS" $(MAKE) $(AM_MAKEFLAGS) check || exit; \ + $(MAKE) $(AM_MAKEFLAGS) clean || exit; \ + done; \ + done; \ + echo "Checking with -Wl,-z,nocombreloc"; \ + LINKOPTS=-Wl,-z,nocombreloc $(MAKE) $(AM_MAKEFLAGS) check || exit; \ + $(MAKE) $(AM_MAKEFLAGS) clean || exit + +check-harder: + @CHECK_ME_HARDER=1 $(MAKE) $(AM_MAKEFLAGS) check || exit +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/trunk/testsuite/cxx1.C b/trunk/testsuite/cxx1.C new file mode 100644 index 0000000..9c11a6d --- /dev/null +++ b/trunk/testsuite/cxx1.C @@ -0,0 +1,26 @@ +#include "cxx1.h" +extern "C" void abort (void); + +void +check (A *x, B *y) +{ + C d; + if (x->b () != 21) + abort (); + if (y->B::a () != 22) + abort (); + if (d.a () != 23) + abort (); + if (d.C::b () != 24) + abort (); +} + +int +main () +{ + A x; + if (x.a () != 20) + abort (); + do_check (check, &x); + return 0; +} diff --git a/trunk/testsuite/cxx1.h b/trunk/testsuite/cxx1.h new file mode 100644 index 0000000..d6efe9b --- /dev/null +++ b/trunk/testsuite/cxx1.h @@ -0,0 +1,19 @@ +struct A + { + virtual int a (); + virtual int b (); + int c; + }; +struct B + { + virtual int a (); + int b; + }; +struct C + { + virtual int a (); + virtual int b (); + int c; + }; + +void do_check (void (*check) (A *x, B *y), A *x); diff --git a/trunk/testsuite/cxx1.sh b/trunk/testsuite/cxx1.sh new file mode 100755 index 0000000..81428c2 --- /dev/null +++ b/trunk/testsuite/cxx1.sh @@ -0,0 +1,20 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f cxx1 cxx1lib*.so cxx1.log +rm -f prelink.cache +$CXX -shared -O2 -fpic -o cxx1lib1.so $srcdir/cxx1lib1.C +$CXX -shared -O2 -fpic -o cxx1lib2.so $srcdir/cxx1lib2.C cxx1lib1.so +BINS="cxx1" +LIBS="cxx1lib1.so cxx1lib2.so" +$CXXLINK -o cxx1 $srcdir/cxx1.C -Wl,--rpath-link,. cxx1lib2.so +savelibs +echo $PRELINK -vvvv ${PRELINK_OPTS--vm} ./cxx1 > cxx1.log +$PRELINK -vvvv ${PRELINK_OPTS--vm} ./cxx1 >> cxx1.log 2>&1 || exit 1 +grep ^`echo $PRELINK | sed 's/ .*$/: /'` cxx1.log | grep -q -v 'C++ conflict' && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./cxx1 || exit 3 +fi +readelf -a ./cxx1 >> cxx1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./cxx1 +comparelibs >> cxx1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/cxx1lib1.C b/trunk/testsuite/cxx1lib1.C new file mode 100644 index 0000000..1eb192a --- /dev/null +++ b/trunk/testsuite/cxx1lib1.C @@ -0,0 +1,34 @@ +#include "cxx1.h" + +int A::a () +{ + return 10; +} + +int A::b () +{ + return 11; +} + +int B::a () +{ + return 12; +} + +int C::a () +{ + return 13; +} + +int C::b () +{ + return 14; +} + +void +do_check (void (*check) (A *x, B *y), A *x) +{ + B y; + + check (x, &y); +} diff --git a/trunk/testsuite/cxx1lib2.C b/trunk/testsuite/cxx1lib2.C new file mode 100644 index 0000000..77055da --- /dev/null +++ b/trunk/testsuite/cxx1lib2.C @@ -0,0 +1,28 @@ +#include "cxx1.h" + +int A::a () +{ + return 20; +} + +int A::b () +{ + return 21; +} + +int B::a () +{ + return 22; +} + +int C::a () +{ + return 23; +} + +int C::b () +{ + return 24; +} + +C c; diff --git a/trunk/testsuite/cycle1.sh b/trunk/testsuite/cycle1.sh new file mode 100755 index 0000000..caf7864 --- /dev/null +++ b/trunk/testsuite/cycle1.sh @@ -0,0 +1,25 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f cycle1 cycle1lib*.so cycle1.log +rm -f prelink.cache +# Test whether prelink doesn't segfault or loop endlessly on +# bogus library dependency chains +echo 'int foo;' | $CC -shared -O2 -fpic -o cycle1lib1.so -xc - +echo 'int bar;' | $CC -shared -O2 -fpic -o cycle1lib2.so -xc - -xnone cycle1lib1.so +echo 'int foo;' | $CC -shared -O2 -fpic -o cycle1lib1.so -xc - -xnone cycle1lib2.so +BINS="cycle1" +LIBS="cycle1lib1.so cycle1lib2.so" +echo 'int main (void) { return 0; } ' \ + | $CCLINK -o cycle1 -xc - -xnone -Wl,--rpath-link,. cycle1lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./cycle1 > cycle1.log +$PRELINK ${PRELINK_OPTS--vm} ./cycle1 >> cycle1.log 2>&1 || exit 1 +grep -v 'has a dependency cycle' cycle1.log \ + | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 +grep -q "^`echo $PRELINK | sed 's/ .*$/: .*has a dependency cycle/'`" \ + cycle1.log || exit 3 +if [ "x$CROSS" = "x" ] ; then + LD_LIBRARY_PATH=. ./cycle1 || exit 4 +fi +# So that it is not prelinked again +chmod -x ./cycle1 diff --git a/trunk/testsuite/cycle2.sh b/trunk/testsuite/cycle2.sh new file mode 100755 index 0000000..a160a3a --- /dev/null +++ b/trunk/testsuite/cycle2.sh @@ -0,0 +1,28 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f cycle2 cycle2lib*.so cycle2.log +rm -f prelink.cache +# Test whether prelink doesn't segfault or loop endlessly on +# bogus library dependency chains +echo 'int i1;' | $CC -shared -O2 -fpic -o cycle2lib1.so -xc - +echo 'int i2;' | $CC -shared -O2 -fpic -o cycle2lib2.so -xc - -xnone cycle2lib1.so +echo 'int i3;' | $CC -shared -O2 -fpic -o cycle2lib3.so -xc - -xnone cycle2lib2.so +echo 'int i4;' | $CC -shared -O2 -fpic -o cycle2lib4.so -xc - -xnone cycle2lib3.so +echo 'int i5;' | $CC -shared -O2 -fpic -o cycle2lib5.so -xc - -xnone cycle2lib4.so +echo 'int i1;' | $CC -shared -O2 -fpic -o cycle2lib1.so -xc - -xnone cycle2lib5.so +BINS="cycle2" +LIBS="cycle2lib1.so cycle2lib2.so cycle2lib3.so cycle2lib4.so cycle2lib5.so" +echo 'int main (void) { return 0; } ' \ + | $CCLINK -o cycle2 -xc - -xnone -Wl,--rpath-link,. cycle2lib5.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./cycle2 > cycle2.log +$PRELINK ${PRELINK_OPTS--vm} ./cycle2 >> cycle2.log 2>&1 || exit 1 +grep -v 'has a dependency cycle' cycle2.log \ + | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 +grep -q "^`echo $PRELINK | sed 's/ .*$/: .*has a dependency cycle/'`" \ + cycle2.log || exit 3 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./cycle2 || exit 4 +fi +# So that it is not prelinked again +chmod -x ./cycle2 diff --git a/trunk/testsuite/deps1.c b/trunk/testsuite/deps1.c new file mode 100644 index 0000000..331546c --- /dev/null +++ b/trunk/testsuite/deps1.c @@ -0,0 +1,18 @@ +#include "reloc1.h" +#include <stdlib.h> + +static struct A local = { 77, &local, &bar + 4 }; + +int main() +{ + if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26) + abort (); + if (f1 () != 1 || f2 () != 2) + abort (); + local.c -= 4; + if (local.a != 77 || local.b != &local || local.c != &bar) + abort (); + if (f8 () != 17) + abort (); + exit (0); +} diff --git a/trunk/testsuite/deps1.h b/trunk/testsuite/deps1.h new file mode 100644 index 0000000..d5868f7 --- /dev/null +++ b/trunk/testsuite/deps1.h @@ -0,0 +1,4 @@ +#include "reloc1.h" + +extern int f8 (void); +extern int f9 (void); diff --git a/trunk/testsuite/deps1.sh b/trunk/testsuite/deps1.sh new file mode 100755 index 0000000..96395fa --- /dev/null +++ b/trunk/testsuite/deps1.sh @@ -0,0 +1,60 @@ +#!/bin/bash +. `dirname $0`/functions.sh + +PRELINK=`echo $PRELINK \ + | sed -e 's, \./\(prelink\.\(cache\|conf\)\), deps1.tree/etc/\1,g' \ + -e 's,path=\.,path=deps1.tree/lib:deps1.tree/usr/lib:deps1.tree/opt/lib,' \ + -e 's,linker=\./,linker=deps1.tree/lib/,'` +CCLINK=`echo $CCLINK \ + | sed -e 's,linker=\./,linker=deps1.tree/lib/,'` +rm -rf deps1.tree +rm -f deps1.log +mkdir -p deps1.tree/{lib,etc,usr/lib,opt/lib,usr/bin} +$CC -shared -O2 -fpic -o deps1.tree/usr/lib/lib1.so $srcdir/deps1lib1.c +$CC -shared -O2 -fpic -o deps1.tree/opt/lib/lib1.so $srcdir/deps1lib1.c +$CC -shared -O2 -fpic -o deps1.tree/usr/lib/lib2.so $srcdir/deps1lib2.c \ + -L deps1.tree/opt/lib -Wl,-rpath,deps1.tree/opt/lib -l1 +echo '' | $CC -shared -O2 -fpic -o deps1.tree/usr/lib/lib3.so -xc - -xnone \ + -L deps1.tree/usr/lib -L deps1.tree/opt/lib -Wl,-rpath,deps1.tree/usr/lib \ + -l1 -l2 +for lib in `cat syslib.list`; do + cp -p $lib.orig deps1.tree/lib/$lib + cp -p $lib.orig deps1.tree/lib/$lib.orig +done +for lib in `cat syslnk.list`; do + cp -dp $lib deps1.tree/lib +done +$CCLINK -o deps1.tree/usr/bin/bin1 $srcdir/deps1.c \ + -Wl,-rpath,deps1.tree/usr/lib -L deps1.tree/usr/lib -l3 +cat > deps1.tree/etc/prelink.conf <<EOF +deps1.tree/usr/bin +deps1.tree/lib +deps1.tree/usr/lib +deps1.tree/opt/lib +EOF +LIBS="deps1.tree/usr/lib/lib1.so deps1.tree/usr/lib/lib2.so" +LIBS="$LIBS deps1.tree/usr/lib/lib3.so deps1.tree/opt/lib/lib1.so" +LIBS="$LIBS `sed 's|^|deps1.tree/lib/|' syslib.list`" +BINS="deps1.tree/usr/bin/bin1" +savelibs +chmod 644 `ls $BINS | sed 's|$|.orig|'` +echo $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps1.log +$PRELINK ${PRELINK_OPTS--v} -avvvvv > deps1.tree/etc/log1 2>&1 || exit 1 +cat deps1.tree/etc/log1 >> deps1.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=deps1.tree/lib deps1.tree/usr/bin/bin1 || exit 2 +fi +readelf -d deps1.tree/{usr,opt}/lib/lib1.so 2>&1 | grep CHECKSUM >> deps1.log || exit 3 +readelf -A deps1.tree/usr/lib/lib1.so >> deps1.log 2>&1 || exit 4 +readelf -A deps1.tree/opt/lib/lib1.so >> deps1.log 2>&1 || exit 5 +readelf -A deps1.tree/usr/lib/lib2.so >> deps1.log 2>&1 || exit 6 +readelf -A deps1.tree/usr/lib/lib3.so >> deps1.log 2>&1 || exit 7 +readelf -A deps1.tree/usr/bin/bin1 >> deps1.log 2>&1 || exit 8 +LIBS="deps1.tree/usr/lib/lib1.so deps1.tree/usr/lib/lib2.so" +LIBS="$LIBS deps1.tree/opt/lib/lib1.so" +readelf -S deps1.tree/usr/lib/lib3.so | grep -q .gnu.prelink_undo \ + && LIBS="$LIBS deps1.tree/usr/lib/lib3.so" +readelf -S deps1.tree/usr/bin/bin1 | grep -q .gnu.prelink_undo \ + || BINS= +comparelibs >> deps1.log 2>&1 || exit 8 +exit 0 diff --git a/trunk/testsuite/deps1lib1.c b/trunk/testsuite/deps1lib1.c new file mode 100644 index 0000000..d4ab28b --- /dev/null +++ b/trunk/testsuite/deps1lib1.c @@ -0,0 +1,21 @@ +#include "deps1.h" + +int bar = 26; +int baz = 28; + +struct A foo = { 1, &foo, &bar }; + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return f1 () + 1; +} + +int f9 (void) +{ + return 18; +} diff --git a/trunk/testsuite/deps1lib2.c b/trunk/testsuite/deps1lib2.c new file mode 100644 index 0000000..f73b456 --- /dev/null +++ b/trunk/testsuite/deps1lib2.c @@ -0,0 +1,11 @@ +#include "reloc1.h" + +int f1 (void) +{ + return 11; +} + +int f8 (void) +{ + return f9 () - 1; +} diff --git a/trunk/testsuite/deps2.sh b/trunk/testsuite/deps2.sh new file mode 100755 index 0000000..4838f9b --- /dev/null +++ b/trunk/testsuite/deps2.sh @@ -0,0 +1,57 @@ +#!/bin/bash +. `dirname $0`/functions.sh + +PRELINK=`echo $PRELINK \ + | sed -e 's, \./\(prelink\.\(cache\|conf\)\), deps2.tree/etc/\1,g' \ + -e 's,path=\.,path=deps2.tree/lib:deps2.tree/usr/lib:deps2.tree/opt/lib,' \ + -e 's,linker=\./,linker=deps2.tree/lib/,'` +CCLINK=`echo $CCLINK \ + | sed -e 's,linker=\./,linker=deps2.tree/lib/,'` +rm -rf deps2.tree +rm -f deps2.log +mkdir -p deps2.tree/{lib,etc,usr/lib,opt/lib,usr/bin} +$CC -shared -O2 -fpic -o deps2.tree/usr/lib/lib1.so $srcdir/deps1lib1.c +$CC -shared -O2 -fpic -o deps2.tree/opt/lib/lib1.so $srcdir/deps2lib1.c +$CC -shared -O2 -fpic -o deps2.tree/usr/lib/lib2.so $srcdir/deps1lib2.c \ + -L deps2.tree/opt/lib -Wl,-rpath,deps2.tree/opt/lib -l1 +echo '' | $CC -shared -O2 -fpic -o deps2.tree/usr/lib/lib3.so -xc - -xnone \ + -L deps2.tree/usr/lib -L deps2.tree/opt/lib -Wl,-rpath,deps2.tree/usr/lib \ + -l1 -l2 +for lib in `cat syslib.list`; do + cp -p $lib.orig deps2.tree/lib/$lib + cp -p $lib.orig deps2.tree/lib/$lib.orig +done +for lib in `cat syslnk.list`; do + cp -dp $lib deps2.tree/lib +done +$CCLINK -o deps2.tree/usr/bin/bin1 $srcdir/deps1.c \ + -Wl,-rpath,deps2.tree/usr/lib -L deps2.tree/usr/lib -l3 +cat > deps2.tree/etc/prelink.conf <<EOF +deps2.tree/usr/bin +deps2.tree/lib +deps2.tree/usr/lib +deps2.tree/opt/lib +EOF +LIBS="deps2.tree/usr/lib/lib1.so deps2.tree/usr/lib/lib2.so" +LIBS="$LIBS deps2.tree/usr/lib/lib3.so deps2.tree/opt/lib/lib1.so" +LIBS="$LIBS `sed 's|^|deps2.tree/lib/|' syslib.list`" +BINS="deps2.tree/usr/bin/bin1" +savelibs +chmod 644 `ls $BINS | sed 's|$|.orig|'` +echo $PRELINK ${PRELINK_OPTS--v} -avvvvv > deps2.log +$PRELINK ${PRELINK_OPTS--v} -avvvvv > deps2.tree/etc/log1 2>&1 || exit 1 +cat deps2.tree/etc/log1 >> deps2.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=deps2.tree/lib deps2.tree/usr/bin/bin1 || exit 2 +fi +readelf -d deps2.tree/{usr,opt}/lib/lib1.so 2>&1 | grep CHECKSUM >> deps2.log || exit 3 +readelf -A deps2.tree/usr/lib/lib1.so >> deps2.log 2>&1 || exit 4 +readelf -A deps2.tree/opt/lib/lib1.so >> deps2.log 2>&1 || exit 5 +readelf -A deps2.tree/usr/lib/lib2.so >> deps2.log 2>&1 || exit 6 +readelf -A deps2.tree/usr/lib/lib3.so >> deps2.log 2>&1 || exit 7 +readelf -A deps2.tree/usr/bin/bin1 >> deps2.log 2>&1 || exit 8 +LIBS="deps2.tree/usr/lib/lib1.so deps2.tree/usr/lib/lib2.so" +LIBS="$LIBS deps2.tree/opt/lib/lib1.so" +BINS= +comparelibs >> deps2.log 2>&1 || exit 9 +exit 0 diff --git a/trunk/testsuite/deps2lib1.c b/trunk/testsuite/deps2lib1.c new file mode 100644 index 0000000..9d4b2de --- /dev/null +++ b/trunk/testsuite/deps2lib1.c @@ -0,0 +1,26 @@ +#include "deps1.h" + +int bar = 26; +int baz = 28; + +struct A foo = { 1, &foo, &bar }; + +int f0 (void) +{ + return f1 () + f2 () + f9 () + bar + baz; +} + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return f1 () + 1; +} + +int f9 (void) +{ + return 18; +} diff --git a/trunk/testsuite/functions.sh b/trunk/testsuite/functions.sh new file mode 100755 index 0000000..c351fd1 --- /dev/null +++ b/trunk/testsuite/functions.sh @@ -0,0 +1,26 @@ +#!/bin/bash +CC="${CC:-gcc} ${LINKOPTS}" +CCLINK=${CCLINK:-${CC} -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`} +CXX="${CXX:-g++} ${LINKOPTS}" +CXXLINK=${CXXLINK:-${CXX} -Wl,--dynamic-linker=`echo ./ld*.so.*[0-9]`} +PRELINK=${PRELINK:-../src/prelink -c ./prelink.conf -C ./prelink.cache --ld-library-path=. --dynamic-linker=`echo ./ld*.so.*[0-9]`} +LDD=${LDD:-../src/prelink-rtld} +STRIP=${STRIP:-strip} +HOST_CC=${HOST_CC:-$CC} +srcdir=${srcdir:-`dirname $0`} +savelibs() { + for i in $LIBS $BINS; do cp -p $i $i.orig; done +} +comparelibs() { + for i in $LIBS $BINS; do + cp -p $i $i.new + echo $PRELINK -u $i.new + $PRELINK -u $i.new || exit + cmp -s $i.orig $i.new || exit + rm -f $i.new + echo $PRELINK -y $i \> $i.new + $PRELINK -y $i > $i.new || exit + cmp -s $i.orig $i.new || exit + rm -f $i.new + done +} diff --git a/trunk/testsuite/layout.C b/trunk/testsuite/layout.C new file mode 100644 index 0000000..5047a34 --- /dev/null +++ b/trunk/testsuite/layout.C @@ -0,0 +1,3 @@ +int main() +{ +} diff --git a/trunk/testsuite/layout1.sh b/trunk/testsuite/layout1.sh new file mode 100755 index 0000000..e217dea --- /dev/null +++ b/trunk/testsuite/layout1.sh @@ -0,0 +1,24 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f prelink.cache +rm -f layout1 layoutlib*.so layout1.log +i=10 +BINS="layout1" +LIBS= +while [ $i -lt 74 ]; do + $CXX -shared -fpic -o layout1lib$i.so $srcdir/layoutlib.C + LIBS="$LIBS layout1lib$i.so" + i=`expr $i + 1` +done +$CXXLINK -o layout1 $srcdir/layout.C layout1lib*.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vR} ./layout1 > layout1.log +$PRELINK ${PRELINK_OPTS--vR} ./layout1 >> layout1.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` layout1.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./layout1 || exit 3 +fi +readelf -a ./layout1 >> layout1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./layout1 +comparelibs >> layout1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/layout2.sh b/trunk/testsuite/layout2.sh new file mode 100755 index 0000000..2307a42 --- /dev/null +++ b/trunk/testsuite/layout2.sh @@ -0,0 +1,23 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f layout2 layout2lib*.so layout2.log +i=1 +BINS="layout2" +LIBS= +while [ $i -lt 6 ]; do + $CXX -shared -fpic -o layout2lib$i.so $srcdir/layoutlib.C + LIBS="$LIBS layout2lib$i.so" + i=`expr $i + 1` +done +$CXXLINK -o layout2 $srcdir/layout.C layout2lib*.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vR} ./layout2 > layout2.log +$PRELINK ${PRELINK_OPTS--vR} ./layout2 >> layout2.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` layout2.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./layout2 || exit 3 +fi +readelf -a ./layout2 >> layout2.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./layout2 +comparelibs >> layout2.log 2>&1 || exit 5 diff --git a/trunk/testsuite/layoutlib.C b/trunk/testsuite/layoutlib.C new file mode 100644 index 0000000..8162515 --- /dev/null +++ b/trunk/testsuite/layoutlib.C @@ -0,0 +1,10 @@ +struct A + { + virtual int a(); + int b; + }; + +int A::a() +{ + return 10; +} diff --git a/trunk/testsuite/movelibs.sh b/trunk/testsuite/movelibs.sh new file mode 100755 index 0000000..010e0e7 --- /dev/null +++ b/trunk/testsuite/movelibs.sh @@ -0,0 +1,35 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# This script copies needed C and C++ libraries into the test directory +echo 'int main() { }' > movelibs.C +$CXX -o movelibs movelibs.C +> syslib.list +> syslnk.list +for i in `RTLD_TRACE_PRELINKING=1 LD_WARN= $LDD ./movelibs \ + | awk '$1 !~ /^\.\/movelibs/ { print $3 } '`; do + k=`basename $i` + if [ -L $i ]; then + j=`ls -l $i | sed 's/^.* -> //'` + if echo $j | grep / >/dev/null 2>&1; then + cp -p $i . + echo $k >> syslib.list + else + cp -dp $i . + cp -p `dirname $i`/$j . + echo $j >> syslib.list + echo $k >> syslnk.list + fi + else + cp -p $i . + echo $k >> syslib.list + fi +done +rm -f movelibs.C movelibs +pwd > prelink.conf +for i in `cat syslib.list`; do + if readelf -WS $i 2>/dev/null | grep -q .gnu.prelink_undo; then + $PRELINK -u $i > /dev/null 2>&1 || exit 1 + fi + cp -p $i $i.orig +done +exit 77 diff --git a/trunk/testsuite/quick1.c b/trunk/testsuite/quick1.c new file mode 100644 index 0000000..dc98441 --- /dev/null +++ b/trunk/testsuite/quick1.c @@ -0,0 +1,21 @@ +#include "reloc1.h" +#include <stdlib.h> + +static struct A local = { 77, &local, &bar + 4 }; +extern int baz; +static char *bazp0 = (char *) &baz; +static char *bazp1 = ((char *) &baz) + 1; + +int main() +{ + if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + local.c -= 4; + if (local.a != 77 || local.b != &local || local.c != &bar) + abort (); + if (bazp1 - bazp0 != 1) + abort (); + exit (0); +} diff --git a/trunk/testsuite/quick1.sh b/trunk/testsuite/quick1.sh new file mode 100755 index 0000000..f3f80a8 --- /dev/null +++ b/trunk/testsuite/quick1.sh @@ -0,0 +1,212 @@ +#!/bin/bash +. `dirname $0`/functions.sh +check_one() { + cnt=0 + log=$1 + echo -n . >> quick1.log + text="$2" + shift 2 + while [ $# -gt 0 ]; do + grep -q "^$text .*$1" $log || exit 40 + cnt=$((++cnt)) + shift + done + [ `grep "^$text " $log | wc -l` = $cnt ] || exit 41 +} +check_log() { + log=$1 + echo -n "Checking $1 " >> quick1.log + check_one $log 'Checking executable' $CHECKE + check_one $log 'Checking shared library' $CHECKL + check_one $log 'Assuming prelinked' $ASSUME + check_one $log 'Prelinking' $PREL + echo >> quick1.log +} + +PRELINK=`echo $PRELINK \ + | sed -e 's, \./\(prelink\.\(cache\|conf\)\), quick1.tree/etc/\1,g' \ + -e 's,path=\.,path=quick1.tree/lib:quick1.tree/usr/lib,' \ + -e 's,linker=\./,linker=quick1.tree/lib/,'` +CCLINK=`echo $CCLINK \ + | sed -e 's,linker=\./,linker=quick1.tree/lib/,'` +rm -rf quick1.tree +rm -f quick1.log +mkdir -p quick1.tree/{lib,etc,usr/lib,usr/bin} +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib2.so $srcdir/reloc1lib2.c \ + -L quick1.tree/usr/lib -l1 +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib3.so $srcdir/quick1lib1.c +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib2.later.so \ + $srcdir/quick1lib2.c -L quick1.tree/usr/lib -l1 -l3 +echo 'int foo;' | $CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib4.so -xc - +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib5.so $srcdir/quick1lib3.c \ + -L quick1.tree/usr/lib -Wl,--rpath-link,quick1.tree/usr/lib -l2 +$CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib6.so $srcdir/quick1lib4.c \ + -L quick1.tree/usr/lib -Wl,--rpath-link,quick1.tree/usr/lib -l5 +echo 'int baz;' | $CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib7.so -xc - \ + -L quick1.tree/usr/lib -Wl,--rpath-link,quick1.tree/usr/lib -l6 +echo 'int baz;' | $CC -shared -O2 -fpic -o quick1.tree/usr/lib/lib7.later.so \ + -xc - -L quick1.tree/usr/lib -Wl,--rpath-link,quick1.tree/usr/lib -l2 +for lib in `cat syslib.list`; do + cp -p $lib.orig quick1.tree/lib/$lib + cp -p $lib.orig quick1.tree/lib/$lib.orig +done +for lib in `cat syslnk.list`; do + cp -dp $lib quick1.tree/lib +done +$CCLINK -o quick1.tree/usr/bin/bin1 $srcdir/reloc1.c \ + -Wl,--rpath-link,quick1.tree/usr/lib -L quick1.tree/usr/lib -l2 +echo 'int main () { extern int foo; return foo; }' \ + | $CCLINK -o quick1.tree/usr/bin/bin2 -xc - -xnone \ + -L quick1.tree/usr/lib -l4 +$CCLINK -o quick1.tree/usr/bin/bin3 $srcdir/reloc1.c \ + -Wl,--rpath-link,quick1.tree/usr/lib -L quick1.tree/usr/lib -l7 +$CCLINK -o quick1.tree/usr/bin/bin4 $srcdir/quick1.c \ + -Wl,--rpath-link,quick1.tree/usr/lib -L quick1.tree/usr/lib -l2 +$CCLINK -o quick1.tree/usr/bin/bin5 $srcdir/quick1.c \ + -Wl,--rpath-link,quick1.tree/usr/lib -L quick1.tree/usr/lib -l7 +echo 'int main () { return 0; }' \ + | $CCLINK -o quick1.tree/usr/bin/bin6 -xc - -xnone \ + -Wl,--rpath-link,quick1.tree/usr/lib -L quick1.tree/usr/lib -l6 +cat > quick1.tree/etc/prelink.conf <<EOF +quick1.tree/usr/bin +quick1.tree/lib +quick1.tree/usr/lib +EOF +LIBS="quick1.tree/usr/lib/lib1.so quick1.tree/usr/lib/lib2.so" +LIBS="$LIBS quick1.tree/usr/lib/lib3.so quick1.tree/usr/lib/lib4.so" +LIBS="$LIBS quick1.tree/usr/lib/lib5.so quick1.tree/usr/lib/lib6.so" +LIBS="$LIBS quick1.tree/usr/lib/lib7.so" +LIBS="$LIBS `sed 's|^|quick1.tree/lib/|' syslib.list`" +BINS="quick1.tree/usr/bin/bin1 quick1.tree/usr/bin/bin2" +BINS="$BINS quick1.tree/usr/bin/bin3 quick1.tree/usr/bin/bin4" +BINS="$BINS quick1.tree/usr/bin/bin5 quick1.tree/usr/bin/bin6" +savelibs +chmod 644 `ls $BINS | sed 's|$|.orig|'` +# Make sure prelinked binaries and libraries will have different ctimes +# than mtimes +sleep 3s +# lib2.later.so needs different timestamps than lib2.so for the tests below +touch quick1.tree/usr/lib/lib2.later.so +cp -p quick1.tree/usr/lib/lib2.later.so{,.orig} +# lib7.later.so needs different timestamps than lib7.so for the tests below +touch quick1.tree/usr/lib/lib7.later.so +cp -p quick1.tree/usr/lib/lib7.later.so{,.orig} +echo $PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick1.log +$PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick1.tree/etc/log1 2>&1 || exit 1 +cat quick1.tree/etc/log1 >> quick1.log +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log2 2>&1 || exit 2 +cat quick1.tree/etc/log2 >> quick1.log +stat quick1.tree/usr/lib/lib2.so >> quick1.log +echo chmod 644 quick1.tree/usr/lib/lib2.so >> quick1.log +chmod 644 quick1.tree/usr/lib/lib2.so +sleep 3s +echo chmod 755 quick1.tree/usr/lib/lib2.so >> quick1.log +chmod 755 quick1.tree/usr/lib/lib2.so +stat quick1.tree/usr/lib/lib2.so >> quick1.log +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log3 2>&1 || exit 3 +cat quick1.tree/etc/log3 >> quick1.log +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log4 2>&1 || exit 4 +cat quick1.tree/etc/log4 >> quick1.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 6 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 9 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 10 +fi +readelf -a quick1.tree/usr/bin/bin1 >> quick1.log 2>&1 || exit 11 +readelf -a quick1.tree/usr/bin/bin3 >> quick1.log 2>&1 || exit 12 +readelf -a quick1.tree/usr/bin/bin4 >> quick1.log 2>&1 || exit 13 +readelf -a quick1.tree/usr/bin/bin5 >> quick1.log 2>&1 || exit 14 +readelf -a quick1.tree/usr/bin/bin6 >> quick1.log 2>&1 || exit 15 +BINS="quick1.tree/usr/bin/bin1 quick1.tree/usr/bin/bin3" +BINS="$BINS quick1.tree/usr/bin/bin4 quick1.tree/usr/bin/bin5" +BINS="$BINS quick1.tree/usr/bin/bin6" +LIBS="quick1.tree/usr/lib/lib2.so quick1.tree/usr/lib/lib7.so" +comparelibs >> quick1.log 2>&1 || exit 16 +for l in 2 7; do + mv -f quick1.tree/usr/lib/lib$l.so{,.old} + mv -f quick1.tree/usr/lib/lib$l.so{,.old}.orig + cp -p quick1.tree/usr/lib/lib$l{.later,}.so + cp -p quick1.tree/usr/lib/lib$l{.later,}.so.orig +done +for b in 1 3 4 5 6; do + cp -p quick1.tree/usr/bin/bin$b{,.old} + chmod 644 quick1.tree/usr/bin/bin$b.old +done +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick1.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick1.tree/etc/log5 2>&1 || exit 17 +cat quick1.tree/etc/log5 >> quick1.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin1 || exit 18 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin2 || exit 19 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin3 || exit 20 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin4 || exit 21 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin5 || exit 22 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick1.tree/lib:quick1.tree/usr/lib quick1.tree/usr/bin/bin6 || exit 23 +fi +readelf -a quick1.tree/usr/bin/bin1 >> quick1.log 2>&1 || exit 24 +readelf -a quick1.tree/usr/bin/bin3 >> quick1.log 2>&1 || exit 25 +readelf -a quick1.tree/usr/bin/bin4 >> quick1.log 2>&1 || exit 26 +readelf -a quick1.tree/usr/bin/bin5 >> quick1.log 2>&1 || exit 27 +readelf -a quick1.tree/usr/bin/bin6 >> quick1.log 2>&1 || exit 28 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` quick1.log && exit 29 +L=quick1.tree/usr/lib/lib +L1=${L}1.so; L2=${L}2.so; L3=${L}3.so; L4=${L}4.so +L5=${L}5.so; L6=${L}6.so; L7=${L}7.so +B=quick1.tree/usr/bin/bin +B1=${B}1; B2=${B}2; B3=${B}3; B4=${B}4; B5=${B}5; B6=${B}6 +SL=`grep -f syslib.list quick1.tree/etc/log1 \ + | sed -n '/^Prelinking/s|^.*\(quick1.tree/lib/\)|\1|p'` +CHECKE="$B1 $B2 $B3 $B4 $B5 $B6"; CHECKL="$SL $L1 $L2 $L4 $L5 $L6 $L7" PREL="$CHECKE $CHECKL"; ASSUME="" +check_log quick1.tree/etc/log1 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $B2 $B3 $B4 $B5 $B6 $SL $L1 $L2 $L4 $L5 $L6 $L7" +check_log quick1.tree/etc/log2 +CHECKE="$B1 $B3 $B4 $B5 $B6"; CHECKL="$SL $L1 $L2 $L5 $L6 $L7"; PREL=""; ASSUME="$B2 $L4" +check_log quick1.tree/etc/log3 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $B2 $B3 $B4 $B5 $B6 $SL $L1 $L2 $L4 $L5 $L6 $L7" +check_log quick1.tree/etc/log4 +CHECKE="$B1 $B3 $B4 $B5 $B6"; CHECKL="$SL $L1 $L2 $L3 $L5 $L7 $L7"; PREL="$B1 $B3 $B4 $B5 $B6 $L2 $L3 $L5 $L6 $L7"; ASSUME="$B2 $L4" +check_log quick1.tree/etc/log5 +BINS="$B1 $B2 $B3 $B4 $B5 $B6" +LIBS="$SL $L1 $L2 $L3 $L4 $L5 $L6 $L7 $L2.old" +comparelibs >> quick1.log 2>&1 || exit 30 +for i in $BINS $SL $L1 $L2 $L3 $L4 $L5 $L6 $L7; do + cp -p $i $i.prelinked +done +for i in $BINS; do + chmod 644 $i.prelinked +done +echo $PRELINK -uavvvvvv >> quick1.log +$PRELINK -uavvvvvv >> quick1.log 2>&1 || exit 31 +for i in $BINS $SL $L1 $L2 $L3 $L4 $L5 $L6 $L7; do + cmp -s $i.orig $i || exit 32 + mv -f $i.prelinked $i +done +chmod 755 $BINS +exit 0 diff --git a/trunk/testsuite/quick1lib1.c b/trunk/testsuite/quick1lib1.c new file mode 100644 index 0000000..41767ce --- /dev/null +++ b/trunk/testsuite/quick1lib1.c @@ -0,0 +1,9 @@ +int q1 (void) +{ + return q2 () + 1; +} + +int q2 (void) +{ + return 77; +} diff --git a/trunk/testsuite/quick1lib2.c b/trunk/testsuite/quick1lib2.c new file mode 100644 index 0000000..b545086 --- /dev/null +++ b/trunk/testsuite/quick1lib2.c @@ -0,0 +1,11 @@ +extern int q1 (void); + +int f1 (void) +{ + return q1 () + 1; +} + +int q2 (void) +{ + return 9; +} diff --git a/trunk/testsuite/quick1lib3.c b/trunk/testsuite/quick1lib3.c new file mode 100644 index 0000000..06760a3 --- /dev/null +++ b/trunk/testsuite/quick1lib3.c @@ -0,0 +1,7 @@ +#ifndef D1 +#define D1(n) int qvar##n; int *qpvar##n = &qvar##n; +#endif +#define D2(n) D1(n##0) D1(n##1) D1(n##2) D1(n##3) D1(n##4) +#define D3(n) D2(n##0) D2(n##1) D2(n##2) D2(n##3) D2(n##4) +#define D4(n) D3(n##0) D3(n##1) D3(n##2) D3(n##3) D3(n##4) +D4(0) D4(1) diff --git a/trunk/testsuite/quick1lib4.c b/trunk/testsuite/quick1lib4.c new file mode 100644 index 0000000..53e23d7 --- /dev/null +++ b/trunk/testsuite/quick1lib4.c @@ -0,0 +1,2 @@ +#define D1(n) int qvar##n; +#include "quick1lib3.c" diff --git a/trunk/testsuite/quick2.sh b/trunk/testsuite/quick2.sh new file mode 100755 index 0000000..87138ae --- /dev/null +++ b/trunk/testsuite/quick2.sh @@ -0,0 +1,288 @@ +#!/bin/bash +. `dirname $0`/functions.sh +check_one() { + cnt=0 + log=$1 + echo -n . >> quick2.log + text="$2" + shift 2 + while [ $# -gt 0 ]; do + grep -q "^$text .*$1" $log || exit 40 + cnt=$((++cnt)) + shift + done + [ `grep "^$text " $log | wc -l` = $cnt ] || exit 41 +} +check_log() { + log=$1 + echo -n "Checking $1 " >> quick2.log + check_one $log 'Checking executable' $CHECKE + check_one $log 'Checking shared library' $CHECKL + check_one $log 'Assuming prelinked' $ASSUME + check_one $log 'Prelinking' $PREL + check_one $log 'Assuming non-prelinkable' $UNPREL + echo >> quick2.log +} + +PRELINK=`echo $PRELINK \ + | sed -e 's, \./\(prelink\.\(cache\|conf\)\), quick2.tree/etc/\1,g' \ + -e 's,path=\.,path=quick2.tree/lib:quick2.tree/usr/lib,' \ + -e 's,linker=\./,linker=quick2.tree/lib/,'` +CCLINK=`echo $CCLINK \ + | sed -e 's,linker=\./,linker=quick2.tree/lib/,'` +rm -rf quick2.tree +rm -f quick2.log +mkdir -p quick2.tree/{lib,etc,usr/lib,usr/bin} +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib2.so $srcdir/reloc1lib2.c \ + -L quick2.tree/usr/lib -l1 +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib3.so $srcdir/quick1lib1.c +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib2.later.so \ + $srcdir/quick1lib2.c -L quick2.tree/usr/lib -l1 -l3 +echo 'int foo;' | $CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib4.so -xc - +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib5.so $srcdir/quick1lib3.c \ + -L quick2.tree/usr/lib -Wl,--rpath-link,quick2.tree/usr/lib -l2 +$CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib6.so $srcdir/quick1lib4.c \ + -L quick2.tree/usr/lib -Wl,--rpath-link,quick2.tree/usr/lib -l5 +echo 'int baz;' | $CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib7.so -xc - \ + -L quick2.tree/usr/lib -Wl,--rpath-link,quick2.tree/usr/lib -l6 \ + -Wl,--spare-dynamic-tags=0 +echo 'int baz;' | $CC -shared -O2 -fpic -o quick2.tree/usr/lib/lib7.later.so \ + -xc - -L quick2.tree/usr/lib -Wl,--rpath-link,quick2.tree/usr/lib -l2 +for lib in `cat syslib.list`; do + cp -p $lib.orig quick2.tree/lib/$lib + cp -p $lib.orig quick2.tree/lib/$lib.orig +done +for lib in `cat syslnk.list`; do + cp -dp $lib quick2.tree/lib +done +$CCLINK -o quick2.tree/usr/bin/bin1 $srcdir/reloc1.c \ + -Wl,--rpath-link,quick2.tree/usr/lib -L quick2.tree/usr/lib -l2 +echo 'int main () { extern int foo; return foo; }' \ + | $CCLINK -o quick2.tree/usr/bin/bin2 -xc - -xnone \ + -L quick2.tree/usr/lib -l4 +$CCLINK -o quick2.tree/usr/bin/bin3 $srcdir/reloc1.c \ + -Wl,--rpath-link,quick2.tree/usr/lib -L quick2.tree/usr/lib -l7 +$CCLINK -o quick2.tree/usr/bin/bin4 $srcdir/quick1.c \ + -Wl,--rpath-link,quick2.tree/usr/lib -L quick2.tree/usr/lib -l2 +$CCLINK -o quick2.tree/usr/bin/bin5 $srcdir/quick1.c \ + -Wl,--rpath-link,quick2.tree/usr/lib -L quick2.tree/usr/lib -l7 +echo 'int main () { return 0; }' \ + | $CCLINK -o quick2.tree/usr/bin/bin6 -xc - -xnone \ + -Wl,--rpath-link,quick2.tree/usr/lib -L quick2.tree/usr/lib -l6 +echo 'int main () { return 0; }' \ + | $CCLINK -o quick2.tree/usr/bin/bin7 -static -xc - -xnone +cat > quick2.tree/usr/bin/bin8 <<EOF +#!/bin/sh +echo This is a sample shell script +echo used to test whether even shell scripts +echo and other executable non-ELF files +echo are cached as non-prelinkable +echo in /etc/prelink.cache and thus do not +echo need to be reread every time prelink -aq +echo is run. +exit 0 +EOF +chmod 755 quick2.tree/usr/bin/bin8 +cat > quick2.tree/usr/bin/bin9.sh <<EOF +#!/bin/sh +echo This is another sample shell script, +echo this time with a .sh extension. +echo This does not need to be even cached +echo as non-prelinkable, provided -b *.sh +echo is present in prelink.conf. +exit 0 +EOF +chmod 755 quick2.tree/usr/bin/bin9.sh +cat > quick2.tree/usr/bin/bin10.py <<EOF +#! /usr/bin/env python +print "This is a sample python script." +print "This does not need to be even cached" +print "as non-prelinkable, provided -b *.py" +print "is present in prelink.conf." +EOF +chmod 755 quick2.tree/usr/bin/bin10.py +cat > quick2.tree/usr/bin/bin11.script <<EOF +#!/bin/sh +echo This is another sample shell script, +echo this time matching b*11*r[hijk]*t shell pattern. +echo This does not need to be even cached +echo as non-prelinkable, provided -b b*11*r[hijk]*t +echo is present in prelink.conf. +exit 0 +EOF +chmod 755 quick2.tree/usr/bin/bin11.script +if [ `$CC -dumpmachine | sed "s/-.*-.*-.*//"` = "arm" ]; then + cat > quick2.tree/usr/bin/bin12 << EOF +#!/bin/sh +echo -pie -fPIE is not supported on our ARM architectures +echo this script will serve to disable that part of the test. +exit 0 +EOF +chmod 0755 quick2.tree/usr/bin/bin12 +else + echo 'int main () { return 0; }' \ + | $CCLINK -o quick2.tree/usr/bin/bin12 -pie -fPIE -xc - -xnone +fi +cat > quick2.tree/etc/prelink.conf <<EOF +-b *.sh +-b *.py +-b b*11*r[hijk]*t +quick2.tree/usr/bin +quick2.tree/lib +quick2.tree/usr/lib +EOF +LIBS="quick2.tree/usr/lib/lib1.so quick2.tree/usr/lib/lib2.so" +LIBS="$LIBS quick2.tree/usr/lib/lib3.so quick2.tree/usr/lib/lib4.so" +LIBS="$LIBS quick2.tree/usr/lib/lib5.so quick2.tree/usr/lib/lib6.so" +LIBS="$LIBS quick2.tree/usr/lib/lib7.so" +LIBS="$LIBS `sed 's|^|quick2.tree/lib/|' syslib.list`" +BINS="quick2.tree/usr/bin/bin1 quick2.tree/usr/bin/bin2" +BINS="$BINS quick2.tree/usr/bin/bin3 quick2.tree/usr/bin/bin4" +BINS="$BINS quick2.tree/usr/bin/bin5 quick2.tree/usr/bin/bin6" +BINS="$BINS quick2.tree/usr/bin/bin7 quick2.tree/usr/bin/bin8" +savelibs +chmod 644 `ls $BINS | sed 's|$|.orig|'` +# Make sure prelinked binaries and libraries will have different ctimes +# than mtimes +sleep 3s +# lib2.later.so needs different timestamps than lib2.so for the tests below +touch quick2.tree/usr/lib/lib2.later.so +cp -p quick2.tree/usr/lib/lib2.later.so{,.orig} +# lib7.later.so needs different timestamps than lib7.so for the tests below +touch quick2.tree/usr/lib/lib7.later.so +cp -p quick2.tree/usr/lib/lib7.later.so{,.orig} +echo $PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick2.log +$PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick2.tree/etc/log1 2>&1 || exit 1 +cat quick2.tree/etc/log1 >> quick2.log +grep -q 'lib7.so: Not enough room to add .dynamic entry' \ + quick2.tree/etc/log1 || exit 60 +grep -q 'Could not prelink .*bin3 because its dependency .*lib7.so could not be prelinked' \ + quick2.tree/etc/log1 || exit 61 +grep -q 'Could not prelink .*bin5 because its dependency .*lib7.so could not be prelinked' \ + quick2.tree/etc/log1 || exit 62 +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log2 2>&1 || exit 2 +cat quick2.tree/etc/log2 >> quick2.log +stat quick2.tree/usr/lib/lib2.so >> quick2.log +echo chmod 644 quick2.tree/usr/lib/lib2.so >> quick2.log +chmod 644 quick2.tree/usr/lib/lib2.so +sleep 3s +echo chmod 755 quick2.tree/usr/lib/lib2.so >> quick2.log +chmod 755 quick2.tree/usr/lib/lib2.so +stat quick2.tree/usr/lib/lib2.so >> quick2.log +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log3 2>&1 || exit 3 +cat quick2.tree/etc/log3 >> quick2.log +grep -q 'lib7.so: Not enough room to add .dynamic entry' \ + quick2.tree/etc/log3 || exit 63 +grep -q 'Could not prelink .*bin3 because its dependency .*lib7.so could not be prelinked' \ + quick2.tree/etc/log3 || exit 64 +grep -q 'Could not prelink .*bin5 because its dependency .*lib7.so could not be prelinked' \ + quick2.tree/etc/log3 || exit 65 +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log4 2>&1 || exit 4 +cat quick2.tree/etc/log4 >> quick2.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 6 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 9 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 10 +fi +readelf -a quick2.tree/usr/bin/bin1 >> quick2.log 2>&1 || exit 11 +readelf -a quick2.tree/usr/bin/bin3 >> quick2.log 2>&1 || exit 12 +readelf -a quick2.tree/usr/bin/bin4 >> quick2.log 2>&1 || exit 13 +readelf -a quick2.tree/usr/bin/bin5 >> quick2.log 2>&1 || exit 14 +readelf -a quick2.tree/usr/bin/bin6 >> quick2.log 2>&1 || exit 15 +BINS="quick2.tree/usr/bin/bin1 quick2.tree/usr/bin/bin4" +BINS="$BINS quick2.tree/usr/bin/bin6" +LIBS="quick2.tree/usr/lib/lib2.so" +comparelibs >> quick2.log 2>&1 || exit 16 +for l in 2 7; do + mv -f quick2.tree/usr/lib/lib$l.so{,.old} + mv -f quick2.tree/usr/lib/lib$l.so{,.old}.orig + cp -p quick2.tree/usr/lib/lib$l{.later,}.so + cp -p quick2.tree/usr/lib/lib$l{.later,}.so.orig +done +for b in 1 3 4 5 6; do + cp -p quick2.tree/usr/bin/bin$b{,.old} + chmod 644 quick2.tree/usr/bin/bin$b.old +done +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick2.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick2.tree/etc/log5 2>&1 || exit 17 +cat quick2.tree/etc/log5 >> quick2.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin1 || exit 18 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin2 || exit 19 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin3 || exit 20 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin4 || exit 21 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin5 || exit 22 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick2.tree/lib:quick2.tree/usr/lib quick2.tree/usr/bin/bin6 || exit 23 +fi +readelf -a quick2.tree/usr/bin/bin1 >> quick2.log 2>&1 || exit 24 +readelf -a quick2.tree/usr/bin/bin3 >> quick2.log 2>&1 || exit 25 +readelf -a quick2.tree/usr/bin/bin4 >> quick2.log 2>&1 || exit 26 +readelf -a quick2.tree/usr/bin/bin5 >> quick2.log 2>&1 || exit 27 +readelf -a quick2.tree/usr/bin/bin6 >> quick2.log 2>&1 || exit 28 +# In both etc/log1 and etc/log3 there should be one +# "Not enough room" and two "Could not prelink" warnings. +[ $(grep ^`echo $PRELINK | sed 's/ .*$/: /'` quick2.log | wc -l) -eq 6 ] || exit 29 +L=quick2.tree/usr/lib/lib +L1=${L}1.so; L2=${L}2.so; L3=${L}3.so; L4=${L}4.so +L5=${L}5.so; L6=${L}6.so; L7=${L}7.so +B=quick2.tree/usr/bin/bin +B1=${B}1; B2=${B}2; B3=${B}3; B4=${B}4; B5=${B}5 +B6=${B}6; B7=${B}7; B8=${B}8; B12=${B}12 +SL=`grep -f syslib.list quick2.tree/etc/log1 \ + | sed -n '/^Prelinking/s|^.*\(quick2.tree/lib/\)|\1|p'` +CHECK_E="$B1 $B2 $B4 $B6"; CHECKE="$CHECK_E $B3 $B5 $B7" +CHECKL="$SL $L1 $L2 $L4 $L5 $L6 $L7"; PREL="$CHECK_E $CHECKL"; ASSUME=""; UNPREL="" +check_log quick2.tree/etc/log1 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $B2 $B4 $B6 $SL $L1 $L2 $L4 $L5 $L6" +UNPREL="$B3 $B5 $B7 $B8 $B12 $L7" +check_log quick2.tree/etc/log2 +CHECKE="$B1 $B3 $B4 $B5 $B6"; CHECKL="$SL $L1 $L2 $L5 $L6 $L7"; PREL="$L7"; ASSUME="$B2 $L4"; UNPREL="$B7 $B8 $B12" +check_log quick2.tree/etc/log3 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $B2 $B4 $B6 $SL $L1 $L2 $L4 $L5 $L6"; UNPREL="$B3 $B5 $B7 $B8 $B12 $L7" +check_log quick2.tree/etc/log4 +CHECKE="$B1 $B3 $B4 $B5 $B6"; CHECKL="$SL $L1 $L2 $L3 $L5 $L7 $L7"; PREL="$B1 $B3 $B4 $B5 $B6 $L2 $L3 $L5 $L6 $L7"; ASSUME="$B2 $L4"; UNPREL="$B7 $B8 $B12" +check_log quick2.tree/etc/log5 +BINS="$B1 $B2 $B3 $B4 $B5 $B6" +LIBS="$SL $L1 $L2 $L3 $L4 $L5 $L6 $L7 $L2.old" +comparelibs >> quick2.log 2>&1 || exit 30 +for i in $BINS $SL $L1 $L2 $L3 $L4 $L5 $L6 $L7; do + cp -p $i $i.prelinked +done +for i in $BINS; do + chmod 644 $i.prelinked +done +echo $PRELINK -uavvvvvv >> quick2.log +$PRELINK -uavvvvvv >> quick2.log 2>&1 || exit 31 +for i in $BINS $SL $L1 $L2 $L3 $L4 $L5 $L6 $L7; do + cmp -s $i.orig $i || exit 32 + mv -f $i.prelinked $i +done +chmod 755 $BINS +exit 0 diff --git a/trunk/testsuite/quick3.sh b/trunk/testsuite/quick3.sh new file mode 100755 index 0000000..0562e52 --- /dev/null +++ b/trunk/testsuite/quick3.sh @@ -0,0 +1,110 @@ +#!/bin/bash +. `dirname $0`/functions.sh +check_one() { + cnt=0 + log=$1 + echo -n . >> quick3.log + text="$2" + shift 2 + while [ $# -gt 0 ]; do + grep -q "^$text .*$1" $log || exit 40 + cnt=$((++cnt)) + shift + done + [ `grep "^$text " $log | wc -l` = $cnt ] || exit 41 +} +check_log() { + log=$1 + echo -n "Checking $1 " >> quick3.log + check_one $log 'Checking executable' $CHECKE + check_one $log 'Checking shared library' $CHECKL + check_one $log 'Assuming prelinked' $ASSUME + check_one $log 'Prelinking' $PREL + echo >> quick3.log +} + +PRELINK=`echo $PRELINK \ + | sed -e 's, \./\(prelink\.\(cache\|conf\)\), quick3.tree/etc/\1,g' \ + -e 's,path=\.,path=quick3.tree/lib:quick3.tree/usr/lib,' \ + -e 's,linker=\./,linker=quick3.tree/lib/,'` +CCLINK=`echo $CCLINK \ + | sed -e 's,linker=\./,linker=quick3.tree/lib/,'` +rm -rf quick3.tree +rm -f quick3.log +mkdir -p quick3.tree/{lib,etc,usr/lib,usr/bin} +$CC -shared -O2 -fpic -o quick3.tree/usr/lib/lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o quick3.tree/usr/lib/lib2.so $srcdir/reloc1lib2.c \ + -L quick3.tree/usr/lib -l1 -Wl,-soname,lib2.so +for lib in `cat syslib.list`; do + cp -p $lib.orig quick3.tree/lib/$lib + cp -p $lib.orig quick3.tree/lib/$lib.orig +done +for lib in `cat syslnk.list`; do + cp -dp $lib quick3.tree/lib +done +$CCLINK -o quick3.tree/usr/bin/bin1 $srcdir/reloc1.c \ + -Wl,--rpath-link,quick3.tree/usr/lib -L quick3.tree/usr/lib -l2 +cat > quick3.tree/etc/prelink.conf <<EOF +quick3.tree/usr/bin +quick3.tree/lib +quick3.tree/usr/lib +EOF +LIBS="quick3.tree/usr/lib/lib1.so quick3.tree/usr/lib/lib2.so" +LIBS="$LIBS `sed 's|^|quick3.tree/lib/|' syslib.list`" +BINS="quick3.tree/usr/bin/bin1" +savelibs +chmod 644 `ls $BINS | sed 's|$|.orig|'` +# Make sure prelinked binaries and libraries will have different ctimes +# than mtimes +sleep 3s +echo $PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick3.log +$PRELINK ${PRELINK_OPTS--vm} -avvvvv > quick3.tree/etc/log1 2>&1 || exit 1 +cat quick3.tree/etc/log1 >> quick3.log +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick3.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick3.tree/etc/log2 2>&1 || exit 2 +cat quick3.tree/etc/log2 >> quick3.log +$CC -shared -O2 -fpic -o quick3.tree/usr/lib/lib2.so.0 $srcdir/reloc1lib2.c \ + -L quick3.tree/usr/lib -l1 -Wl,-soname,lib2.so +rm -f quick3.tree/usr/lib/lib2.so{,.orig} +cp -p quick3.tree/usr/lib/lib2.so.0{,.orig} +ln -sf lib2.so.0 quick3.tree/usr/lib/lib2.so +sleep 3s +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick3.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick3.tree/etc/log3 2>&1 || exit 3 +cat quick3.tree/etc/log3 >> quick3.log +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=quick3.tree/lib:quick3.tree/usr/lib quick3.tree/usr/bin/bin1 || exit 4 +fi +LIBS="quick3.tree/usr/lib/lib1.so quick3.tree/usr/lib/lib2.so.0" +echo $PRELINK ${PRELINK_OPTS--vm} -aqvvvvv >> quick3.log +$PRELINK ${PRELINK_OPTS--vm} -aqvvvvv > quick3.tree/etc/log4 2>&1 || exit 5 +cat quick3.tree/etc/log4 >> quick3.log +comparelibs >> quick3.log 2>&1 || exit 6 +[ -L quick3.tree/usr/lib/lib2.so ] || exit 7 +L=quick3.tree/usr/lib/lib +L1=${L}1.so; L2=${L}2.so; L3=${L}2.so.0 +B1=quick3.tree/usr/bin/bin1 +SL=`grep -f syslib.list quick3.tree/etc/log1 \ + | sed -n '/^Prelinking/s|^.*\(quick3.tree/lib/\)|\1|p'` +CHECKE="$B1"; CHECKL="$SL $L1 $L2" PREL="$CHECKE $CHECKL"; ASSUME="" +check_log quick3.tree/etc/log1 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $L1 $L2 $SL" +check_log quick3.tree/etc/log2 +CHECKE="$B1"; CHECKL="$SL $L1 $L3"; PREL="$B1 $L3"; ASSUME="" +check_log quick3.tree/etc/log3 +CHECKE=""; CHECKL=""; PREL=""; ASSUME="$B1 $L1 $L3 $SL" +check_log quick3.tree/etc/log4 +for i in $B1 $SL $L1 $L3; do + cp -p $i $i.prelinked +done +for i in $B1; do + chmod 644 $i.prelinked +done +echo $PRELINK -uavvvvvv >> quick3.log +$PRELINK -uavvvvvv >> quick3.log 2>&1 || exit 31 +for i in $B1 $SL $L1 $L3; do + cmp -s $i.orig $i || exit 32 + mv -f $i.prelinked $i +done +chmod 755 $BINS +exit 0 diff --git a/trunk/testsuite/reloc1.c b/trunk/testsuite/reloc1.c new file mode 100644 index 0000000..e679bed --- /dev/null +++ b/trunk/testsuite/reloc1.c @@ -0,0 +1,16 @@ +#include "reloc1.h" +#include <stdlib.h> + +static struct A local = { 77, &local, &bar + 4 }; + +int main() +{ + if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + local.c -= 4; + if (local.a != 77 || local.b != &local || local.c != &bar) + abort (); + exit (0); +} diff --git a/trunk/testsuite/reloc1.h b/trunk/testsuite/reloc1.h new file mode 100644 index 0000000..093dd3a --- /dev/null +++ b/trunk/testsuite/reloc1.h @@ -0,0 +1,12 @@ +struct A + { + char a; + struct A *b; + int *c; + }; + +extern struct A foo; +extern int bar; +extern int f1 (void); +extern int f2 (void); +extern struct A *f3 (void); diff --git a/trunk/testsuite/reloc1.sh b/trunk/testsuite/reloc1.sh new file mode 100755 index 0000000..ade05c9 --- /dev/null +++ b/trunk/testsuite/reloc1.sh @@ -0,0 +1,20 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc1 reloc1lib*.so reloc1.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o reloc1lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o reloc1lib2.so $srcdir/reloc1lib2.c reloc1lib1.so +BINS="reloc1" +LIBS="reloc1lib1.so reloc1lib2.so" +$CCLINK -o reloc1 $srcdir/reloc1.c -Wl,--rpath-link,. reloc1lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc1 > reloc1.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc1 >> reloc1.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc1.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc1 || exit 3 +fi +readelf -a ./reloc1 >> reloc1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc1 +comparelibs >> reloc1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc10.c b/trunk/testsuite/reloc10.c new file mode 100644 index 0000000..5720d33 --- /dev/null +++ b/trunk/testsuite/reloc10.c @@ -0,0 +1,19 @@ +#include <stdlib.h> + +extern int bar, baz, *barp, *bazp, dummy; +extern int f1 (void), f2 (void), f3 (void), f4 (void); +/* Try to use COPY reloc for bar and get away without COPY + reloc for baz. Similarly for barp and bazp. */ +int *bazp2 = &baz; +int **bazp3 = &bazp; + +int main (void) +{ + if (f1 () != 11 || f2 () != 12 || bar != 36 || *bazp2 != 38) + abort (); + if (f3 () != 14 || f4 () != 16 || *barp != 36 || **bazp3 != 38) + abort (); + if (dummy != 24) + abort (); + exit (0); +} diff --git a/trunk/testsuite/reloc10.sh b/trunk/testsuite/reloc10.sh new file mode 100755 index 0000000..66dd438 --- /dev/null +++ b/trunk/testsuite/reloc10.sh @@ -0,0 +1,23 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc10 reloc10lib*.so reloc10.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o reloc10lib1.so $srcdir/reloc10lib1.c +$CC -shared -O2 -nostdlib -fpic -o reloc10lib2.so $srcdir/reloc10lib2.c reloc10lib1.so +$CC -shared -O2 -nostdlib -fpic -o reloc10lib3.so $srcdir/reloc10lib3.c reloc10lib1.so +$CC -shared -O2 -nostdlib -fpic -o reloc10lib4.so $srcdir/reloc10lib4.c reloc10lib1.so +$CC -shared -O2 -fpic -o reloc10lib5.so $srcdir/reloc10lib5.c reloc10lib2.so reloc10lib3.so reloc10lib4.so +BINS="reloc10" +LIBS="reloc10lib1.so reloc10lib2.so reloc10lib3.so reloc10lib4.so reloc10lib5.so" +$CCLINK -o reloc10 $srcdir/reloc10.c -Wl,--rpath-link,. reloc10lib5.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc10 > reloc10.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc10 >> reloc10.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc10.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc10 || exit 3 +fi +readelf -a ./reloc10 >> reloc10.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc10 +comparelibs >> reloc10.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc10lib1.c b/trunk/testsuite/reloc10lib1.c new file mode 100644 index 0000000..2ee06d2 --- /dev/null +++ b/trunk/testsuite/reloc10lib1.c @@ -0,0 +1,12 @@ +int bar = 26; +int baz = 28; + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return 2; +} diff --git a/trunk/testsuite/reloc10lib2.c b/trunk/testsuite/reloc10lib2.c new file mode 100644 index 0000000..fc327fc --- /dev/null +++ b/trunk/testsuite/reloc10lib2.c @@ -0,0 +1,11 @@ +extern int bar, baz, f1 (void), f2 (void); + +int f3 (void) +{ + return f1 () + 3; +} + +int f4 (void) +{ + return f2 () + 4; +} diff --git a/trunk/testsuite/reloc10lib3.c b/trunk/testsuite/reloc10lib3.c new file mode 100644 index 0000000..2ec80ab --- /dev/null +++ b/trunk/testsuite/reloc10lib3.c @@ -0,0 +1,3 @@ +extern int bar, baz, f1 (void), f2 (void); + +int *barp = &bar, *bazp = &baz; diff --git a/trunk/testsuite/reloc10lib4.c b/trunk/testsuite/reloc10lib4.c new file mode 100644 index 0000000..4376249 --- /dev/null +++ b/trunk/testsuite/reloc10lib4.c @@ -0,0 +1 @@ +int dummy = 24; diff --git a/trunk/testsuite/reloc10lib5.c b/trunk/testsuite/reloc10lib5.c new file mode 100644 index 0000000..19fd925 --- /dev/null +++ b/trunk/testsuite/reloc10lib5.c @@ -0,0 +1,12 @@ +int bar = 36; +int baz = 38; + +int f1 (void) +{ + return 11; +} + +int f2 (void) +{ + return 12; +} diff --git a/trunk/testsuite/reloc11.c b/trunk/testsuite/reloc11.c new file mode 100644 index 0000000..923aff4 --- /dev/null +++ b/trunk/testsuite/reloc11.c @@ -0,0 +1,16 @@ +#include <stdlib.h> + +extern int dummy; +extern int var, var2, varp1 (), var2m1 (), bar (); +int *pvar = &var, *pvar2 = &var2; + +int main (void) +{ + if (dummy != 24) + abort (); + if (*pvar != 32 || *pvar2 != 16) + abort (); + if (varp1 () != 33 || var2m1 () != 6 || bar () != 40) + abort (); + exit (0); +} diff --git a/trunk/testsuite/reloc11.sh b/trunk/testsuite/reloc11.sh new file mode 100755 index 0000000..ab0cbee --- /dev/null +++ b/trunk/testsuite/reloc11.sh @@ -0,0 +1,21 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc11 reloc11lib*.so reloc11.log +rm -f prelink.cache +$CC -shared -O2 -nostdlib -fpic -o reloc11lib1.so $srcdir/reloc10lib4.c +$CC -shared -O2 -nostdlib -fpic -o reloc11lib2.so $srcdir/reloc11lib2.c +$CC -shared -O2 -nostdlib -fpic -o reloc11lib3.so $srcdir/reloc11lib3.c reloc11lib2.so +BINS="reloc11" +LIBS="reloc11lib1.so reloc11lib2.so reloc11lib3.so" +$CCLINK -o reloc11 $srcdir/reloc11.c -Wl,--rpath-link,. reloc11lib1.so reloc11lib3.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc11 > reloc11.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc11 >> reloc11.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc11.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc11 || exit 3 +fi +readelf -a ./reloc11 >> reloc11.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc11 +comparelibs >> reloc11.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc11lib2.c b/trunk/testsuite/reloc11lib2.c new file mode 100644 index 0000000..6a2191c --- /dev/null +++ b/trunk/testsuite/reloc11lib2.c @@ -0,0 +1,16 @@ +int var = 24, var2 = 16; + +int varp1 (void) +{ + return var + 1; +} + +int var2m1 (void) +{ + return var2 - 1; +} + +int bar (void) +{ + return varp1 () + var2m1 () + 1; +} diff --git a/trunk/testsuite/reloc11lib3.c b/trunk/testsuite/reloc11lib3.c new file mode 100644 index 0000000..0cea7f3 --- /dev/null +++ b/trunk/testsuite/reloc11lib3.c @@ -0,0 +1,7 @@ +int var = 32; +extern int var2; + +int var2m1 (void) +{ + return var2 - 10; +} diff --git a/trunk/testsuite/reloc1lib1.c b/trunk/testsuite/reloc1lib1.c new file mode 100644 index 0000000..8aa0628 --- /dev/null +++ b/trunk/testsuite/reloc1lib1.c @@ -0,0 +1,16 @@ +#include "reloc1.h" + +int bar = 26; +int baz = 28; + +struct A foo = { 1, &foo, &bar }; + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return f1 () + 1; +} diff --git a/trunk/testsuite/reloc1lib2.c b/trunk/testsuite/reloc1lib2.c new file mode 100644 index 0000000..a338c1d --- /dev/null +++ b/trunk/testsuite/reloc1lib2.c @@ -0,0 +1,6 @@ +#include "reloc1.h" + +int f1 (void) +{ + return 11; +} diff --git a/trunk/testsuite/reloc2.c b/trunk/testsuite/reloc2.c new file mode 100644 index 0000000..6c7fed5 --- /dev/null +++ b/trunk/testsuite/reloc2.c @@ -0,0 +1,13 @@ +#include <stdlib.h> + +extern int f2 (int add); +extern void * f3 (void); + +int main() +{ + if (f2 (1) != 27 || f2 (0) != 1) + abort (); + if (f3 () != (void *) f3) + abort (); + exit (0); +} diff --git a/trunk/testsuite/reloc2.sh b/trunk/testsuite/reloc2.sh new file mode 100755 index 0000000..4d180c6 --- /dev/null +++ b/trunk/testsuite/reloc2.sh @@ -0,0 +1,26 @@ +#!/bin/bash +. `dirname $0`/functions.sh +SHFLAGS= +case "`uname -m`" in + ia64|ppc*|x86_64|mips*) SHFLAGS=-fpic;; # Does not support non-pic shared libs + s390*) if file reloc1lib1.so | grep -q 64-bit; then SHFLAGS=-fpic; fi;; +esac +rm -f reloc2 reloc2lib*.so reloc2.log +$CC -shared $SHFLAGS -O2 -o reloc2lib1.so $srcdir/reloc2lib1.c +$CC -shared $SHFLAGS -O2 -o reloc2lib2.so $srcdir/reloc2lib2.c \ + reloc2lib1.so 2>/dev/null +BINS="reloc2" +LIBS="reloc2lib1.so reloc2lib2.so" +$CCLINK -o reloc2 $srcdir/reloc2.c -Wl,--rpath-link,. reloc2lib2.so +$STRIP -R .comment $BINS $LIBS +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc2 > reloc2.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc2 >> reloc2.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc2.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc2 || exit 3 +fi +readelf -a ./reloc2 >> reloc2.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc2 +comparelibs >> reloc2.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc2lib1.c b/trunk/testsuite/reloc2lib1.c new file mode 100644 index 0000000..3551704 --- /dev/null +++ b/trunk/testsuite/reloc2lib1.c @@ -0,0 +1,4 @@ +int f1 (int dummy) +{ + return 1; +} diff --git a/trunk/testsuite/reloc2lib2.c b/trunk/testsuite/reloc2lib2.c new file mode 100644 index 0000000..094daad --- /dev/null +++ b/trunk/testsuite/reloc2lib2.c @@ -0,0 +1,15 @@ +extern int f1 (int dummy); + +int f2 (int add) +{ + if (add) + return f1 (0) + 26; + return f1 (0); +} + +/* Make sure conflict in f3 is not against read-only segment. */ +asm (".section trampoline, \"awx\"; .previous"); +void * __attribute__((section ("trampoline"))) f3 (void) +{ + return (void *) f3; +} diff --git a/trunk/testsuite/reloc3.c b/trunk/testsuite/reloc3.c new file mode 100644 index 0000000..2f455d7 --- /dev/null +++ b/trunk/testsuite/reloc3.c @@ -0,0 +1,29 @@ +#include "reloc1.h" +#include <stdlib.h> +#include <stdio.h> + +int i; +int j __attribute__((aligned (32))); +int k[2048]; +int l = 26; + +void f5 (FILE *f) +{ + fprintf (stdout, "OK"); +} + +int main() +{ + struct A *x; + foo.c -= 2; + if (foo.a != 1 || foo.b != &foo || foo.c[0] != 28 || foo.c[1] != 29 + || foo.c[2] != 30) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + x = f3 (); + if (x->a != 2 || x->b != x || x->c != foo.c + 1) + abort (); + f5 (stdout); + exit (0); +} diff --git a/trunk/testsuite/reloc3.sh b/trunk/testsuite/reloc3.sh new file mode 100755 index 0000000..acf0497 --- /dev/null +++ b/trunk/testsuite/reloc3.sh @@ -0,0 +1,21 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc3 reloc3lib*.so reloc3.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o reloc3lib1.so $srcdir/reloc3lib1.c +$CC -shared -O2 -fpic -o reloc3lib2.so $srcdir/reloc1lib2.c reloc3lib1.so +BINS="reloc3" +LIBS="reloc3lib1.so reloc3lib2.so" +$CCLINK -o reloc3 $srcdir/reloc3.c -Wl,--rpath-link,. reloc3lib2.so +$STRIP -g $BINS $LIBS +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc3 > reloc3.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc3 >> reloc3.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc3.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc3 >> reloc3.log || exit 3 +fi +readelf -a ./reloc3 >> reloc3.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc3 +comparelibs >> reloc3.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc3lib1.c b/trunk/testsuite/reloc3lib1.c new file mode 100644 index 0000000..fd649c6 --- /dev/null +++ b/trunk/testsuite/reloc3lib1.c @@ -0,0 +1,21 @@ +#include "reloc1.h" + +int baz[3] = { 28, 29, 30 }; + +struct A foo = { 1, &foo, &baz[2] }; +static struct A xfoo = { 2, &xfoo, &baz[1] }; + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return f1 () + 1; +} + +struct A *f3 (void) +{ + return &xfoo; +} diff --git a/trunk/testsuite/reloc4.c b/trunk/testsuite/reloc4.c new file mode 100644 index 0000000..cb3b17a --- /dev/null +++ b/trunk/testsuite/reloc4.c @@ -0,0 +1,14 @@ +#include <stdio.h> + +int main (void) +{ + int i; + + printf ("#include <stdlib.h>\nextern int"); + for (i = 0; i < 255; ++i) + printf (" bar%02x (int),", i); + printf (" barff (int);\nint main (void)\n{\n int x = 0;\n"); + for (i = 0; i < 256; ++i) + printf (" x = bar%02x (x);\n", i); + printf (" if (x != 0x7fff8000) abort ();\n exit (0);\n}\n"); +} diff --git a/trunk/testsuite/reloc4.sh b/trunk/testsuite/reloc4.sh new file mode 100755 index 0000000..c20f8b5 --- /dev/null +++ b/trunk/testsuite/reloc4.sh @@ -0,0 +1,36 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# This test takes a lot of time, so skip it normally +[ -z "$CHECK_ME_HARDER" ] && exit 77 +rm -f reloc4 reloc4lib*.so reloc4.log +rm -f prelink.cache +$HOST_CC -O2 -o reloc4lib1.tmp $srcdir/reloc4lib1.c +$HOST_CC -O2 -o reloc4lib2.tmp $srcdir/reloc4lib2.c +$HOST_CC -O2 -o reloc4lib3.tmp $srcdir/reloc4lib3.c +$HOST_CC -O2 -o reloc4.tmp $srcdir/reloc4.c +./reloc4lib1.tmp > reloc4lib1.tmp.c +./reloc4lib2.tmp > reloc4lib2.tmp.c +./reloc4lib3.tmp > reloc4lib3.tmp.c +./reloc4.tmp > reloc4.tmp.c +case "`$RUN uname -m`" in + mips*) extra=-mxgot ;; + *) extra= ;; +esac +$CC -shared -fpic $extra -o reloc4lib1.so reloc4lib1.tmp.c +$CC -shared -fpic $extra -o reloc4lib2.so reloc4lib2.tmp.c reloc4lib1.so +$CC -shared -fpic $extra -o reloc4lib3.so reloc4lib3.tmp.c reloc4lib2.so +BINS="reloc4" +LIBS="reloc4lib1.so reloc4lib2.so reloc4lib3.so" +$CCLINK $extra -o reloc4 reloc4.tmp.c -Wl,--rpath-link,. reloc4lib3.so +savelibs +rm -f reloc4*.tmp reloc4*.tmp.c +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc4 > reloc4.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc4 >> reloc4.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc4.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc4 || exit 3 +fi +readelf -a ./reloc4 >> reloc4.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc4 +comparelibs >> reloc4.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc4lib1.c b/trunk/testsuite/reloc4lib1.c new file mode 100644 index 0000000..f1297d8 --- /dev/null +++ b/trunk/testsuite/reloc4lib1.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int main (void) +{ + int i; + + for (i = 0; i < 65536; ++i) + printf ("int foo%04x (void) { return %d; }\n", i, (i & 31) == 0 ? 0 : i); +} diff --git a/trunk/testsuite/reloc4lib2.c b/trunk/testsuite/reloc4lib2.c new file mode 100644 index 0000000..07aa721 --- /dev/null +++ b/trunk/testsuite/reloc4lib2.c @@ -0,0 +1,17 @@ +#include <stdio.h> + +int main (void) +{ + int i, j; + + for (i = 0; i < 256; ++i) + { + printf ("extern int "); + for (j = 0; j < 255; ++j) + printf ("foo%02x%02x (void), ", i, j); + printf ("foo%02xff (void);\nint bar%02x (int x) { return x", i, i); + for (j = 0; j < 256; ++j) + printf (" + foo%02x%02x ()", i, j); + printf ("; }\n"); + } +} diff --git a/trunk/testsuite/reloc4lib3.c b/trunk/testsuite/reloc4lib3.c new file mode 100644 index 0000000..1f30817 --- /dev/null +++ b/trunk/testsuite/reloc4lib3.c @@ -0,0 +1,9 @@ +#include <stdio.h> + +int main (void) +{ + int i; + + for (i = 0; i < 65536; i += 32) + printf ("int foo%04x (void) { return %d; }\n", i, i); +} diff --git a/trunk/testsuite/reloc5.c b/trunk/testsuite/reloc5.c new file mode 100644 index 0000000..b174bcf --- /dev/null +++ b/trunk/testsuite/reloc5.c @@ -0,0 +1,24 @@ +#include <stdio.h> + +int main (void) +{ + int i; + + printf ("#include <stdlib.h>\nextern char testzero[16384];\nextern int"); + for (i = 0; i < 255; ++i) + printf (" bar%02x (int),", i); + printf (" barff (int);\nint main (void)\n{\n int x = 0;\n"); + for (i = 0; i < 256; ++i) + printf (" x = bar%02x (x);\n", i); + printf (" if (x != 0x7fff8000) abort ();\n"); + printf (" for (x = 0; x < 16384; ++x)\n"); + printf (" if (testzero[x]) abort ();\n"); + printf (" exit (0);\n}\n\n"); + printf ("#ifdef __arm__\n"); + printf ("asm (\".section nonalloced,\\\"aw\\\",%%nobits\\n\\t\"\n"); + printf ("#else\n"); + printf ("asm (\".section nonalloced,\\\"aw\\\",@nobits\\n\\t\"\n"); + printf ("#endif\n"); + printf (" \".globl testzero\\n\\t\"\n"); + printf (" \"testzero: .skip 16384\");\n"); +} diff --git a/trunk/testsuite/reloc5.sh b/trunk/testsuite/reloc5.sh new file mode 100755 index 0000000..f543f69 --- /dev/null +++ b/trunk/testsuite/reloc5.sh @@ -0,0 +1,22 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# This test takes a lot of time, so skip it normally +[ -z "$CHECK_ME_HARDER" ] && exit 77 +rm -f reloc5 reloc5.log +rm -f prelink.cache +$HOST_CC -O2 -o reloc5.tmp $srcdir/reloc5.c +./reloc5.tmp > reloc5.tmp.c +BINS="reloc5" +$CCLINK -o reloc5 reloc5.tmp.c -Wl,--rpath-link,. reloc4lib3.so +savelibs +rm -f reloc5*.tmp reloc5*.tmp.c +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc5 > reloc5.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc5 >> reloc5.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc5.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc5 || exit 3 +fi +readelf -a ./reloc5 >> reloc5.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc5 +comparelibs >> reloc5.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc6.sh b/trunk/testsuite/reloc6.sh new file mode 100755 index 0000000..7f72936 --- /dev/null +++ b/trunk/testsuite/reloc6.sh @@ -0,0 +1,36 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc6 reloc6lib*.so reloc6.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o reloc6lib1.so $srcdir/reloc3lib1.c +$CC -shared -O2 -fpic -o reloc6lib2.so $srcdir/reloc1lib2.c reloc6lib1.so +$CCLINK -o reloc6 $srcdir/reloc3.c -Wl,--rpath-link,. reloc6lib2.so +$CCLINK -o reloc6.nop $srcdir/reloc3.c -Wl,--rpath-link,. reloc6lib2.so +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc6 > reloc6.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc6 >> reloc6.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc6.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 3 +fi +readelf -a ./reloc6 >> reloc6.log 2>&1 || exit 4 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 5 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 6 +fi +mv -f reloc6lib2.so reloc6lib2.so.p +$CC -shared -O2 -fpic -o reloc6lib2.so $srcdir/reloc1lib2.c reloc6lib1.so +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6 >> reloc6.log || exit 7 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc6.nop >> reloc6.log || exit 8 +fi +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. LD_BIND_NOW=1 ./reloc6.nop >> reloc6.log || exit 9 +fi +mv -f reloc6lib2.so reloc6lib2.so.nop +mv -f reloc6lib2.so.p reloc6lib2.so +# So that it is not prelinked again +chmod -x ./reloc6 ./reloc6.nop diff --git a/trunk/testsuite/reloc7.c b/trunk/testsuite/reloc7.c new file mode 100644 index 0000000..c1f6dc8 --- /dev/null +++ b/trunk/testsuite/reloc7.c @@ -0,0 +1,38 @@ +#include "reloc1.h" +#include <stdlib.h> +#include <stdio.h> + +int i; +int j __attribute__((aligned (32))); +int k[2048]; +int l = 26; +int m[3] = { 28, 29, 30 }; +extern int baz[3]; + +struct A n __attribute__((section("nsec"))) = { 1, &n, &m[2] }; +static struct A o __attribute__((section("osec"))) = { 2, &o, &baz[1] }; + +void f5 (FILE *f) +{ + fprintf (stdout, "OK"); +} + +int main() +{ + struct A *x; + foo.c -= 2; + if (foo.a != 1 || foo.b != &foo || foo.c[0] != 28 || foo.c[1] != 29 + || foo.c[2] != 30) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + x = f3 (); + if (x->a != 2 || x->b != x || x->c != foo.c + 1) + abort (); + if (n.a != 1 || n.b != &n || n.c != m + 2) + abort (); + if (o.a != 2 || o.b != &o || o.c != baz + 1) + abort (); + f5 (stdout); + exit (0); +} diff --git a/trunk/testsuite/reloc7.sh b/trunk/testsuite/reloc7.sh new file mode 100755 index 0000000..edbbcbf --- /dev/null +++ b/trunk/testsuite/reloc7.sh @@ -0,0 +1,20 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f reloc7 reloc7lib*.so reloc7.log +rm -f prelink.cache +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc7lib1.so $srcdir/reloc3lib1.c +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc7lib2.so $srcdir/reloc1lib2.c reloc7lib1.so +BINS="reloc7" +LIBS="reloc7lib1.so reloc7lib2.so" +$CCLINK -o reloc7 -Wl,-z,nocombreloc $srcdir/reloc7.c -Wl,--rpath-link,. reloc7lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc7 > reloc7.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc7 >> reloc7.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc7.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc7 >> reloc7.log || exit 3 +fi +readelf -a ./reloc7 >> reloc7.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc7 +comparelibs >> reloc7.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc8.sh b/trunk/testsuite/reloc8.sh new file mode 100755 index 0000000..9f5e1fb --- /dev/null +++ b/trunk/testsuite/reloc8.sh @@ -0,0 +1,28 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# Disable this test under SELinux +if [ "x$CROSS" = "x" ]; then + test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +fi +rm -f reloc8 reloc8lib*.so reloc8.log +rm -f prelink.cache +NOCOPYRELOC=-Wl,-z,nocopyreloc +case "`uname -m`" in + x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; +esac +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib1.so $srcdir/reloc3lib1.c +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc8lib2.so $srcdir/reloc1lib2.c reloc8lib1.so +BINS="reloc8" +LIBS="reloc8lib1.so reloc8lib2.so" +$CCLINK -o reloc8 $NOCOPYRELOC $srcdir/reloc7.c -Wl,--rpath-link,. reloc8lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc8 > reloc8.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc8 >> reloc8.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc8.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc8 >> reloc8.log || exit 3 +fi +readelf -a ./reloc8 >> reloc8.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc8 +comparelibs >> reloc8.log 2>&1 || exit 5 diff --git a/trunk/testsuite/reloc9.sh b/trunk/testsuite/reloc9.sh new file mode 100755 index 0000000..d3a449c --- /dev/null +++ b/trunk/testsuite/reloc9.sh @@ -0,0 +1,28 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# Disable this test under SELinux +if [ "x$CROSS" = "x" ]; then + test -x /usr/sbin/getenforce -a "`/usr/sbin/getenforce`" = Enforcing && exit 77 +fi +rm -f reloc9 reloc9lib*.so reloc9.log +rm -f prelink.cache +NOCOPYRELOC=-Wl,-z,nocopyreloc +case "`uname -m`" in + x86_64|s390*) if file reloc1lib1.so | grep -q 64-bit; then NOCOPYRELOC=; fi;; +esac +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib1.so $srcdir/reloc3lib1.c +$CC -shared -O2 -Wl,-z,nocombreloc -fpic -o reloc9lib2.so $srcdir/reloc1lib2.c reloc9lib1.so +BINS="reloc9" +LIBS="reloc9lib1.so reloc9lib2.so" +$CCLINK -o reloc9 -Wl,-z,nocombreloc $NOCOPYRELOC $srcdir/reloc7.c -Wl,--rpath-link,. reloc9lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./reloc9 > reloc9.log +$PRELINK ${PRELINK_OPTS--vm} ./reloc9 >> reloc9.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` reloc9.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./reloc9 >> reloc9.log || exit 3 +fi +readelf -a ./reloc9 >> reloc9.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./reloc9 +comparelibs >> reloc9.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle1.sh b/trunk/testsuite/shuffle1.sh new file mode 100755 index 0000000..4553d2e --- /dev/null +++ b/trunk/testsuite/shuffle1.sh @@ -0,0 +1,24 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f shuffle1 shuffle1lib*.so shuffle1.log shuffle1.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle1lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle1lib2.so $srcdir/reloc1lib2.c shuffle1lib1.so +BINS="shuffle1" +LIBS="shuffle1lib1.so shuffle1lib2.so" +$CCLINK -o shuffle1 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle1lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/0x08048000/0x08000000/;s/SIZEOF_HEADERS.*$/& . += 56;/' > shuffle1.lds +$CCLINK -o shuffle1 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle1lib2.so \ + -Wl,-T,shuffle1.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle1 > shuffle1.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle1 >> shuffle1.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle1.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle1 || exit 3 +fi +readelf -a ./shuffle1 >> shuffle1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle1 +comparelibs >> shuffle1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle2.c b/trunk/testsuite/shuffle2.c new file mode 100644 index 0000000..c9f03ce --- /dev/null +++ b/trunk/testsuite/shuffle2.c @@ -0,0 +1,27 @@ +#include "reloc1.h" +#include <stdlib.h> + +extern char testzero[16384]; + +int main() +{ + int i; + if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + for (i = 0; i < 16384; ++i) + if (testzero[i]) + abort (); + exit (0); +} + +#ifdef __arm__ +asm (".section nonalloced,\"aw\",%nobits\n\t" + ".globl testzero\n\t" + "testzero: .skip 16384"); +#else +asm (".section nonalloced,\"aw\",@nobits\n\t" + ".globl testzero\n\t" + "testzero: .skip 16384"); +#endif diff --git a/trunk/testsuite/shuffle2.sh b/trunk/testsuite/shuffle2.sh new file mode 100755 index 0000000..fdaf03e --- /dev/null +++ b/trunk/testsuite/shuffle2.sh @@ -0,0 +1,29 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# Kernels before 2.4.10 are known not to work +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in + [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; + esac +fi +rm -f shuffle2 shuffle2lib*.so shuffle2.log shuffle2.lds +$CC -shared -O2 -fpic -o shuffle2lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle2lib2.so $srcdir/reloc1lib2.c shuffle2lib1.so +BINS="shuffle2" +LIBS="shuffle2lib1.so shuffle2lib2.so" +$CCLINK -o shuffle2 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle2lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/0x08048000/0x08000000/;s/SIZEOF_HEADERS.*$/& . += 56;/' > shuffle2.lds +$CCLINK -o shuffle2 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle2lib2.so \ + -Wl,-T,shuffle2.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle2 > shuffle2.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle2 >> shuffle2.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle2.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle2 || exit 3 +fi +readelf -a ./shuffle2 >> shuffle2.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle2 +comparelibs >> shuffle2.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle3.sh b/trunk/testsuite/shuffle3.sh new file mode 100755 index 0000000..989bfcb --- /dev/null +++ b/trunk/testsuite/shuffle3.sh @@ -0,0 +1,30 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# Kernels before 2.4.10 are known not to work +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in + [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; + esac +fi +rm -f shuffle3 shuffle3lib*.so shuffle3.log shuffle3.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle3lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle3lib2.so $srcdir/reloc1lib2.c shuffle3lib1.so +BINS="shuffle3" +LIBS="shuffle3lib1.so shuffle3lib2.so" +$CCLINK -o shuffle3 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle3lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/0x08048000/0x08000000/' > shuffle3.lds +$CCLINK -o shuffle3 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle3lib2.so \ + -Wl,-T,shuffle3.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle3 > shuffle3.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle3 >> shuffle3.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle3.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle3 || exit 3 +fi +readelf -a ./shuffle3 >> shuffle3.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle3 +comparelibs >> shuffle3.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle4.sh b/trunk/testsuite/shuffle4.sh new file mode 100755 index 0000000..781431c --- /dev/null +++ b/trunk/testsuite/shuffle4.sh @@ -0,0 +1,22 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# Kernels before 2.4.10 are known not to work +if [ "x$CROSS" = "x" ]; then + case "`uname -r`" in + [01].*|2.[0-3].*|2.4.[0-9]|2.4.[0-9][^0-9]*) exit 77;; + esac +fi +rm -f shuffle4 shuffle4.log +BINS="shuffle4" +$CCLINK -o shuffle4 $srcdir/shuffle2.c -Wl,--rpath-link,. shuffle3lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle4 > shuffle4.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle4 >> shuffle4.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle4.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle4 || exit 3 +fi +readelf -a ./shuffle4 >> shuffle4.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle4 +comparelibs >> shuffle4.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle5.sh b/trunk/testsuite/shuffle5.sh new file mode 100755 index 0000000..db722e8 --- /dev/null +++ b/trunk/testsuite/shuffle5.sh @@ -0,0 +1,24 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f shuffle5 shuffle5lib*.so shuffle5.log shuffle5.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle5lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle5lib2.so $srcdir/reloc1lib2.c shuffle5lib1.so +BINS="shuffle5" +LIBS="shuffle5lib1.so shuffle5lib2.so" +$CCLINK -o shuffle5 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle5lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/0x08048000/0x08000000/;s/SIZEOF_HEADERS.*$/& . += 180;/' > shuffle5.lds +$CCLINK -o shuffle5 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle5lib2.so \ + -Wl,-T,shuffle5.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle5 > shuffle5.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle5 >> shuffle5.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle5.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle5 || exit 3 +fi +readelf -a ./shuffle5 >> shuffle5.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle5 +comparelibs >> shuffle5.log 2>&1 || exit 5 diff --git a/trunk/testsuite/shuffle6.sh b/trunk/testsuite/shuffle6.sh new file mode 100755 index 0000000..eb28d62 --- /dev/null +++ b/trunk/testsuite/shuffle6.sh @@ -0,0 +1,37 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f shuffle6 shuffle6lib*.so shuffle6.log shuffle6.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle6lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle6lib2.so $srcdir/reloc1lib2.c shuffle6lib1.so +BINS="shuffle6" +LIBS="shuffle6lib1.so shuffle6lib2.so" +$CCLINK -o shuffle6 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle6lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e 's/0x08048000/0x08000000/;s/SIZEOF_HEADERS.*$/& . += 56;/' > shuffle6.lds +$CCLINK -o shuffle6 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle6lib2.so \ + -Wl,-T,shuffle6.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 > shuffle6.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle6.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle6 || exit 3 +fi +readelf -a ./shuffle6 >> shuffle6.log 2>&1 || exit 4 +comparelibs >> shuffle6.log 2>&1 || exit 5 +for l in shuffle6lib{1,2}.so{,.orig}; do mv -f $l $l.first; done +cp -p shuffle6 shuffle6.first +$CC -shared -O2 -fpic -o shuffle6lib1.so $srcdir/shuffle6lib1.c +$CC -shared -O2 -fpic -o shuffle6lib2.so $srcdir/shuffle6lib2.c shuffle6lib1.so +for l in shuffle6lib{1,2}.so; do cp -p $l $l.orig; done +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle6 >> shuffle6.log 2>&1 || exit 6 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle6.log && exit 7 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle6 || exit 8 +fi +readelf -a ./shuffle6 >> shuffle6.log 2>&1 || exit 9 +# So that it is not prelinked again +chmod -x ./shuffle6 +comparelibs >> shuffle6.log 2>&1 || exit 10 diff --git a/trunk/testsuite/shuffle6lib1.c b/trunk/testsuite/shuffle6lib1.c new file mode 100644 index 0000000..8053293 --- /dev/null +++ b/trunk/testsuite/shuffle6lib1.c @@ -0,0 +1,20 @@ +#include "reloc1.h" + +int bar = 26; +int baz = 28; +#define M(i) int b##i, *pb##i = &b##i; +M(0) M(1) M(2) M(3) M(4) M(5) M(6) M(7) M(8) M(9) +M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19) +#undef M + +struct A foo = { 1, &foo, &bar }; + +int f1 (void) +{ + return 1; +} + +int f2 (void) +{ + return f1 () + 1; +} diff --git a/trunk/testsuite/shuffle6lib2.c b/trunk/testsuite/shuffle6lib2.c new file mode 100644 index 0000000..ed18f6b --- /dev/null +++ b/trunk/testsuite/shuffle6lib2.c @@ -0,0 +1,16 @@ +#include "reloc1.h" +#include <stdlib.h> + +#define M(i) int b##i; extern *pb##i; +M(0) M(1) M(2) M(3) M(4) M(5) M(6) M(7) M(8) M(9) +M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19) +#undef M + +int f1 (void) +{ +#define M(i) if (pb##i != &b##i) abort (); +M(0) M(1) M(2) M(3) M(4) M(5) M(6) M(7) M(8) M(9) +M(10) M(11) M(12) M(13) M(14) M(15) M(16) M(17) M(18) M(19) +#undef M + return 11; +} diff --git a/trunk/testsuite/shuffle7.sh b/trunk/testsuite/shuffle7.sh new file mode 100755 index 0000000..c6449c8 --- /dev/null +++ b/trunk/testsuite/shuffle7.sh @@ -0,0 +1,50 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f shuffle7 shuffle7lib*.so shuffle7.log shuffle7.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle7lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle7lib2.so $srcdir/reloc1lib2.c shuffle7lib1.so +BINS="shuffle7" +LIBS="shuffle7lib1.so shuffle7lib2.so" +$CCLINK -o shuffle7 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle7lib2.so \ + -Wl,--verbose 2>&1 | sed -e '/^=========/,/^=========/!d;/^=========/d' \ + -e '/\.hash/a\ + . = . + 0x300;' > shuffle7.lds +$CCLINK -o shuffle7 $srcdir/reloc1.c -Wl,--rpath-link,. shuffle7lib2.so \ + -Wl,-T,shuffle7.lds +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 > shuffle7.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 3 +fi +readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 4 +comparelibs >> shuffle7.log 2>&1 || exit 5 +for l in shuffle7lib{1,2}.so{,.orig}; do mv -f $l $l.first; done +cp -p shuffle7 shuffle7.first +$CC -shared -O2 -fpic -o shuffle7lib1.so $srcdir/shuffle6lib1.c +$CC -shared -O2 -fpic -o shuffle7lib2.so $srcdir/shuffle6lib2.c shuffle7lib1.so +for l in shuffle7lib{1,2}.so; do cp -p $l $l.orig; done +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 6 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 7 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 8 +fi +readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 9 +comparelibs >> shuffle7.log 2>&1 || exit 10 +for l in shuffle7lib{1,2}.so{,.orig}; do mv -f $l $l.second; done +cp -p shuffle7 shuffle7.second +for l in shuffle7lib{1,2}.so{,.orig}; do cp -p $l.first $l; done +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle7 >> shuffle7.log 2>&1 || exit 11 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle7.log && exit 12 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle7 || exit 13 +fi +readelf -a ./shuffle7 >> shuffle7.log 2>&1 || exit 14 +comparelibs >> shuffle7.log 2>&1 || exit 15 +cmp -s shuffle7{,.first} || exit 16 +# So that it is not prelinked again +chmod -x ./shuffle7 diff --git a/trunk/testsuite/shuffle8.c b/trunk/testsuite/shuffle8.c new file mode 100644 index 0000000..4e80184 --- /dev/null +++ b/trunk/testsuite/shuffle8.c @@ -0,0 +1,20 @@ +#include "reloc1.h" +#include <stdlib.h> + +static struct A local = { 77, &local, &bar + 4 }; +int vbss[16384] __attribute__((aligned (4096))); +int vdata __attribute__((aligned (4096))) = 5; + +asm (".text; .balign 4096; vtext:; .previous"); + +int main() +{ + if (foo.a != 1 || foo.b != &foo || foo.c != &bar || bar != 26) + abort (); + if (f1 () != 11 || f2 () != 12) + abort (); + local.c -= 4; + if (local.a != 77 || local.b != &local || local.c != &bar) + abort (); + exit (vbss[31] + vdata - 5); +} diff --git a/trunk/testsuite/shuffle8.sh b/trunk/testsuite/shuffle8.sh new file mode 100755 index 0000000..51dcc4c --- /dev/null +++ b/trunk/testsuite/shuffle8.sh @@ -0,0 +1,21 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f shuffle8 shuffle8lib*.so shuffle8.log shuffle8.lds +rm -f prelink.cache +$CC -shared -O2 -fpic -o shuffle8lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o shuffle8lib2.so $srcdir/reloc1lib2.c shuffle8lib1.so +BINS="shuffle8" +LIBS="shuffle8lib1.so shuffle8lib2.so" +$CCLINK -o shuffle8 $srcdir/shuffle8.c -Wl,--rpath-link,. shuffle8lib2.so +$STRIP -R .comment shuffle8 +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./shuffle8 > shuffle8.log +$PRELINK ${PRELINK_OPTS--vm} ./shuffle8 >> shuffle8.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` shuffle8.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./shuffle8 || exit 3 +fi +readelf -a ./shuffle8 >> shuffle8.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./shuffle8 +comparelibs >> shuffle8.log 2>&1 || exit 5 diff --git a/trunk/testsuite/tls1.c b/trunk/testsuite/tls1.c new file mode 100644 index 0000000..08bd26f --- /dev/null +++ b/trunk/testsuite/tls1.c @@ -0,0 +1,36 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy = 12; +__thread struct A local = { 1, 2, 3 }; + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int main() +{ + struct A *p; + if (local.a != 1 || local.b != 2 || local.c != 3) + abort (); + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + check1 (); + check2 (); + if (f1a () != &a1 || f2a () != &a2 || f3a () != &a3 || f4a () != &a4) + abort (); + CHECK (5, 16); + CHECK (6, 19); + if (f7a () != &a2 || f8a () != &a4) + abort (); + CHECK (9, 28); + CHECK (10, 31); + exit (0); +} diff --git a/trunk/testsuite/tls1.h b/trunk/testsuite/tls1.h new file mode 100644 index 0000000..d627340 --- /dev/null +++ b/trunk/testsuite/tls1.h @@ -0,0 +1,30 @@ +struct A + { + char a; + int b; + long long c; + }; + +extern __thread struct A a1, a2, a3, a4; +extern struct A *f1a (void); +extern struct A *f2a (void); +extern struct A *f3a (void); +extern struct A *f4a (void); +extern struct A *f5a (void); +extern struct A *f6a (void); +extern struct A *f7a (void); +extern struct A *f8a (void); +extern struct A *f9a (void); +extern struct A *f10a (void); +extern int f1b (void); +extern int f2b (void); +extern int f3b (void); +extern int f4b (void); +extern int f5b (void); +extern int f6b (void); +extern int f7b (void); +extern int f8b (void); +extern int f9b (void); +extern int f10b (void); +extern void check1 (void); +extern void check2 (void); diff --git a/trunk/testsuite/tls1.sh b/trunk/testsuite/tls1.sh new file mode 100755 index 0000000..f3d2113 --- /dev/null +++ b/trunk/testsuite/tls1.sh @@ -0,0 +1,25 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls1 tls1lib*.so tls1.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o tls1lib1.so $srcdir/tls1lib1.c +$CC -shared -O2 -fpic -o tls1lib2.so $srcdir/tls1lib2.c tls1lib1.so +BINS="tls1" +LIBS="tls1lib1.so tls1lib2.so" +$CCLINK -o tls1 $srcdir/tls1.c -Wl,--rpath-link,. tls1lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls1 > tls1.log +$PRELINK ${PRELINK_OPTS--vm} ./tls1 >> tls1.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls1.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls1 || exit 3 +fi +readelf -a ./tls1 >> tls1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./tls1 +comparelibs >> tls1.log 2>&1 || exit 5 diff --git a/trunk/testsuite/tls1lib1.c b/trunk/testsuite/tls1lib1.c new file mode 100644 index 0000000..eb0734b --- /dev/null +++ b/trunk/testsuite/tls1lib1.c @@ -0,0 +1,89 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 13, 14, 15 }; +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A *f1a (void) +{ + return &a1; +} + +struct A *f2a (void) +{ + return &a2; +} + +struct A *f3a (void) +{ + return &a3; +} + +struct A *f4a (void) +{ + return &a4; +} + +struct A *f5a (void) +{ + return &local1; +} + +struct A *f6a (void) +{ + return &local2; +} + +int f1b (void) +{ + return a1.a; +} + +int f2b (void) +{ + return a2.b; +} + +int f3b (void) +{ + return a3.c; +} + +int f4b (void) +{ + return a4.a; +} + +int f5b (void) +{ + return local1.b; +} + +int f6b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls1lib2.c b/trunk/testsuite/tls1lib2.c new file mode 100644 index 0000000..eee03a9 --- /dev/null +++ b/trunk/testsuite/tls1lib2.c @@ -0,0 +1,62 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread long long dummy = 12; +__thread struct A a2 = { 22, 23, 24 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 25, 26, 27 }; +static __thread struct A local1 = { 28, 29, 30 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 31, 32, 33 }; + +void check2 (void) +{ + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 28 || local1.b != 29 || local1.c != 30) + abort (); + if (local2.a != 31 || local2.b != 32 || local2.c != 33) + abort (); +} + +struct A *f7a (void) +{ + return &a2; +} + +struct A *f8a (void) +{ + return &a4; +} + +struct A *f9a (void) +{ + return &local1; +} + +struct A *f10a (void) +{ + return &local2; +} + +int f7b (void) +{ + return a2.b; +} + +int f8b (void) +{ + return a4.a; +} + +int f9b (void) +{ + return local1.b; +} + +int f10b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls2.c b/trunk/testsuite/tls2.c new file mode 100644 index 0000000..1246165 --- /dev/null +++ b/trunk/testsuite/tls2.c @@ -0,0 +1,25 @@ +#include "tls1.h" +#include <stdlib.h> + +#define CHECK(N, S) \ + p = f##N##a (); \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int main() +{ + struct A *p; + check1 (); + check2 (); + CHECK (1, 4); + CHECK (2, 22); + CHECK (3, 10); + CHECK (4, 25); + CHECK (5, 16); + CHECK (6, 19); + CHECK (7, 22); + CHECK (8, 25); + CHECK (9, 28); + CHECK (10, 31); + exit (0); +} diff --git a/trunk/testsuite/tls2.sh b/trunk/testsuite/tls2.sh new file mode 100755 index 0000000..4b515b0 --- /dev/null +++ b/trunk/testsuite/tls2.sh @@ -0,0 +1,26 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls2 tls2lib*.so tls2.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o tls2lib1.so $srcdir/tls2lib1.c +$CC -shared -O2 -fpic -o tls2lib2.so $srcdir/tls1lib2.c tls2lib1.so +BINS="tls2" +LIBS="tls2lib1.so tls2lib2.so" +$CCLINK -o tls2 $srcdir/tls2.c -Wl,--rpath-link,. tls2lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls2 > tls2.log +$PRELINK ${PRELINK_OPTS--vm} ./tls2 >> tls2.log 2>&1 || exit 1 +grep -v 'has undefined non-weak symbols' tls2.log \ + | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls2 || exit 3 +fi +readelf -a ./tls2 >> tls2.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./tls2 +comparelibs >> tls2.log 2>&1 || exit 5 diff --git a/trunk/testsuite/tls2lib1.c b/trunk/testsuite/tls2lib1.c new file mode 100644 index 0000000..24b7555 --- /dev/null +++ b/trunk/testsuite/tls2lib1.c @@ -0,0 +1,87 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +extern __thread struct A a4 __attribute__((tls_model("initial-exec"))); +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; + +void check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); +} + +struct A *f1a (void) +{ + return &a1; +} + +struct A *f2a (void) +{ + return &a2; +} + +struct A *f3a (void) +{ + return &a3; +} + +struct A *f4a (void) +{ + return &a4; +} + +struct A *f5a (void) +{ + return &local1; +} + +struct A *f6a (void) +{ + return &local2; +} + +int f1b (void) +{ + return a1.a; +} + +int f2b (void) +{ + return a2.b; +} + +int f3b (void) +{ + return a3.c; +} + +int f4b (void) +{ + return a4.a; +} + +int f5b (void) +{ + return local1.b; +} + +int f6b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls3.sh b/trunk/testsuite/tls3.sh new file mode 100755 index 0000000..e7270e9 --- /dev/null +++ b/trunk/testsuite/tls3.sh @@ -0,0 +1,30 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +SHFLAGS= +case "`uname -m`" in + ia64|ppc*|x86_64|alpha*|s390*|mips*) SHFLAGS=-fpic;; # Does not support non-pic shared libs +esac +rm -f tls3 tls3lib*.so tls3.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o tls3lib1.so $srcdir/tls1lib1.c +$CC -shared -O2 $SHFLAGS -o tls3lib2.so $srcdir/tls3lib2.c \ + tls3lib1.so 2>/dev/null +BINS="tls3" +LIBS="tls3lib1.so tls3lib2.so" +$CCLINK -o tls3 $srcdir/tls1.c -Wl,--rpath-link,. tls3lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls3 > tls3.log +$PRELINK ${PRELINK_OPTS--vm} ./tls3 >> tls3.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls3.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls3 || exit 3 +fi +readelf -a ./tls3 >> tls3.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./tls3 +comparelibs >> tls3.log 2>&1 || exit 5 diff --git a/trunk/testsuite/tls3lib2.c b/trunk/testsuite/tls3lib2.c new file mode 100644 index 0000000..ba485d3 --- /dev/null +++ b/trunk/testsuite/tls3lib2.c @@ -0,0 +1,68 @@ +#include "tls1.h" +#include <stdlib.h> + +asm (".section trampoline, \"awx\"; .previous"); + +#if !defined __sparc__ || defined __pic__ || defined __PIC__ +#define ieattr __attribute__((tls_model("initial-exec"))) +#else +#define ieattr +#endif + +static __thread long long dummy = 12; +__thread struct A a2 = { 22, 23, 24 }; +__thread struct A a4 ieattr = { 25, 26, 27 }; +static __thread struct A local1 = { 28, 29, 30 }; +static __thread struct A local2 ieattr = { 31, 32, 33 }; + +void __attribute__((section ("trampoline"))) check2 (void) +{ + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 28 || local1.b != 29 || local1.c != 30) + abort (); + if (local2.a != 31 || local2.b != 32 || local2.c != 33) + abort (); +} + +struct A * __attribute__((section ("trampoline"))) f7a (void) +{ + return &a2; +} + +struct A * __attribute__((section ("trampoline"))) f8a (void) +{ + return &a4; +} + +struct A * __attribute__((section ("trampoline"))) f9a (void) +{ + return &local1; +} + +struct A * __attribute__((section ("trampoline"))) f10a (void) +{ + return &local2; +} + +int __attribute__((section ("trampoline"))) f7b (void) +{ + return a2.b; +} + +int __attribute__((section ("trampoline"))) f8b (void) +{ + return a4.a; +} + +int __attribute__((section ("trampoline"))) f9b (void) +{ + return local1.b; +} + +int __attribute__((section ("trampoline"))) f10b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls4.c b/trunk/testsuite/tls4.c new file mode 100644 index 0000000..0882f07 --- /dev/null +++ b/trunk/testsuite/tls4.c @@ -0,0 +1,16 @@ +#include "tls1.h" +#include <stdlib.h> + +#define CHECK(N, S) \ + p = &a##N; \ + if (p->a != S || p->b != S + 1 || p->c != S + 2) \ + abort () + +int main() +{ + struct A *p; + check1 (); + CHECK (1, 4); + CHECK (2, 7); + exit (0); +} diff --git a/trunk/testsuite/tls4.sh b/trunk/testsuite/tls4.sh new file mode 100755 index 0000000..e6bdde2 --- /dev/null +++ b/trunk/testsuite/tls4.sh @@ -0,0 +1,26 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls4 tls4lib*.so tls4.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o tls4lib1.so $srcdir/tls4lib1.c +$CC -shared -O2 -fpic -o tls4lib2.so $srcdir/tls4lib2.c \ + tls4lib1.so 2>/dev/null +BINS="tls4" +LIBS="tls4lib1.so tls4lib2.so" +$CCLINK -o tls4 $srcdir/tls4.c -Wl,--rpath-link,. tls4lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls4 > tls4.log +$PRELINK ${PRELINK_OPTS--vm} ./tls4 >> tls4.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls4.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls4 || exit 3 +fi +readelf -a ./tls4 >> tls4.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./tls4 +comparelibs >> tls4.log 2>&1 || exit 5 diff --git a/trunk/testsuite/tls4lib1.c b/trunk/testsuite/tls4lib1.c new file mode 100644 index 0000000..a03af0b --- /dev/null +++ b/trunk/testsuite/tls4lib1.c @@ -0,0 +1,5 @@ +#include "tls1.h" +#include <stdlib.h> + +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; diff --git a/trunk/testsuite/tls4lib2.c b/trunk/testsuite/tls4lib2.c new file mode 100644 index 0000000..309504b --- /dev/null +++ b/trunk/testsuite/tls4lib2.c @@ -0,0 +1,12 @@ +#include "tls1.h" +#include <stdlib.h> + +extern __thread struct A a2 __attribute__((tls_model("initial-exec"))); + +void check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 7 || a2.b != 8 || a2.c != 9) + abort (); +} diff --git a/trunk/testsuite/tls5.sh b/trunk/testsuite/tls5.sh new file mode 100755 index 0000000..68ec82f --- /dev/null +++ b/trunk/testsuite/tls5.sh @@ -0,0 +1,34 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls5 tls5lib*.so tls5.log +rm -f prelink.cache +echo 'int tls5;' | $CC -shared -O2 -fpic -xc - -o tls5lib3.so +$CC -shared -O2 -fpic -o tls5lib1.so $srcdir/tls5lib1.c tls5lib3.so +$CC -shared -O2 -fpic -o tls5lib2.so $srcdir/tls1lib2.c \ + -Wl,--rpath-link,. tls5lib1.so +BINS="tls5" +LIBS="tls5lib1.so tls5lib2.so tls5lib3.so" +$CCLINK -o tls5 $srcdir/tls1.c -Wl,--rpath-link,. tls5lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls5 > tls5.log +$PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls5.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls5 || exit 3 +fi +$PRELINK -u tls5lib3.so || exit 4 +echo $PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log +$PRELINK ${PRELINK_OPTS--vm} ./tls5 >> tls5.log 2>&1 || exit 5 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls5.log && exit 6 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls5 || exit 7 +fi +readelf -a ./tls5 >> tls5.log 2>&1 || exit 8 +# So that it is not prelinked again +chmod -x ./tls5 +comparelibs >> tls5.log 2>&1 || exit 9 diff --git a/trunk/testsuite/tls5lib1.c b/trunk/testsuite/tls5lib1.c new file mode 100644 index 0000000..9677848 --- /dev/null +++ b/trunk/testsuite/tls5lib1.c @@ -0,0 +1,96 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a2 = { 7, 8, 9 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +__thread struct A a4 __attribute__((tls_model("initial-exec"))) + = { 13, 14, 15 }; +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; +struct Z { char a; struct Z *b; int *c; }; +int y[2]; +struct Z z[2] = { { 1, &z[1], &y[0] }, { 2, &z[0], &y[1] } }; + +void check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); + if (z[0].a != 1 || z[0].b != &z[1] || z[0].c != &y[0]) + abort (); + if (z[1].a != 2 || z[1].b != &z[0] || z[1].c != &y[1]) + abort (); +} + +struct A *f1a (void) +{ + return &a1; +} + +struct A *f2a (void) +{ + return &a2; +} + +struct A *f3a (void) +{ + return &a3; +} + +struct A *f4a (void) +{ + return &a4; +} + +struct A *f5a (void) +{ + return &local1; +} + +struct A *f6a (void) +{ + return &local2; +} + +int f1b (void) +{ + return a1.a; +} + +int f2b (void) +{ + return a2.b; +} + +int f3b (void) +{ + return a3.c; +} + +int f4b (void) +{ + return a4.a; +} + +int f5b (void) +{ + return local1.b; +} + +int f6b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls6.sh b/trunk/testsuite/tls6.sh new file mode 100755 index 0000000..60ae492 --- /dev/null +++ b/trunk/testsuite/tls6.sh @@ -0,0 +1,36 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls6 tls6lib*.so tls6.log +rm -f prelink.cache +echo 'int tls6;' | $CC -shared -O2 -fpic -xc - -o tls6lib3.so +$CC -shared -O2 -fpic -o tls6lib1.so $srcdir/tls6lib1.c tls6lib3.so +$CC -shared -O2 -fpic -o tls6lib2.so $srcdir/tls1lib2.c \ + -Wl,--rpath-link,. tls6lib1.so +BINS="tls6" +LIBS="tls6lib1.so tls6lib2.so tls6lib3.so" +$CCLINK -o tls6 $srcdir/tls2.c -Wl,--rpath-link,. tls6lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls6 > tls6.log +$PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log 2>&1 || exit 1 +grep -v 'has undefined non-weak symbols' tls6.log \ + | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls6 || exit 3 +fi +$PRELINK -u tls6lib3.so || exit 4 +echo $PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log +$PRELINK ${PRELINK_OPTS--vm} ./tls6 >> tls6.log 2>&1 || exit 5 +grep -v 'has undefined non-weak symbols' tls6.log \ + | grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` && exit 6 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls6 || exit 7 +fi +readelf -a ./tls6 >> tls6.log 2>&1 || exit 8 +# So that it is not prelinked again +chmod -x ./tls6 +comparelibs >> tls6.log 2>&1 || exit 9 diff --git a/trunk/testsuite/tls6lib1.c b/trunk/testsuite/tls6lib1.c new file mode 100644 index 0000000..5310c06 --- /dev/null +++ b/trunk/testsuite/tls6lib1.c @@ -0,0 +1,94 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy = 12; +__thread struct A a1 = { 4, 5, 6 }; +__thread struct A a3 __attribute__((tls_model("initial-exec"))) + = { 10, 11, 12 }; +extern __thread struct A a4 __attribute__((tls_model("initial-exec"))); +static __thread struct A local1 = { 16, 17, 18 }; +static __thread struct A local2 __attribute__((tls_model("initial-exec"))) + = { 19, 20, 21 }; +struct Z { char a; struct Z *b; int *c; }; +int y[2]; +struct Z z[2] = { { 1, &z[1], &y[0] }, { 2, &z[0], &y[1] } }; + +void check1 (void) +{ + if (a1.a != 4 || a1.b != 5 || a1.c != 6) + abort (); + if (a2.a != 22 || a2.b != 23 || a2.c != 24) + abort (); + if (a3.a != 10 || a3.b != 11 || a3.c != 12) + abort (); + if (a4.a != 25 || a4.b != 26 || a4.c != 27) + abort (); + if (local1.a != 16 || local1.b != 17 || local1.c != 18) + abort (); + if (local2.a != 19 || local2.b != 20 || local2.c != 21) + abort (); + if (z[0].a != 1 || z[0].b != &z[1] || z[0].c != &y[0]) + abort (); + if (z[1].a != 2 || z[1].b != &z[0] || z[1].c != &y[1]) + abort (); +} + +struct A *f1a (void) +{ + return &a1; +} + +struct A *f2a (void) +{ + return &a2; +} + +struct A *f3a (void) +{ + return &a3; +} + +struct A *f4a (void) +{ + return &a4; +} + +struct A *f5a (void) +{ + return &local1; +} + +struct A *f6a (void) +{ + return &local2; +} + +int f1b (void) +{ + return a1.a; +} + +int f2b (void) +{ + return a2.b; +} + +int f3b (void) +{ + return a3.c; +} + +int f4b (void) +{ + return a4.a; +} + +int f5b (void) +{ + return local1.b; +} + +int f6b (void) +{ + return local2.c; +} diff --git a/trunk/testsuite/tls7.c b/trunk/testsuite/tls7.c new file mode 100644 index 0000000..4a3db24 --- /dev/null +++ b/trunk/testsuite/tls7.c @@ -0,0 +1,10 @@ +#include "tls1.h" +#include <stdlib.h> + +static __thread int dummy; +__thread struct A local; + +int main() +{ + exit (dummy + local.a + local.b + local.c); +} diff --git a/trunk/testsuite/tls7.sh b/trunk/testsuite/tls7.sh new file mode 100755 index 0000000..216a379 --- /dev/null +++ b/trunk/testsuite/tls7.sh @@ -0,0 +1,23 @@ +#!/bin/bash +. `dirname $0`/functions.sh +# First check if __thread is supported by ld.so/gcc/ld/as: +rm -f tlstest +#echo '__thread int a; int main (void) { return a; }' \ +# | $CC -xc - -o tlstest > /dev/null 2>&1 || exit 77 +#( ./tlstest || { rm -f tlstest; exit 77; } ) 2>/dev/null || exit 77 +rm -f tls7 tls7.log +rm -f prelink.cache +BINS="tls7" +LIBS="" +$CCLINK -o tls7 $srcdir/tls7.c +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./tls7 > tls7.log +$PRELINK ${PRELINK_OPTS--vm} ./tls7 >> tls7.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` tls7.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./tls7 || exit 3 +fi +readelf -a ./tls7 >> tls7.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./tls7 +comparelibs >> tls7.log 2>&1 || exit 5 diff --git a/trunk/testsuite/undo1.sh b/trunk/testsuite/undo1.sh new file mode 100755 index 0000000..ed61b6b --- /dev/null +++ b/trunk/testsuite/undo1.sh @@ -0,0 +1,24 @@ +#!/bin/bash +. `dirname $0`/functions.sh +rm -f undo1 undo1lib*.so undo1.log +rm -f prelink.cache +$CC -shared -O2 -fpic -o undo1lib1.so $srcdir/reloc1lib1.c +$CC -shared -O2 -fpic -o undo1lib2.so $srcdir/reloc1lib2.c undo1lib1.so +BINS="undo1" +LIBS="undo1lib1.so undo1lib2.so" +$CCLINK -o undo1 $srcdir/reloc1.c -Wl,--rpath-link,. undo1lib2.so +savelibs +echo $PRELINK ${PRELINK_OPTS--vm} ./undo1 > undo1.log +$PRELINK ${PRELINK_OPTS--vm} ./undo1 >> undo1.log 2>&1 || exit 1 +grep -q ^`echo $PRELINK | sed 's/ .*$/: /'` undo1.log && exit 2 +if [ "x$CROSS" = "x" ]; then + LD_LIBRARY_PATH=. ./undo1 || exit 3 +fi +readelf -a ./undo1 >> undo1.log 2>&1 || exit 4 +# So that it is not prelinked again +chmod -x ./undo1 +echo $PRELINK -uo undo1.undo undo1 >> undo1.log +$PRELINK -uo undo1.undo undo1 >> undo1.log 2>&1 || exit 5 +cmp -s undo1.undo undo1.orig >> undo1.log 2>&1 || exit 6 +rm -f undo1.undo +comparelibs >> undo1.log 2>&1 || exit 7 diff --git a/trunk/testsuite/undosyslibs.sh b/trunk/testsuite/undosyslibs.sh new file mode 100755 index 0000000..1ce136d --- /dev/null +++ b/trunk/testsuite/undosyslibs.sh @@ -0,0 +1,4 @@ +#!/bin/bash +. `dirname $0`/functions.sh +LIBS=`cat syslib.list` +comparelibs >> undosyslibs.log 2>&1 || exit 1 |