diff --git a/packages/libelf/ar.c.patch b/packages/libelf/ar.c.patch new file mode 100644 index 000000000..226763acb --- /dev/null +++ b/packages/libelf/ar.c.patch @@ -0,0 +1,1541 @@ +diff -u -r ../elfutils-0.166/src/ar.c ./src/ar.c +--- ../elfutils-0.166/src/ar.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./src/ar.c 2016-05-04 14:29:53.035376083 -0400 +@@ -1,1536 +1 @@ +-/* Create, modify, and extract from archives. +- Copyright (C) 2005-2012 Red Hat, Inc. +- This file is part of elfutils. +- Written by Ulrich Drepper , 2005. +- +- This file is free software; you can redistribute it and/or modify +- it under the terms of the GNU General Public License as published by +- the Free Software Foundation; either version 3 of the License, or +- (at your option) any later version. +- +- elfutils is distributed in the hope that it will be useful, but +- WITHOUT ANY WARRANTY; without even the implied warranty of +- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- GNU General Public License for more details. +- +- You should have received a copy of the GNU General Public License +- along with this program. If not, see . */ +- +-#ifdef HAVE_CONFIG_H +-# include +-#endif +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-#include "arlib.h" +- +- +-/* Name and version of program. */ +-static void print_version (FILE *stream, struct argp_state *state); +-ARGP_PROGRAM_VERSION_HOOK_DEF = print_version; +- +-/* Prototypes for local functions. */ +-static int do_oper_extract (int oper, const char *arfname, char **argv, +- int argc, long int instance); +-static int do_oper_delete (const char *arfname, char **argv, int argc, +- long int instance); +-static int do_oper_insert (int oper, const char *arfname, char **argv, +- int argc, const char *member); +- +- +-/* Bug report address. */ +-ARGP_PROGRAM_BUG_ADDRESS_DEF = PACKAGE_BUGREPORT; +- +- +-/* Definitions of arguments for argp functions. */ +-static const struct argp_option options[] = +-{ +- { NULL, 0, NULL, 0, N_("Commands:"), 1 }, +- { NULL, 'd', NULL, 0, N_("Delete files from archive."), 0 }, +- { NULL, 'm', NULL, 0, N_("Move files in archive."), 0 }, +- { NULL, 'p', NULL, 0, N_("Print files in archive."), 0 }, +- { NULL, 'q', NULL, 0, N_("Quick append files to archive."), 0 }, +- { NULL, 'r', NULL, 0, +- N_("Replace existing or insert new file into archive."), 0 }, +- { NULL, 't', NULL, 0, N_("Display content of archive."), 0 }, +- { NULL, 'x', NULL, 0, N_("Extract files from archive."), 0 }, +- +- { NULL, 0, NULL, 0, N_("Command Modifiers:"), 2 }, +- { NULL, 'o', NULL, 0, N_("Preserve original dates."), 0 }, +- { NULL, 'N', NULL, 0, N_("Use instance [COUNT] of name."), 0 }, +- { NULL, 'C', NULL, 0, +- N_("Do not replace existing files with extracted files."), 0 }, +- { NULL, 'T', NULL, 0, N_("Allow filename to be truncated if necessary."), +- 0 }, +- { NULL, 'v', NULL, 0, N_("Provide verbose output."), 0 }, +- { NULL, 's', NULL, 0, N_("Force regeneration of symbol table."), 0 }, +- { NULL, 'a', NULL, 0, N_("Insert file after [MEMBER]."), 0 }, +- { NULL, 'b', NULL, 0, N_("Insert file before [MEMBER]."), 0 }, +- { NULL, 'i', NULL, 0, N_("Same as -b."), 0 }, +- { NULL, 'c', NULL, 0, N_("Suppress message when library has to be created."), +- 0 }, +- { NULL, 'P', NULL, 0, N_("Use full path for file matching."), 0 }, +- { NULL, 'u', NULL, 0, N_("Update only older files in archive."), 0 }, +- +- { NULL, 0, NULL, 0, NULL, 0 } +-}; +- +-/* Short description of program. */ +-static const char doc[] = N_("Create, modify, and extract from archives."); +- +-/* Strings for arguments in help texts. */ +-static const char args_doc[] = N_("[MEMBER] [COUNT] ARCHIVE [FILE...]"); +- +-/* Prototype for option handler. */ +-static error_t parse_opt (int key, char *arg, struct argp_state *state); +- +-/* Data structure to communicate with argp functions. */ +-static struct argp argp = +-{ +- options, parse_opt, args_doc, doc, arlib_argp_children, NULL, NULL +-}; +- +- +-/* What operation to perform. */ +-static enum +- { +- oper_none, +- oper_delete, +- oper_move, +- oper_print, +- oper_qappend, +- oper_replace, +- oper_list, +- oper_extract +- } operation; +- +-/* Modifiers. */ +-static bool verbose; +-static bool preserve_dates; +-static bool instance_specifed; +-static bool dont_replace_existing; +-static bool allow_truncate_fname; +-static bool force_symtab; +-static bool suppress_create_msg; +-static bool full_path; +-static bool update_newer; +-static enum { ipos_none, ipos_before, ipos_after } ipos; +- +- +-int +-main (int argc, char *argv[]) +-{ +- /* We use no threads here which can interfere with handling a stream. */ +- (void) __fsetlocking (stdin, FSETLOCKING_BYCALLER); +- (void) __fsetlocking (stdout, FSETLOCKING_BYCALLER); +- (void) __fsetlocking (stderr, FSETLOCKING_BYCALLER); +- +- /* Set locale. */ +- (void) setlocale (LC_ALL, ""); +- +- /* Make sure the message catalog can be found. */ +- (void) bindtextdomain (PACKAGE_TARNAME, LOCALEDIR); +- +- /* Initialize the message catalog. */ +- (void) textdomain (PACKAGE_TARNAME); +- +- /* For historical reasons the options in the first parameter need +- not be preceded by a dash. Add it now if necessary. */ +- if (argc > 1 && argv[1][0] != '-') +- { +- size_t len = strlen (argv[1]) + 1; +- char *newp = alloca (len + 1); +- newp[0] = '-'; +- memcpy (&newp[1], argv[1], len); +- argv[1] = newp; +- } +- +- /* Parse and process arguments. */ +- int remaining; +- (void) argp_parse (&argp, argc, argv, ARGP_IN_ORDER, &remaining, NULL); +- +- /* Tell the library which version we are expecting. */ +- (void) elf_version (EV_CURRENT); +- +- /* Handle the [MEMBER] parameter. */ +- const char *member = NULL; +- if (ipos != ipos_none) +- { +- /* Only valid for certain operations. */ +- if (operation != oper_move && operation != oper_replace) +- error (1, 0, gettext ("\ +-'a', 'b', and 'i' are only allowed with the 'm' and 'r' options")); +- +- if (remaining == argc) +- { +- error (0, 0, gettext ("\ +-MEMBER parameter required for 'a', 'b', and 'i' modifiers")); +- argp_help (&argp, stderr, ARGP_HELP_USAGE | ARGP_HELP_SEE, +- program_invocation_short_name); +- exit (EXIT_FAILURE); +- } +- +- member = argv[remaining++]; +- } +- +- /* Handle the [COUNT] parameter. */ +- long int instance = -1; +- if (instance_specifed) +- { +- /* Only valid for certain operations. */ +- if (operation != oper_extract && operation != oper_delete) +- error (1, 0, gettext ("\ +-'N' is only meaningful with the 'x' and 'd' options")); +- +- if (remaining == argc) +- { +- error (0, 0, gettext ("COUNT parameter required")); +- argp_help (&argp, stderr, ARGP_HELP_SEE, +- program_invocation_short_name); +- exit (EXIT_FAILURE); +- } +- +- char *endp; +- errno = 0; +- if (((instance = strtol (argv[remaining], &endp, 10)) == LONG_MAX +- && errno == ERANGE) +- || instance <= 0 +- || *endp != '\0') +- error (1, 0, gettext ("invalid COUNT parameter %s"), argv[remaining]); +- +- ++remaining; +- } +- +- if ((dont_replace_existing || allow_truncate_fname) +- && unlikely (operation != oper_extract)) +- error (1, 0, gettext ("'%c' is only meaningful with the 'x' option"), +- dont_replace_existing ? 'C' : 'T'); +- +- /* There must at least be one more parameter specifying the archive. */ +- if (remaining == argc) +- { +- error (0, 0, gettext ("archive name required")); +- argp_help (&argp, stderr, ARGP_HELP_SEE, program_invocation_short_name); +- exit (EXIT_FAILURE); +- } +- +- const char *arfname = argv[remaining++]; +- argv += remaining; +- argc -= remaining; +- +- int status; +- switch (operation) +- { +- case oper_none: +- error (0, 0, gettext ("command option required")); +- argp_help (&argp, stderr, ARGP_HELP_STD_ERR, +- program_invocation_short_name); +- status = 1; +- break; +- +- case oper_list: +- case oper_print: +- status = do_oper_extract (operation, arfname, argv, argc, -1); +- break; +- +- case oper_extract: +- status = do_oper_extract (operation, arfname, argv, argc, instance); +- break; +- +- case oper_delete: +- status = do_oper_delete (arfname, argv, argc, instance); +- break; +- +- case oper_move: +- case oper_qappend: +- case oper_replace: +- status = do_oper_insert (operation, arfname, argv, argc, member); +- break; +- +- default: +- assert (! "should not happen"); +- status = 1; +- break; +- } +- +- return status; +-} +- +- +-/* Print the version information. */ +-static void +-print_version (FILE *stream, struct argp_state *state __attribute__ ((unused))) +-{ +- fprintf (stream, "ar (%s) %s\n", PACKAGE_NAME, PACKAGE_VERSION); +- fprintf (stream, gettext ("\ +-Copyright (C) %s Red Hat, Inc.\n\ +-This is free software; see the source for copying conditions. There is NO\n\ +-warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n\ +-"), "2012"); +- fprintf (stream, gettext ("Written by %s.\n"), "Ulrich Drepper"); +-} +- +- +-/* Handle program arguments. */ +-static error_t +-parse_opt (int key, char *arg __attribute__ ((unused)), +- struct argp_state *state __attribute__ ((unused))) +-{ +- switch (key) +- { +- case 'd': +- case 'm': +- case 'p': +- case 'q': +- case 'r': +- case 't': +- case 'x': +- if (operation != oper_none) +- { +- error (0, 0, gettext ("More than one operation specified")); +- argp_help (&argp, stderr, ARGP_HELP_SEE, +- program_invocation_short_name); +- exit (EXIT_FAILURE); +- } +- +- switch (key) +- { +- case 'd': +- operation = oper_delete; +- break; +- case 'm': +- operation = oper_move; +- break; +- case 'p': +- operation = oper_print; +- break; +- case 'q': +- operation = oper_qappend; +- break; +- case 'r': +- operation = oper_replace; +- break; +- case 't': +- operation = oper_list; +- break; +- case 'x': +- operation = oper_extract; +- break; +- } +- break; +- +- case 'a': +- ipos = ipos_after; +- break; +- +- case 'b': +- case 'i': +- ipos = ipos_before; +- break; +- +- case 'c': +- suppress_create_msg = true; +- break; +- +- case 'C': +- dont_replace_existing = true; +- break; +- +- case 'N': +- instance_specifed = true; +- break; +- +- case 'o': +- preserve_dates = true; +- break; +- +- case 'P': +- full_path = true; +- break; +- +- case 's': +- force_symtab = true; +- break; +- +- case 'T': +- allow_truncate_fname = true; +- break; +- +- case 'u': +- update_newer = true; +- break; +- +- case 'v': +- verbose = true; +- break; +- +- default: +- return ARGP_ERR_UNKNOWN; +- } +- return 0; +-} +- +- +-static int +-open_archive (const char *arfname, int flags, int mode, Elf **elf, +- struct stat *st, bool miss_allowed) +-{ +- int fd = open (arfname, flags, mode); +- if (fd == -1) +- { +- if (miss_allowed) +- return -1; +- +- error (EXIT_FAILURE, errno, gettext ("cannot open archive '%s'"), +- arfname); +- } +- +- if (elf != NULL) +- { +- Elf_Cmd cmd = flags == O_RDONLY ? ELF_C_READ_MMAP : ELF_C_RDWR_MMAP; +- +- *elf = elf_begin (fd, cmd, NULL); +- if (*elf == NULL) +- error (EXIT_FAILURE, 0, gettext ("cannot open archive '%s': %s"), +- arfname, elf_errmsg (-1)); +- +- if (flags == O_RDONLY && elf_kind (*elf) != ELF_K_AR) +- error (EXIT_FAILURE, 0, gettext ("%s: not an archive file"), arfname); +- } +- +- if (st != NULL && fstat (fd, st) != 0) +- error (EXIT_FAILURE, errno, gettext ("cannot stat archive '%s'"), +- arfname); +- +- return fd; +-} +- +- +-static void +-not_found (int argc, char *argv[argc], bool found[argc]) +-{ +- for (int i = 0; i < argc; ++i) +- if (!found[i]) +- printf (gettext ("no entry %s in archive\n"), argv[i]); +-} +- +- +-static int +-copy_content (Elf *elf, int newfd, off_t off, size_t n) +-{ +- size_t len; +- char *rawfile = elf_rawfile (elf, &len); +- +- assert (off + n <= len); +- +- /* Tell the kernel we will read all the pages sequentially. */ +- size_t ps = sysconf (_SC_PAGESIZE); +- if (n > 2 * ps) +- posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL); +- +- return write_retry (newfd, rawfile + off, n) != (ssize_t) n; +-} +- +- +-static int +-do_oper_extract (int oper, const char *arfname, char **argv, int argc, +- long int instance) +-{ +- bool found[argc]; +- memset (found, '\0', sizeof (found)); +- +- size_t name_max = 0; +- inline bool should_truncate_fname (void) +- { +- if (errno == ENAMETOOLONG && allow_truncate_fname) +- { +- if (name_max == 0) +- { +- long int len = pathconf (".", _PC_NAME_MAX); +- if (len > 0) +- name_max = len; +- } +- return name_max != 0; +- } +- return false; +- } +- +- off_t index_off = -1; +- size_t index_size = 0; +- off_t cur_off = SARMAG; +- +- int status = 0; +- Elf *elf; +- int fd = open_archive (arfname, O_RDONLY, 0, &elf, NULL, false); +- +- if (hcreate (2 * argc) == 0) +- error (EXIT_FAILURE, errno, gettext ("cannot create hash table")); +- +- for (int cnt = 0; cnt < argc; ++cnt) +- { +- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] }; +- if (hsearch (entry, ENTER) == NULL) +- error (EXIT_FAILURE, errno, +- gettext ("cannot insert into hash table")); +- } +- +- struct stat st; +- if (force_symtab) +- { +- if (fstat (fd, &st) != 0) +- { +- error (0, errno, gettext ("cannot stat '%s'"), arfname); +- close (fd); +- return 1; +- } +- arlib_init (); +- } +- +- Elf_Cmd cmd = ELF_C_READ_MMAP; +- Elf *subelf; +- while ((subelf = elf_begin (fd, cmd, elf)) != NULL) +- { +- Elf_Arhdr *arhdr = elf_getarhdr (subelf); +- +- if (strcmp (arhdr->ar_name, "/") == 0) +- { +- index_off = elf_getaroff (subelf); +- index_size = arhdr->ar_size; +- goto next; +- } +- if (strcmp (arhdr->ar_name, "//") == 0) +- goto next; +- +- if (force_symtab) +- { +- arlib_add_symbols (elf, arfname, arhdr->ar_name, cur_off); +- cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1)) +- + sizeof (struct ar_hdr)); +- } +- +- bool do_extract = argc <= 0; +- if (!do_extract) +- { +- ENTRY entry; +- entry.key = arhdr->ar_name; +- ENTRY *res = hsearch (entry, FIND); +- if (res != NULL && (instance < 0 || instance-- == 0) +- && !found[(char **) res->data - argv]) +- found[(char **) res->data - argv] = do_extract = true; +- } +- +- if (do_extract) +- { +- if (verbose) +- { +- if (oper == oper_print) +- { +- printf ("\n<%s>\n\n", arhdr->ar_name); +- +- /* We have to flush now because now we use the descriptor +- directly. */ +- fflush (stdout); +- } +- else if (oper == oper_list) +- { +- char datestr[100]; +- strftime (datestr, sizeof (datestr), "%b %e %H:%M %Y", +- localtime (&arhdr->ar_date)); +- +- printf ("%c%c%c%c%c%c%c%c%c %u/%u %6ju %s %s\n", +- (arhdr->ar_mode & S_IRUSR) ? 'r' : '-', +- (arhdr->ar_mode & S_IWUSR) ? 'w' : '-', +- (arhdr->ar_mode & S_IXUSR) +- ? ((arhdr->ar_mode & S_ISUID) ? 's' : 'x') +- : ((arhdr->ar_mode & S_ISUID) ? 'S' : '-'), +- (arhdr->ar_mode & S_IRGRP) ? 'r' : '-', +- (arhdr->ar_mode & S_IWGRP) ? 'w' : '-', +- (arhdr->ar_mode & S_IXGRP) +- ? ((arhdr->ar_mode & S_ISGID) ? 's' : 'x') +- : ((arhdr->ar_mode & S_ISGID) ? 'S' : '-'), +- (arhdr->ar_mode & S_IROTH) ? 'r' : '-', +- (arhdr->ar_mode & S_IWOTH) ? 'w' : '-', +- (arhdr->ar_mode & S_IXOTH) +- ? ((arhdr->ar_mode & S_ISVTX) ? 't' : 'x') +- : ((arhdr->ar_mode & S_ISVTX) ? 'T' : '-'), +- arhdr->ar_uid, +- arhdr->ar_gid, +- (uintmax_t) arhdr->ar_size, +- datestr, +- arhdr->ar_name); +- } +- else +- printf ("x - %s\n", arhdr->ar_name); +- } +- +- if (oper == oper_list) +- { +- if (!verbose) +- puts (arhdr->ar_name); +- +- goto next; +- } +- +- size_t nleft; +- char *data = elf_rawfile (subelf, &nleft); +- if (data == NULL) +- { +- error (0, 0, gettext ("cannot read content of %s: %s"), +- arhdr->ar_name, elf_errmsg (-1)); +- status = 1; +- goto next; +- } +- +- int xfd; +- char tempfname[] = "XXXXXX"; +- bool use_mkstemp = true; +- +- if (oper == oper_print) +- xfd = STDOUT_FILENO; +- else +- { +- xfd = mkstemp (tempfname); +- if (unlikely (xfd == -1)) +- { +- /* We cannot create a temporary file. Try to overwrite +- the file or create it if it does not exist. */ +- int flags = O_WRONLY | O_CREAT; +- if (dont_replace_existing) +- flags |= O_EXCL; +- else +- flags |= O_TRUNC; +- xfd = open (arhdr->ar_name, flags, 0600); +- if (unlikely (xfd == -1)) +- { +- int printlen = INT_MAX; +- +- if (should_truncate_fname ()) +- { +- /* Try to truncate the name. First find out by how +- much. */ +- printlen = name_max; +- char truncfname[name_max + 1]; +- *((char *) mempcpy (truncfname, arhdr->ar_name, +- name_max)) = '\0'; +- +- xfd = open (truncfname, flags, 0600); +- } +- +- if (xfd == -1) +- { +- error (0, errno, gettext ("cannot open %.*s"), +- (int) printlen, arhdr->ar_name); +- status = 1; +- goto next; +- } +- } +- +- use_mkstemp = false; +- } +- } +- +- ssize_t n; +- while ((n = TEMP_FAILURE_RETRY (write (xfd, data, nleft))) != -1) +- { +- nleft -= n; +- if (nleft == 0) +- break; +- data += n; +- } +- +- if (unlikely (n == -1)) +- { +- error (0, errno, gettext ("failed to write %s"), arhdr->ar_name); +- status = 1; +- unlink (tempfname); +- close (xfd); +- goto next; +- } +- +- if (oper != oper_print) +- { +- /* Fix up the mode. */ +- if (unlikely (fchmod (xfd, arhdr->ar_mode) != 0)) +- { +- error (0, errno, gettext ("cannot change mode of %s"), +- arhdr->ar_name); +- status = 0; +- } +- +- if (preserve_dates) +- { +- struct timespec tv[2]; +- tv[0].tv_sec = arhdr->ar_date; +- tv[0].tv_nsec = 0; +- tv[1].tv_sec = arhdr->ar_date; +- tv[1].tv_nsec = 0; +- +- if (unlikely (futimens (xfd, tv) != 0)) +- { +- error (0, errno, +- gettext ("cannot change modification time of %s"), +- arhdr->ar_name); +- status = 1; +- } +- } +- +- /* If we used a temporary file, move it do the right +- name now. */ +- if (use_mkstemp) +- { +- int r; +- +- if (dont_replace_existing) +- { +- r = link (tempfname, arhdr->ar_name); +- if (likely (r == 0)) +- unlink (tempfname); +- } +- else +- r = rename (tempfname, arhdr->ar_name); +- +- if (unlikely (r) != 0) +- { +- int printlen = INT_MAX; +- +- if (should_truncate_fname ()) +- { +- /* Try to truncate the name. First find out by how +- much. */ +- printlen = name_max; +- char truncfname[name_max + 1]; +- *((char *) mempcpy (truncfname, arhdr->ar_name, +- name_max)) = '\0'; +- +- if (dont_replace_existing) +- { +- r = link (tempfname, truncfname); +- if (likely (r == 0)) +- unlink (tempfname); +- } +- else +- r = rename (tempfname, truncfname); +- } +- +- if (r != 0) +- { +- error (0, errno, gettext ("\ +-cannot rename temporary file to %.*s"), +- printlen, arhdr->ar_name); +- unlink (tempfname); +- status = 1; +- } +- } +- } +- +- close (xfd); +- } +- } +- +- next: +- cmd = elf_next (subelf); +- if (elf_end (subelf) != 0) +- error (1, 0, "%s: %s", arfname, elf_errmsg (-1)); +- } +- +- hdestroy (); +- +- if (force_symtab) +- { +- arlib_finalize (); +- +- if (symtab.symsnamelen != 0 +- /* We have to rewrite the file also if it initially had an index +- but now does not need one anymore. */ +- || (symtab.symsnamelen == 0 && index_size != 0)) +- { +- char tmpfname[strlen (arfname) + 7]; +- strcpy (stpcpy (tmpfname, arfname), "XXXXXX"); +- int newfd = mkstemp (tmpfname); +- if (unlikely (newfd == -1)) +- { +- nonew: +- error (0, errno, gettext ("cannot create new file")); +- status = 1; +- } +- else +- { +- /* Create the header. */ +- if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG)) +- { +- // XXX Use /prof/self/fd/%d ??? +- nonew_unlink: +- unlink (tmpfname); +- if (newfd != -1) +- close (newfd); +- goto nonew; +- } +- +- /* Create the new file. There are three parts as far we are +- concerned: 1. original context before the index, 2. the +- new index, 3. everything after the new index. */ +- off_t rest_off; +- if (index_off != -1) +- rest_off = (index_off + sizeof (struct ar_hdr) +- + ((index_size + 1) & ~1ul)); +- else +- rest_off = SARMAG; +- +- if ((symtab.symsnamelen != 0 +- && ((write_retry (newfd, symtab.symsoff, +- symtab.symsofflen) +- != (ssize_t) symtab.symsofflen) +- || (write_retry (newfd, symtab.symsname, +- symtab.symsnamelen) +- != (ssize_t) symtab.symsnamelen))) +- /* Even if the original file had content before the +- symbol table, we write it in the correct order. */ +- || (index_off != SARMAG +- && copy_content (elf, newfd, SARMAG, index_off - SARMAG)) +- || copy_content (elf, newfd, rest_off, st.st_size - rest_off) +- /* Set the mode of the new file to the same values the +- original file has. */ +- || fchmod (newfd, st.st_mode & ALLPERMS) != 0 +- /* Never complain about fchown failing. */ +- || (({asm ("" :: "r" (fchown (newfd, st.st_uid, +- st.st_gid))); }), +- close (newfd) != 0) +- || (newfd = -1, rename (tmpfname, arfname) != 0)) +- goto nonew_unlink; +- } +- } +- } +- +- elf_end (elf); +- +- close (fd); +- +- not_found (argc, argv, found); +- +- return status; +-} +- +- +-struct armem +-{ +- off_t off; +- off_t old_off; +- size_t size; +- long int long_name_off; +- struct armem *next; +- void *mem; +- time_t sec; +- uid_t uid; +- gid_t gid; +- mode_t mode; +- const char *name; +- Elf *elf; +-}; +- +- +-static int +-write_member (struct armem *memb, off_t *startp, off_t *lenp, Elf *elf, +- off_t end_off, int newfd) +-{ +- struct ar_hdr arhdr; +- char tmpbuf[sizeof (arhdr.ar_name) + 1]; +- +- bool changed_header = memb->long_name_off != -1; +- if (changed_header) +- { +- /* In case of a long file name we assume the archive header +- changed and we write it here. */ +- memcpy (&arhdr, elf_rawfile (elf, NULL) + *startp, sizeof (arhdr)); +- +- snprintf (tmpbuf, sizeof (tmpbuf), "/%-*ld", +- (int) sizeof (arhdr.ar_name), memb->long_name_off); +- changed_header = memcmp (arhdr.ar_name, tmpbuf, +- sizeof (arhdr.ar_name)) != 0; +- } +- +- /* If the files are adjacent in the old file extend the range. */ +- if (*startp != -1 && !changed_header && *startp + *lenp == memb->old_off) +- { +- /* Extend the current range. */ +- *lenp += (memb->next != NULL +- ? memb->next->off : end_off) - memb->off; +- return 0; +- } +- +- /* Write out the old range. */ +- if (*startp != -1 && copy_content (elf, newfd, *startp, *lenp)) +- return -1; +- +- *startp = memb->old_off; +- *lenp = (memb->next != NULL ? memb->next->off : end_off) - memb->off; +- +- if (changed_header) +- { +- memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name)); +- +- if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr)) +- != sizeof (arhdr))) +- return -1; +- +- *startp += sizeof (struct ar_hdr); +- assert ((size_t) *lenp >= sizeof (struct ar_hdr)); +- *lenp -= sizeof (struct ar_hdr); +- } +- +- return 0; +-} +- +-/* Store the name in the long name table if necessary. +- Record its offset or -1 if we did not need to use the table. */ +-static void +-remember_long_name (struct armem *mem, const char *name, size_t namelen) +-{ +- mem->long_name_off = (namelen > MAX_AR_NAME_LEN +- ? arlib_add_long_name (name, namelen) +- : -1l); +-} +- +-static int +-do_oper_delete (const char *arfname, char **argv, int argc, +- long int instance) +-{ +- bool *found = alloca (sizeof (bool) * argc); +- memset (found, '\0', sizeof (bool) * argc); +- +- /* List of the files we keep. */ +- struct armem *to_copy = NULL; +- +- int status = 0; +- Elf *elf; +- struct stat st; +- int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, false); +- +- if (hcreate (2 * argc) == 0) +- error (EXIT_FAILURE, errno, gettext ("cannot create hash table")); +- +- for (int cnt = 0; cnt < argc; ++cnt) +- { +- ENTRY entry = { .key = argv[cnt], .data = &argv[cnt] }; +- if (hsearch (entry, ENTER) == NULL) +- error (EXIT_FAILURE, errno, +- gettext ("cannot insert into hash table")); +- } +- +- arlib_init (); +- +- off_t cur_off = SARMAG; +- Elf_Cmd cmd = ELF_C_READ_MMAP; +- Elf *subelf; +- while ((subelf = elf_begin (fd, cmd, elf)) != NULL) +- { +- Elf_Arhdr *arhdr = elf_getarhdr (subelf); +- +- /* Ignore the symbol table and the long file name table here. */ +- if (strcmp (arhdr->ar_name, "/") == 0 +- || strcmp (arhdr->ar_name, "//") == 0) +- goto next; +- +- bool do_delete = argc <= 0; +- if (!do_delete) +- { +- ENTRY entry; +- entry.key = arhdr->ar_name; +- ENTRY *res = hsearch (entry, FIND); +- if (res != NULL && (instance < 0 || instance-- == 0) +- && !found[(char **) res->data - argv]) +- found[(char **) res->data - argv] = do_delete = true; +- } +- +- if (do_delete) +- { +- if (verbose) +- printf ("d - %s\n", arhdr->ar_name); +- } +- else +- { +- struct armem *newp = alloca (sizeof (struct armem)); +- newp->old_off = elf_getaroff (subelf); +- newp->off = cur_off; +- +- cur_off += (((arhdr->ar_size + 1) & ~((off_t) 1)) +- + sizeof (struct ar_hdr)); +- +- if (to_copy == NULL) +- to_copy = newp->next = newp; +- else +- { +- newp->next = to_copy->next; +- to_copy = to_copy->next = newp; +- } +- +- /* If we recreate the symbol table read the file's symbol +- table now. */ +- arlib_add_symbols (subelf, arfname, arhdr->ar_name, newp->off); +- +- /* Remember long file names. */ +- remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name)); +- } +- +- next: +- cmd = elf_next (subelf); +- if (elf_end (subelf) != 0) +- error (1, 0, "%s: %s", arfname, elf_errmsg (-1)); +- } +- +- arlib_finalize (); +- +- hdestroy (); +- +- /* Create a new, temporary file in the same directory as the +- original file. */ +- char tmpfname[strlen (arfname) + 7]; +- strcpy (stpcpy (tmpfname, arfname), "XXXXXX"); +- int newfd = mkstemp (tmpfname); +- if (unlikely (newfd == -1)) +- goto nonew; +- +- /* Create the header. */ +- if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG)) +- { +- // XXX Use /prof/self/fd/%d ??? +- nonew_unlink: +- unlink (tmpfname); +- if (newfd != -1) +- close (newfd); +- nonew: +- error (0, errno, gettext ("cannot create new file")); +- status = 1; +- goto errout; +- } +- +- /* If the archive is empty that is all we have to do. */ +- if (likely (to_copy != NULL)) +- { +- /* Write the symbol table or the long file name table or both. */ +- if (symtab.symsnamelen != 0 +- && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen) +- != (ssize_t) symtab.symsofflen) +- || (write_retry (newfd, symtab.symsname, symtab.symsnamelen) +- != (ssize_t) symtab.symsnamelen))) +- goto nonew_unlink; +- +- if (symtab.longnameslen > sizeof (struct ar_hdr) +- && (write_retry (newfd, symtab.longnames, symtab.longnameslen) +- != (ssize_t) symtab.longnameslen)) +- goto nonew_unlink; +- +- /* NULL-terminate the list of files to copy. */ +- struct armem *last = to_copy; +- to_copy = to_copy->next; +- last->next = NULL; +- +- off_t start = -1; +- off_t len = -1; +- +- do +- if (write_member (to_copy, &start, &len, elf, cur_off, newfd) != 0) +- goto nonew_unlink; +- while ((to_copy = to_copy->next) != NULL); +- +- /* Write the last part. */ +- if (copy_content (elf, newfd, start, len)) +- goto nonew_unlink; +- } +- +- /* Set the mode of the new file to the same values the original file +- has. */ +- if (fchmod (newfd, st.st_mode & ALLPERMS) != 0 +- /* Never complain about fchown failing. */ +- || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }), +- close (newfd) != 0) +- || (newfd = -1, rename (tmpfname, arfname) != 0)) +- goto nonew_unlink; +- +- errout: +-#ifdef DEBUG +- elf_end (elf); +- +- arlib_fini (); +- +- close (fd); +-#endif +- +- not_found (argc, argv, found); +- +- return status; +-} +- +- +-static void +-no0print (bool ofmt, char *buf, int bufsize, long int val) +-{ +- char tmpbuf[bufsize + 1]; +- snprintf (tmpbuf, sizeof (tmpbuf), ofmt ? "%-*lo" : "%-*ld", bufsize, val); +- memcpy (buf, tmpbuf, bufsize); +-} +- +- +-static int +-do_oper_insert (int oper, const char *arfname, char **argv, int argc, +- const char *member) +-{ +- int status = 0; +- Elf *elf; +- struct stat st; +- int fd = open_archive (arfname, O_RDONLY, 0, &elf, &st, oper != oper_move); +- +- /* List of the files we keep. */ +- struct armem *all = NULL; +- struct armem *after_memberelem = NULL; +- struct armem **found = alloca (sizeof (*found) * argc); +- memset (found, '\0', sizeof (*found) * argc); +- +- arlib_init (); +- +- /* Initialize early for no_old case. */ +- off_t cur_off = SARMAG; +- +- if (fd == -1) +- { +- if (!suppress_create_msg) +- fprintf (stderr, "%s: creating %s\n", +- program_invocation_short_name, arfname); +- +- goto no_old; +- } +- +- /* Store the names of all files from the command line in a hash +- table so that we can match it. Note that when no file name is +- given we are basically doing nothing except recreating the +- index. */ +- if (oper != oper_qappend) +- { +- if (hcreate (2 * argc) == 0) +- error (EXIT_FAILURE, errno, gettext ("cannot create hash table")); +- +- for (int cnt = 0; cnt < argc; ++cnt) +- { +- ENTRY entry; +- entry.key = full_path ? argv[cnt] : basename (argv[cnt]); +- entry.data = &argv[cnt]; +- if (hsearch (entry, ENTER) == NULL) +- error (EXIT_FAILURE, errno, +- gettext ("cannot insert into hash table")); +- } +- } +- +- /* While iterating over the current content of the archive we must +- determine a number of things: which archive members to keep, +- which are replaced, and where to insert the new members. */ +- Elf_Cmd cmd = ELF_C_READ_MMAP; +- Elf *subelf; +- while ((subelf = elf_begin (fd, cmd, elf)) != NULL) +- { +- Elf_Arhdr *arhdr = elf_getarhdr (subelf); +- +- /* Ignore the symbol table and the long file name table here. */ +- if (strcmp (arhdr->ar_name, "/") == 0 +- || strcmp (arhdr->ar_name, "//") == 0) +- goto next; +- +- struct armem *newp = alloca (sizeof (struct armem)); +- newp->old_off = elf_getaroff (subelf); +- newp->size = arhdr->ar_size; +- newp->sec = arhdr->ar_date; +- newp->mem = NULL; +- +- /* Remember long file names. */ +- remember_long_name (newp, arhdr->ar_name, strlen (arhdr->ar_name)); +- +- /* Check whether this is a file we are looking for. */ +- if (oper != oper_qappend) +- { +- /* Check whether this is the member used as the insert point. */ +- if (member != NULL && strcmp (arhdr->ar_name, member) == 0) +- { +- /* Note that all == NULL means insert at the beginning. */ +- if (ipos == ipos_before) +- after_memberelem = all; +- else +- after_memberelem = newp; +- member = NULL; +- } +- +- ENTRY entry; +- entry.key = arhdr->ar_name; +- ENTRY *res = hsearch (entry, FIND); +- if (res != NULL && found[(char **) res->data - argv] == NULL) +- { +- found[(char **) res->data - argv] = newp; +- +- /* If we insert before or after a certain element move +- all files to a special list. */ +- if (unlikely (ipos != ipos_none || oper == oper_move)) +- { +- if (after_memberelem == newp) +- /* Since we remove this element even though we should +- insert everything after it, we in fact insert +- everything after the previous element. */ +- after_memberelem = all; +- +- goto next; +- } +- } +- } +- +- if (all == NULL) +- all = newp->next = newp; +- else +- { +- newp->next = all->next; +- all = all->next = newp; +- } +- +- next: +- cmd = elf_next (subelf); +- if (elf_end (subelf) != 0) +- error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1)); +- } +- +- if (oper != oper_qappend) +- hdestroy (); +- +- no_old: +- if (member != NULL) +- error (EXIT_FAILURE, 0, gettext ("position member %s not found"), +- member); +- +- if (oper == oper_move) +- { +- /* Make sure all requested elements are found in the archive. */ +- for (int cnt = 0; cnt < argc; ++cnt) +- { +- if (found[cnt] == NULL) +- { +- fprintf (stderr, gettext ("%s: no entry %s in archive!\n"), +- program_invocation_short_name, argv[cnt]); +- status = 1; +- } +- +- if (verbose) +- printf ("m - %s\n", argv[cnt]); +- } +- } +- else +- { +- /* Open all the new files, get their sizes and add all symbols. */ +- for (int cnt = 0; cnt < argc; ++cnt) +- { +- const char *bname = basename (argv[cnt]); +- size_t bnamelen = strlen (bname); +- if (found[cnt] == NULL) +- { +- found[cnt] = alloca (sizeof (struct armem)); +- found[cnt]->old_off = -1; +- +- remember_long_name (found[cnt], bname, bnamelen); +- } +- +- struct stat newst; +- Elf *newelf; +- int newfd = open (argv[cnt], O_RDONLY); +- if (newfd == -1) +- { +- error (0, errno, gettext ("cannot open %s"), argv[cnt]); +- status = 1; +- } +- else if (fstat (newfd, &newst) == -1) +- { +- error (0, errno, gettext ("cannot stat %s"), argv[cnt]); +- close (newfd); +- status = 1; +- } +- else if (!S_ISREG (newst.st_mode)) +- { +- error (0, errno, gettext ("%s is no regular file"), argv[cnt]); +- close (newfd); +- status = 1; +- } +- else if (update_newer +- && found[cnt]->old_off != -1l +- && found[cnt]->sec > st.st_mtime) +- /* Do nothing, the file in the archive is younger. */ +- close (newfd); +- else if ((newelf = elf_begin (newfd, ELF_C_READ_MMAP, NULL)) +- == NULL) +- { +- fprintf (stderr, +- gettext ("cannot get ELF descriptor for %s: %s\n"), +- argv[cnt], elf_errmsg (-1)); +- status = 1; +- } +- else +- { +- if (verbose) +- printf ("%c - %s\n", +- found[cnt]->old_off == -1l ? 'a' : 'r', argv[cnt]); +- +- found[cnt]->elf = newelf; +- found[cnt]->sec = arlib_deterministic_output ? 0 : newst.st_mtime; +- found[cnt]->uid = arlib_deterministic_output ? 0 : newst.st_uid; +- found[cnt]->gid = arlib_deterministic_output ? 0 : newst.st_gid; +- found[cnt]->mode = newst.st_mode; +- found[cnt]->name = bname; +- +- found[cnt]->mem = elf_rawfile (newelf, &found[cnt]->size); +- if (found[cnt]->mem == NULL +- || elf_cntl (newelf, ELF_C_FDDONE) != 0) +- error (EXIT_FAILURE, 0, gettext ("cannot read %s: %s"), +- argv[cnt], elf_errmsg (-1)); +- +- close (newfd); +- +- if (found[cnt]->old_off != -1l) +- /* Remember long file names. */ +- remember_long_name (found[cnt], bname, bnamelen); +- } +- } +- } +- +- if (status != 0) +- { +-#ifdef DEBUG +- elf_end (elf); +- +- arlib_fini (); +- +- close (fd); +-#endif +- +- return status; +- } +- +- /* If we have no entry point so far add at the end. AFTER_MEMBERELEM +- being NULL when adding before an entry means add at the beginning. */ +- if (ipos != ipos_before && after_memberelem == NULL) +- after_memberelem = all; +- +- /* Convert the circular list into a normal list first. */ +- if (all != NULL) +- { +- struct armem *tmp = all; +- all = all->next; +- tmp->next = NULL; +- } +- +- struct armem *last_added = after_memberelem; +- for (int cnt = 0; cnt < argc; ++cnt) +- if (oper != oper_replace || found[cnt]->old_off == -1) +- { +- if (last_added == NULL) +- { +- found[cnt]->next = all; +- last_added = all = found[cnt]; +- } +- else +- { +- found[cnt]->next = last_added->next; +- last_added = last_added->next = found[cnt]; +- } +- } +- +- /* Finally compute the offset and add the symbols for the files +- after the insert point. */ +- if (likely (all != NULL)) +- for (struct armem *memp = all; memp != NULL; memp = memp->next) +- { +- memp->off = cur_off; +- +- if (memp->mem == NULL) +- { +- Elf_Arhdr *arhdr; +- /* Fake initializing arhdr and subelf to keep gcc calm. */ +- asm ("" : "=m" (arhdr), "=m" (subelf)); +- if (elf_rand (elf, memp->old_off) == 0 +- || (subelf = elf_begin (fd, ELF_C_READ_MMAP, elf)) == NULL +- || (arhdr = elf_getarhdr (subelf)) == NULL) +- /* This should never happen since we already looked at the +- archive content. But who knows... */ +- error (EXIT_FAILURE, 0, "%s: %s", arfname, elf_errmsg (-1)); +- +- arlib_add_symbols (subelf, arfname, arhdr->ar_name, cur_off); +- +- elf_end (subelf); +- } +- else +- arlib_add_symbols (memp->elf, arfname, memp->name, cur_off); +- +- cur_off += (((memp->size + 1) & ~((off_t) 1)) +- + sizeof (struct ar_hdr)); +- } +- +- /* Now we have all the information for the symbol table and long +- file name table. Construct the final layout. */ +- arlib_finalize (); +- +- /* Create a new, temporary file in the same directory as the +- original file. */ +- char tmpfname[strlen (arfname) + 7]; +- strcpy (stpcpy (tmpfname, arfname), "XXXXXX"); +- int newfd; +- if (fd != -1) +- newfd = mkstemp (tmpfname); +- else +- { +- newfd = open (arfname, O_RDWR | O_CREAT | O_EXCL, DEFFILEMODE); +- if (newfd == -1 && errno == EEXIST) +- /* Bah, first the file did not exist, now it does. Restart. */ +- return do_oper_insert (oper, arfname, argv, argc, member); +- } +- if (unlikely (newfd == -1)) +- goto nonew; +- +- /* Create the header. */ +- if (unlikely (write_retry (newfd, ARMAG, SARMAG) != SARMAG)) +- { +- nonew_unlink: +- if (fd != -1) +- { +- // XXX Use /prof/self/fd/%d ??? +- unlink (tmpfname); +- if (newfd != -1) +- close (newfd); +- } +- nonew: +- error (0, errno, gettext ("cannot create new file")); +- status = 1; +- goto errout; +- } +- +- /* If the new archive is not empty we actually have something to do. */ +- if (likely (all != NULL)) +- { +- /* Write the symbol table or the long file name table or both. */ +- if (symtab.symsnamelen != 0 +- && ((write_retry (newfd, symtab.symsoff, symtab.symsofflen) +- != (ssize_t) symtab.symsofflen) +- || (write_retry (newfd, symtab.symsname, symtab.symsnamelen) +- != (ssize_t) symtab.symsnamelen))) +- goto nonew_unlink; +- +- if (symtab.longnameslen > sizeof (struct ar_hdr) +- && (write_retry (newfd, symtab.longnames, symtab.longnameslen) +- != (ssize_t) symtab.longnameslen)) +- goto nonew_unlink; +- +- off_t start = -1; +- off_t len = -1; +- +- while (all != NULL) +- { +- if (all->mem != NULL) +- { +- /* This is a new file. If there is anything from the +- archive left to be written do it now. */ +- if (start != -1 && copy_content (elf, newfd, start, len)) +- goto nonew_unlink; +- +- start = -1; +- len = -1; +- +- /* Create the header. */ +- struct ar_hdr arhdr; +- char tmpbuf[sizeof (arhdr.ar_name) + 1]; +- if (all->long_name_off == -1) +- { +- size_t namelen = strlen (all->name); +- char *p = mempcpy (arhdr.ar_name, all->name, namelen); +- *p++ = '/'; +- memset (p, ' ', sizeof (arhdr.ar_name) - namelen - 1); +- } +- else +- { +- snprintf (tmpbuf, sizeof (arhdr.ar_name) + 1, "/%-*ld", +- (int) sizeof (arhdr.ar_name), all->long_name_off); +- memcpy (arhdr.ar_name, tmpbuf, sizeof (arhdr.ar_name)); +- } +- +- no0print (false, arhdr.ar_date, sizeof (arhdr.ar_date), +- all->sec); +- no0print (false, arhdr.ar_uid, sizeof (arhdr.ar_uid), all->uid); +- no0print (false, arhdr.ar_gid, sizeof (arhdr.ar_gid), all->gid); +- no0print (true, arhdr.ar_mode, sizeof (arhdr.ar_mode), +- all->mode); +- no0print (false, arhdr.ar_size, sizeof (arhdr.ar_size), +- all->size); +- memcpy (arhdr.ar_fmag, ARFMAG, sizeof (arhdr.ar_fmag)); +- +- if (unlikely (write_retry (newfd, &arhdr, sizeof (arhdr)) +- != sizeof (arhdr))) +- goto nonew_unlink; +- +- /* Now the file itself. */ +- if (unlikely (write_retry (newfd, all->mem, all->size) +- != (off_t) all->size)) +- goto nonew_unlink; +- +- /* Pad the file if its size is odd. */ +- if ((all->size & 1) != 0) +- if (unlikely (write_retry (newfd, "\n", 1) != 1)) +- goto nonew_unlink; +- } +- else +- { +- /* This is a member from the archive. */ +- if (write_member (all, &start, &len, elf, cur_off, newfd) +- != 0) +- goto nonew_unlink; +- } +- +- all = all->next; +- } +- +- /* Write the last part. */ +- if (start != -1 && copy_content (elf, newfd, start, len)) +- goto nonew_unlink; +- } +- +- /* Set the mode of the new file to the same values the original file +- has. */ +- if (fd != -1 +- && (fchmod (newfd, st.st_mode & ALLPERMS) != 0 +- /* Never complain about fchown failing. */ +- || (({asm ("" :: "r" (fchown (newfd, st.st_uid, st.st_gid))); }), +- close (newfd) != 0) +- || (newfd = -1, rename (tmpfname, arfname) != 0))) +- goto nonew_unlink; +- +- errout: +-#ifdef DEBUG +- elf_end (elf); +- +- arlib_fini (); +- +- close (fd); +-#endif +- +- return status; +-} +- +- +-#include "debugpred.h" ++int main() { return 0; } diff --git a/packages/libelf/build.sh b/packages/libelf/build.sh index 9f647cf8d..859816ee8 100644 --- a/packages/libelf/build.sh +++ b/packages/libelf/build.sh @@ -1,20 +1,46 @@ -TERMUX_PKG_VERSION=0.161 -TERMUX_PKG_BUILD_REVISION=1 +TERMUX_PKG_VERSION=0.166 TERMUX_PKG_HOMEPAGE=https://fedorahosted.org/elfutils/ TERMUX_PKG_DESCRIPTION="ELF object file access library" TERMUX_PKG_SRCURL=https://fedorahosted.org/releases/e/l/elfutils/${TERMUX_PKG_VERSION}/elfutils-${TERMUX_PKG_VERSION}.tar.bz2 +# For langinfo: +TERMUX_PKG_DEPENDS="libandroid-support" +# Use "eu-" as program prefix to avoid conflict with binutils programs. +# This is what several linux distributions do. +TERMUX_PKG_EXTRA_CONFIGURE_ARGS="--program-prefix='eu-'" +# The ar.c file is patched away for now: +TERMUX_PKG_RM_AFTER_INSTALL="bin/eu-ar" LDFLAGS+=" -lintl" -CFLAGS+=" -DTERMUX_EXPOSE_MEMPCPY=1" +CFLAGS+=" -DTERMUX_EXPOSE_MEMPCPY=1 -Wno-error=unused-value -Wno-error=format-nonliteral -Wno-error" -termux_step_pre_make () { - export TERMUX_PKG_BUILDDIR=$TERMUX_PKG_BUILDDIR/libelf - cd $TERMUX_PKG_BUILDDIR +# Exposes ACCESSPERMS in which elfutils uses: +CFLAGS+=" -D__USE_BSD" + +termux_step_pre_configure () { + # Install argp lib. + ARGP_FILE=$TERMUX_PKG_CACHEDIR/argp-standalone.1.3.tar.gz + if [ ! -f $ARGP_FILE ]; then + curl -o $ARGP_FILE http://www.lysator.liu.se/~nisse/archive/argp-standalone-1.3.tar.gz + fi + + cd $TERMUX_PKG_TMPDIR + tar xf $ARGP_FILE + cd argp-standalone-1.3 + ./configure --host=$TERMUX_HOST_PLATFORM + make + + cp $TERMUX_PKG_BUILDER_DIR/error.h . + cp $TERMUX_PKG_BUILDER_DIR/stdio_ext.h . + cp $TERMUX_PKG_BUILDER_DIR/obstack.h . + cp $TERMUX_PKG_BUILDER_DIR/qsort_r.h . + + LDFLAGS+=" -L$TERMUX_PKG_TMPDIR/argp-standalone-1.3" + CPPFLAGS+=" -isystem $TERMUX_PKG_TMPDIR/argp-standalone-1.3" } -termux_step_post_make_install () { - make install-includeHEADERS -} +#termux_step_post_make_install () { +#make install-includeHEADERS +#} termux_step_post_massage () { # Remove to avoid spurios linking to libelf (https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=10648): diff --git a/packages/libelf/config.h.in.patch b/packages/libelf/config.h.in.patch new file mode 100644 index 000000000..6d833c8a7 --- /dev/null +++ b/packages/libelf/config.h.in.patch @@ -0,0 +1,11 @@ +diff -u -r ../elfutils-0.166/config.h.in ./config.h.in +--- ../elfutils-0.166/config.h.in 2016-03-31 04:59:09.000000000 -0400 ++++ ./config.h.in 2016-05-04 13:36:44.002345307 -0400 +@@ -1,4 +1,7 @@ + /* config.h.in. Generated from configure.ac by autoheader. */ ++#include /* for basename(3) */ ++#include /* for fputc_unlocked(3) */ ++#define DL_CALL_FCT(f, args) ((*(f)) args) + + /* Building with -fsanitize=undefined or not */ + #undef CHECK_UNDEFINED diff --git a/packages/libelf/dwfl_error.c.patch b/packages/libelf/dwfl_error.c.patch new file mode 100644 index 000000000..acaa692df --- /dev/null +++ b/packages/libelf/dwfl_error.c.patch @@ -0,0 +1,22 @@ +diff -u -r ../elfutils-0.166/libdwfl/dwfl_error.c ./libdwfl/dwfl_error.c +--- ../elfutils-0.166/libdwfl/dwfl_error.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./libdwfl/dwfl_error.c 2016-05-04 13:15:42.522820139 -0400 +@@ -140,6 +140,7 @@ + const char * + dwfl_errmsg (int error) + { ++ char* error_msg; + if (error == 0 || error == -1) + { + int last_error = global_error; +@@ -154,7 +155,9 @@ + switch (error &~ 0xffff) + { + case OTHER_ERROR (ERRNO): +- return strerror_r (error & 0xffff, "bad", 0); ++ error_msg = malloc(256); ++ strerror_r (error & 0xffff, error_msg, 256); ++ return error_msg; + case OTHER_ERROR (LIBELF): + return elf_errmsg (error & 0xffff); + case OTHER_ERROR (LIBDW): diff --git a/packages/libelf/eblwstrtab.c.patch b/packages/libelf/eblwstrtab.c.patch new file mode 100644 index 000000000..4eeb46eaa --- /dev/null +++ b/packages/libelf/eblwstrtab.c.patch @@ -0,0 +1,15 @@ +diff -u -r ../elfutils-0.166/libebl/eblwstrtab.c ./libebl/eblwstrtab.c +--- ../elfutils-0.166/libebl/eblwstrtab.c 2015-08-21 08:22:37.000000000 -0400 ++++ ./libebl/eblwstrtab.c 2016-05-04 13:11:26.834934000 -0400 +@@ -294,6 +294,11 @@ + return newstr; + } + ++static wchar_t* wmempcpy(wchar_t* s1, const wchar_t* s2, size_t n) ++{ ++ size_t bytes = n * sizeof(wchar_t); ++ return (wchar_t *) (memcpy((char *) s1, (char *) s2, bytes) + bytes); ++} + + static void + copystrings (struct Ebl_WStrent *nodep, wchar_t **freep, size_t *offsetp) diff --git a/packages/libelf/elf_getaroff.c.patch b/packages/libelf/elf_getaroff.c.patch index 802339e4e..3fc56a5ff 100644 --- a/packages/libelf/elf_getaroff.c.patch +++ b/packages/libelf/elf_getaroff.c.patch @@ -1,12 +1,12 @@ -diff -u -r ../elfutils-0.159/libelf/elf_getaroff.c ./libelf/elf_getaroff.c ---- ../elfutils-0.159/libelf/elf_getaroff.c 2014-02-05 01:21:44.000000000 +0100 -+++ ./libelf/elf_getaroff.c 2014-05-30 15:05:42.226191850 +0200 +diff -u -r ../elfutils-0.166/libelf/elf_getaroff.c ./libelf/elf_getaroff.c +--- ../elfutils-0.166/libelf/elf_getaroff.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./libelf/elf_getaroff.c 2016-05-04 13:07:06.547288608 -0400 @@ -38,7 +38,7 @@ #include "libelfP.h" -off_t +loff_t - elf_getaroff (elf) - Elf *elf; + elf_getaroff (Elf *elf) { + /* Be gratious, the specs demand it. */ diff --git a/packages/libelf/elf_getbase.c.patch b/packages/libelf/elf_getbase.c.patch deleted file mode 100644 index 36e84eb2a..000000000 --- a/packages/libelf/elf_getbase.c.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -u -r ../elfutils-0.159/libelf/elf_getbase.c ./libelf/elf_getbase.c ---- ../elfutils-0.159/libelf/elf_getbase.c 2014-02-05 01:21:44.000000000 +0100 -+++ ./libelf/elf_getbase.c 2014-05-30 14:42:12.766230381 +0200 -@@ -37,7 +37,7 @@ - #include "libelfP.h" - - --off_t -+loff_t - elf_getbase (elf) - Elf *elf; - { diff --git a/packages/libelf/elf_update.c.patch b/packages/libelf/elf_update.c.patch index b57d81791..fd5cd6f5d 100644 --- a/packages/libelf/elf_update.c.patch +++ b/packages/libelf/elf_update.c.patch @@ -1,12 +1,11 @@ -diff -u -r ../elfutils-0.159/libelf/elf_update.c ./libelf/elf_update.c ---- ../elfutils-0.159/libelf/elf_update.c 2014-05-18 16:32:15.000000000 +0200 -+++ ./libelf/elf_update.c 2014-05-30 14:56:42.806206596 +0200 -@@ -123,7 +123,7 @@ - } +diff -u -r ../elfutils-0.166/libelf/elf_update.c ./libelf/elf_update.c +--- ../elfutils-0.166/libelf/elf_update.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./libelf/elf_update.c 2016-05-04 13:06:15.836140729 -0400 +@@ -39,6 +39,7 @@ + #include "libelfP.h" --off_t -+loff_t - elf_update (elf, cmd) - Elf *elf; - Elf_Cmd cmd; ++#define off_t loff_t + + static off_t + write_file (Elf *elf, off_t size, int change_bo, size_t shnum) diff --git a/packages/libelf/elfcompress.c.patch b/packages/libelf/elfcompress.c.patch new file mode 100644 index 000000000..36cd5e4db --- /dev/null +++ b/packages/libelf/elfcompress.c.patch @@ -0,0 +1,12 @@ +diff -u -r ../elfutils-0.166/src/elfcompress.c ./src/elfcompress.c +--- ../elfutils-0.166/src/elfcompress.c 2016-03-02 11:25:38.000000000 -0500 ++++ ./src/elfcompress.c 2016-05-04 14:33:03.812183632 -0400 +@@ -166,7 +166,7 @@ + struct section_pattern *pattern = patterns; + while (pattern != NULL) + { +- if (fnmatch (pattern->pattern, name, FNM_EXTMATCH) == 0) ++ if (fnmatch (pattern->pattern, name, 0) == 0) + return true; + pattern = pattern->next; + } diff --git a/packages/libelf/error.h b/packages/libelf/error.h new file mode 100644 index 000000000..9f2230b70 --- /dev/null +++ b/packages/libelf/error.h @@ -0,0 +1,25 @@ +#include +#include +#include + +/* program_invocation_short_name GNU extension - http://linux.die.net/man/3/program_invocation_short_name */ +extern char* __progname; +#define program_invocation_short_name __progname + +/* error(3) GNU extension - http://man7.org/linux/man-pages/man3/error.3.html */ +unsigned int error_message_count; +static inline void error(int status, int errnum, const char* format, ...) { + error_message_count++; + va_list myargs; + va_start(myargs, format); + vfprintf(stderr, format, myargs); + va_end(myargs); + exit(status); +} + +/* strchrnul(3) GNU extension - http://man7.org/linux/man-pages/man3/strchr.3.html */ +static inline char* strchrnul(char const* s, int c) +{ + char* result = strchr(s, c); + return (result == NULL) ? (char*)(s + strlen(s)) : result; +} diff --git a/packages/libelf/ldgeneric.c.patch b/packages/libelf/ldgeneric.c.patch new file mode 100644 index 000000000..820870060 --- /dev/null +++ b/packages/libelf/ldgeneric.c.patch @@ -0,0 +1,60 @@ +diff -u -r ../elfutils-0.166/src/ldgeneric.c ./src/ldgeneric.c +--- ../elfutils-0.166/src/ldgeneric.c 2015-08-21 08:22:37.000000000 -0400 ++++ ./src/ldgeneric.c 2016-05-04 15:20:09.029651147 -0400 +@@ -1747,7 +1747,13 @@ + + /* The content of the file is available in memory. Read the + memory region as a stream. */ ++#ifdef __ANDROID__ ++ ldin = tmpfile(); ++ fwrite(content, 1, contentsize, ldin); ++ rewind(ldin); ++#else + ldin = fmemopen (content, contentsize, "r"); ++#endif + } + + /* No need for locking. */ +@@ -2631,9 +2637,9 @@ + /* Callback function registered with on_exit to make sure the temporary + files gets removed if something goes wrong. */ + static void +-remove_tempfile (int status, void *arg) ++remove_tempfile () + { +- if (status != 0 && ld_state.tempfname != NULL) ++ if (ld_state.tempfname != NULL) + unlink (ld_state.tempfname); + } + +@@ -2680,7 +2686,7 @@ + + /* Make sure we remove the temporary file in case something goes + wrong. */ +- on_exit (remove_tempfile, NULL); ++ atexit (remove_tempfile); + + /* Create the ELF file data for the output file. */ + Elf *elf = ld_state.outelf = elf_begin (fd, +@@ -3352,6 +3358,7 @@ + struct id_list search; + struct id_list *verp; + bool result = ld_state.default_bind_local; ++ size_t substr_len; + + if (XELF_ST_BIND (sym->st_info) == STB_LOCAL || sym->st_shndx == SHN_UNDEF) + /* We don't have to do anything to local symbols here. */ +@@ -3367,7 +3374,12 @@ + version = strchr (str, VER_CHR); + if (version != NULL) + { +- search.id = strndupa (str, version - str); ++ substr_len = version - str; ++ char* tmp = alloca(substr_len+1); ++ strncpy(tmp, str, substr_len); ++ tmp[substr_len] = 0; ++ search.id = tmp; ++ + if (*++version == VER_CHR) + /* Skip the second '@' signaling a default definition. */ + ++version; diff --git a/packages/libelf/libdwflP.h.patch b/packages/libelf/libdwflP.h.patch new file mode 100644 index 000000000..74014ca52 --- /dev/null +++ b/packages/libelf/libdwflP.h.patch @@ -0,0 +1,14 @@ +diff -u -r ../elfutils-0.166/libdwfl/libdwflP.h ./libdwfl/libdwflP.h +--- ../elfutils-0.166/libdwfl/libdwflP.h 2016-01-12 07:49:19.000000000 -0500 ++++ ./libdwfl/libdwflP.h 2016-05-04 13:21:07.997599838 -0400 +@@ -771,5 +771,10 @@ + /* The default used by dwfl_standard_find_debuginfo. */ + #define DEFAULT_DEBUGINFO_PATH ":.debug:/usr/lib/debug" + ++ /* canonicalize_file_name GNU extension - http://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html */ ++inline static char* canonicalize_file_name(const char *path) ++{ ++ return realpath(path, NULL); ++} + + #endif /* libdwflP.h */ diff --git a/packages/libelf/libelf-elf_getbase.c.patch b/packages/libelf/libelf-elf_getbase.c.patch new file mode 100644 index 000000000..f4e038926 --- /dev/null +++ b/packages/libelf/libelf-elf_getbase.c.patch @@ -0,0 +1,12 @@ +diff -u -r ../elfutils-0.166/libelf/elf_getbase.c ./libelf/elf_getbase.c +--- ../elfutils-0.166/libelf/elf_getbase.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./libelf/elf_getbase.c 2016-05-04 13:01:52.776589425 -0400 +@@ -37,7 +37,7 @@ + #include "libelfP.h" + + +-off_t ++loff_t + elf_getbase (Elf *elf) + { + return elf == NULL ? (off_t) -1 : elf->start_offset; diff --git a/packages/libelf/libelf-elf_getdata_rawchunk.c.patch b/packages/libelf/libelf-elf_getdata_rawchunk.c.patch new file mode 100644 index 000000000..00a64bca6 --- /dev/null +++ b/packages/libelf/libelf-elf_getdata_rawchunk.c.patch @@ -0,0 +1,12 @@ +diff -u -r ../elfutils-0.166/libelf/elf_getdata_rawchunk.c ./libelf/elf_getdata_rawchunk.c +--- ../elfutils-0.166/libelf/elf_getdata_rawchunk.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./libelf/elf_getdata_rawchunk.c 2016-05-04 13:03:35.578844420 -0400 +@@ -41,7 +41,7 @@ + #include "common.h" + + Elf_Data * +-elf_getdata_rawchunk (Elf *elf, off_t offset, size_t size, Elf_Type type) ++elf_getdata_rawchunk (Elf *elf, loff_t offset, size_t size, Elf_Type type) + { + if (unlikely (elf == NULL)) + return NULL; diff --git a/packages/libelf/obstack.h b/packages/libelf/obstack.h new file mode 100644 index 000000000..f68d1c9e6 --- /dev/null +++ b/packages/libelf/obstack.h @@ -0,0 +1,794 @@ +/* obstack.h - object stack macros + Copyright (C) 1988-1994,1996-1999,2003,2004,2005,2009,2011,2012 + Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +/* Summary: + +All the apparent functions defined here are macros. The idea +is that you would use these pre-tested macros to solve a +very specific set of problems, and they would run fast. +Caution: no side-effects in arguments please!! They may be +evaluated MANY times!! + +These macros operate a stack of objects. Each object starts life +small, and may grow to maturity. (Consider building a word syllable +by syllable.) An object can move while it is growing. Once it has +been "finished" it never changes address again. So the "top of the +stack" is typically an immature growing object, while the rest of the +stack is of mature, fixed size and fixed address objects. + +These routines grab large chunks of memory, using a function you +supply, called `obstack_chunk_alloc'. On occasion, they free chunks, +by calling `obstack_chunk_free'. You must define them and declare +them before using any obstack macros. + +Each independent stack is represented by a `struct obstack'. +Each of the obstack macros expects a pointer to such a structure +as the first argument. + +One motivation for this package is the problem of growing char strings +in symbol tables. Unless you are "fascist pig with a read-only mind" +--Gosper's immortal quote from HAKMEM item 154, out of context--you +would not like to put any arbitrary upper limit on the length of your +symbols. + +In practice this often means you will build many short symbols and a +few long symbols. At the time you are reading a symbol you don't know +how long it is. One traditional method is to read a symbol into a +buffer, realloc()ating the buffer every time you try to read a symbol +that is longer than the buffer. This is beaut, but you still will +want to copy the symbol from the buffer to a more permanent +symbol-table entry say about half the time. + +With obstacks, you can work differently. Use one obstack for all symbol +names. As you read a symbol, grow the name in the obstack gradually. +When the name is complete, finalize it. Then, if the symbol exists already, +free the newly read name. + +The way we do this is to take a large chunk, allocating memory from +low addresses. When you want to build a symbol in the chunk you just +add chars above the current "high water mark" in the chunk. When you +have finished adding chars, because you got to the end of the symbol, +you know how long the chars are, and you can create a new object. +Mostly the chars will not burst over the highest address of the chunk, +because you would typically expect a chunk to be (say) 100 times as +long as an average object. + +In case that isn't clear, when we have enough chars to make up +the object, THEY ARE ALREADY CONTIGUOUS IN THE CHUNK (guaranteed) +so we just point to it where it lies. No moving of chars is +needed and this is the second win: potentially long strings need +never be explicitly shuffled. Once an object is formed, it does not +change its address during its lifetime. + +When the chars burst over a chunk boundary, we allocate a larger +chunk, and then copy the partly formed object from the end of the old +chunk to the beginning of the new larger chunk. We then carry on +accreting characters to the end of the object as we normally would. + +A special macro is provided to add a single char at a time to a +growing object. This allows the use of register variables, which +break the ordinary 'growth' macro. + +Summary: + We allocate large chunks. + We carve out one object at a time from the current chunk. + Once carved, an object never moves. + We are free to append data of any size to the currently + growing object. + Exactly one object is growing in an obstack at any one time. + You can run one obstack per control block. + You may have as many control blocks as you dare. + Because of the way we do it, you can `unwind' an obstack + back to a previous state. (You may remove objects much + as you would with a stack.) +*/ + + +/* Don't do the contents of this file more than once. */ + +#ifndef _OBSTACK_H +#define _OBSTACK_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We need the type of a pointer subtraction. If __PTRDIFF_TYPE__ is + defined, as with GNU C, use that; that way we don't pollute the + namespace with 's symbols. Otherwise, include + and use ptrdiff_t. */ + +#ifdef __PTRDIFF_TYPE__ +# define PTR_INT_TYPE __PTRDIFF_TYPE__ +#else +# include +# define PTR_INT_TYPE ptrdiff_t +#endif + +/* If B is the base of an object addressed by P, return the result of + aligning P to the next multiple of A + 1. B and P must be of type + char *. A + 1 must be a power of 2. */ + +#define __BPTR_ALIGN(B, P, A) ((B) + (((P) - (B) + (A)) & ~(A))) + +/* Similiar to _BPTR_ALIGN (B, P, A), except optimize the common case + where pointers can be converted to integers, aligned as integers, + and converted back again. If PTR_INT_TYPE is narrower than a + pointer (e.g., the AS/400), play it safe and compute the alignment + relative to B. Otherwise, use the faster strategy of computing the + alignment relative to 0. */ + +#define __PTR_ALIGN(B, P, A) \ + __BPTR_ALIGN (sizeof (PTR_INT_TYPE) < sizeof (void *) ? (B) : (char *) 0, \ + P, A) + +#include + +struct _obstack_chunk /* Lives at front of each chunk. */ +{ + char *limit; /* 1 past end of this chunk */ + struct _obstack_chunk *prev; /* address of prior chunk or NULL */ + char contents[4]; /* objects begin here */ +}; + +struct obstack /* control current object in current chunk */ +{ + long chunk_size; /* preferred size to allocate chunks in */ + struct _obstack_chunk *chunk; /* address of current struct obstack_chunk */ + char *object_base; /* address of object we are building */ + char *next_free; /* where to add next char to current object */ + char *chunk_limit; /* address of char after current chunk */ + union + { + PTR_INT_TYPE tempint; + void *tempptr; + } temp; /* Temporary for some macros. */ + int alignment_mask; /* Mask of alignment for each object. */ + /* These prototypes vary based on `use_extra_arg', and we use + casts to the prototypeless function type in all assignments, + but having prototypes here quiets -Wstrict-prototypes. */ + struct _obstack_chunk *(*chunkfun) (void *, long); + void (*freefun) (void *, struct _obstack_chunk *); + void *extra_arg; /* first arg for chunk alloc/dealloc funcs */ + unsigned use_extra_arg:1; /* chunk alloc/dealloc funcs take extra arg */ + unsigned maybe_empty_object:1;/* There is a possibility that the current + chunk contains a zero-length object. This + prevents freeing the chunk if we allocate + a bigger chunk to replace it. */ + unsigned alloc_failed:1; /* No longer used, as we now call the failed + handler on error, but retained for binary + compatibility. */ +}; + +static void _obstack_newchunk (struct obstack *h, int length); + +/* Exit value used when `print_and_abort' is used. */ +extern int obstack_exit_failure; + +/* Pointer to beginning of object being allocated or to be allocated next. + Note that this might not be the final address of the object + because a new chunk might be needed to hold the final size. */ + +#define obstack_base(h) ((void *) (h)->object_base) + +/* Size for allocating ordinary chunks. */ + +#define obstack_chunk_size(h) ((h)->chunk_size) + +/* Pointer to next byte not yet allocated in current chunk. */ + +#define obstack_next_free(h) ((h)->next_free) + +/* Mask specifying low bits that should be clear in address of an object. */ + +#define obstack_alignment_mask(h) ((h)->alignment_mask) + +/* To prevent prototype warnings provide complete argument list. */ +#define obstack_init(h) \ + _obstack_begin ((h), 0, 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_begin(h, size) \ + _obstack_begin ((h), (size), 0, \ + (void *(*) (long)) obstack_chunk_alloc, \ + (void (*) (void *)) obstack_chunk_free) + +#define obstack_specify_allocation(h, size, alignment, chunkfun, freefun) \ + _obstack_begin ((h), (size), (alignment), \ + (void *(*) (long)) (chunkfun), \ + (void (*) (void *)) (freefun)) + +#define obstack_specify_allocation_with_arg(h, size, alignment, chunkfun, freefun, arg) \ + _obstack_begin_1 ((h), (size), (alignment), \ + (void *(*) (void *, long)) (chunkfun), \ + (void (*) (void *, void *)) (freefun), (arg)) + +#define obstack_chunkfun(h, newchunkfun) \ + ((h) -> chunkfun = (struct _obstack_chunk *(*)(void *, long)) (newchunkfun)) + +#define obstack_freefun(h, newfreefun) \ + ((h) -> freefun = (void (*)(void *, struct _obstack_chunk *)) (newfreefun)) + +#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) + +#define obstack_blank_fast(h,n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used (h) + +#if defined __GNUC__ +/* NextStep 2.0 cc is really gcc 1.93 but it defines __GNUC__ = 2 and + does not implement __extension__. But that compiler doesn't define + __GNUC_MINOR__. */ +# if __GNUC__ < 2 || (__NeXT__ && !__GNUC_MINOR__) +# define __extension__ +# endif + +/* For GNU C, if not -traditional, + we can define these macros to compute all args only once + without using a global variable. + Also, we can avoid using the `temp' slot, to make faster code. */ + +# define obstack_object_size(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->next_free - __o->object_base); }) + +# define obstack_room(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (unsigned) (__o->chunk_limit - __o->next_free); }) + +# define obstack_make_room(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + (void) 0; }) + +# define obstack_empty_p(OBSTACK) \ + __extension__ \ + ({ struct obstack const *__o = (OBSTACK); \ + (__o->chunk->prev == 0 \ + && __o->next_free == __PTR_ALIGN ((char *) __o->chunk, \ + __o->chunk->contents, \ + __o->alignment_mask)); }) + +# define obstack_grow(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len > __o->chunk_limit) \ + _obstack_newchunk (__o, __len); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + (void) 0; }) + +# define obstack_grow0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->next_free + __len + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, __len + 1); \ + memcpy (__o->next_free, where, __len); \ + __o->next_free += __len; \ + *(__o->next_free)++ = 0; \ + (void) 0; }) + +# define obstack_1grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + 1 > __o->chunk_limit) \ + _obstack_newchunk (__o, 1); \ + obstack_1grow_fast (__o, datum); \ + (void) 0; }) + +/* These assume that the obstack alignment is good enough for pointers + or ints, and that the data added so far to the current object + shares that much alignment. */ + +# define obstack_ptr_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (void *) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (void *)); \ + obstack_ptr_grow_fast (__o, datum); }) \ + +# define obstack_int_grow(OBSTACK,datum) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + if (__o->next_free + sizeof (int) > __o->chunk_limit) \ + _obstack_newchunk (__o, sizeof (int)); \ + obstack_int_grow_fast (__o, datum); }) + +# define obstack_ptr_grow_fast(OBSTACK,aptr) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(const void **) __o1->next_free = (aptr); \ + __o1->next_free += sizeof (const void *); \ + (void) 0; }) + +# define obstack_int_grow_fast(OBSTACK,aint) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + *(int *) __o1->next_free = (aint); \ + __o1->next_free += sizeof (int); \ + (void) 0; }) + +# define obstack_blank(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + int __len = (length); \ + if (__o->chunk_limit - __o->next_free < __len) \ + _obstack_newchunk (__o, __len); \ + obstack_blank_fast (__o, __len); \ + (void) 0; }) + +# define obstack_alloc(OBSTACK,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_blank (__h, (length)); \ + obstack_finish (__h); }) + +# define obstack_copy(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow (__h, (where), (length)); \ + obstack_finish (__h); }) + +# define obstack_copy0(OBSTACK,where,length) \ +__extension__ \ +({ struct obstack *__h = (OBSTACK); \ + obstack_grow0 (__h, (where), (length)); \ + obstack_finish (__h); }) + +/* The local variable is named __o1 to avoid a name conflict + when obstack_blank is called. */ +# define obstack_finish(OBSTACK) \ +__extension__ \ +({ struct obstack *__o1 = (OBSTACK); \ + void *__value = (void *) __o1->object_base; \ + if (__o1->next_free == __value) \ + __o1->maybe_empty_object = 1; \ + __o1->next_free \ + = __PTR_ALIGN (__o1->object_base, __o1->next_free, \ + __o1->alignment_mask); \ + if (__o1->next_free - (char *)__o1->chunk \ + > __o1->chunk_limit - (char *)__o1->chunk) \ + __o1->next_free = __o1->chunk_limit; \ + __o1->object_base = __o1->next_free; \ + __value; }) + +# define obstack_free(OBSTACK, OBJ) \ +__extension__ \ +({ struct obstack *__o = (OBSTACK); \ + void *__obj = (OBJ); \ + if (__obj > (void *)__o->chunk && __obj < (void *)__o->chunk_limit) \ + __o->next_free = __o->object_base = (char *)__obj; \ + else (obstack_free_func) (__o, __obj); }) + +#else /* not __GNUC__ */ + +# define obstack_object_size(h) \ + (unsigned) ((h)->next_free - (h)->object_base) + +# define obstack_room(h) \ + (unsigned) ((h)->chunk_limit - (h)->next_free) + +# define obstack_empty_p(h) \ + ((h)->chunk->prev == 0 \ + && (h)->next_free == __PTR_ALIGN ((char *) (h)->chunk, \ + (h)->chunk->contents, \ + (h)->alignment_mask)) + +/* Note that the call to _obstack_newchunk is enclosed in (..., 0) + so that we can avoid having void expressions + in the arms of the conditional expression. + Casting the third operand to void was tried before, + but some compilers won't accept it. */ + +# define obstack_make_room(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0)) + +# define obstack_grow(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint) + +# define obstack_grow0(h,where,length) \ +( (h)->temp.tempint = (length), \ + (((h)->next_free + (h)->temp.tempint + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint + 1), 0) : 0), \ + memcpy ((h)->next_free, where, (h)->temp.tempint), \ + (h)->next_free += (h)->temp.tempint, \ + *((h)->next_free)++ = 0) + +# define obstack_1grow(h,datum) \ +( (((h)->next_free + 1 > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), 1), 0) : 0), \ + obstack_1grow_fast (h, datum)) + +# define obstack_ptr_grow(h,datum) \ +( (((h)->next_free + sizeof (char *) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (char *)), 0) : 0), \ + obstack_ptr_grow_fast (h, datum)) + +# define obstack_int_grow(h,datum) \ +( (((h)->next_free + sizeof (int) > (h)->chunk_limit) \ + ? (_obstack_newchunk ((h), sizeof (int)), 0) : 0), \ + obstack_int_grow_fast (h, datum)) + +# define obstack_ptr_grow_fast(h,aptr) \ + (((const void **) ((h)->next_free += sizeof (void *)))[-1] = (aptr)) + +# define obstack_int_grow_fast(h,aint) \ + (((int *) ((h)->next_free += sizeof (int)))[-1] = (aint)) + +# define obstack_blank(h,length) \ +( (h)->temp.tempint = (length), \ + (((h)->chunk_limit - (h)->next_free < (h)->temp.tempint) \ + ? (_obstack_newchunk ((h), (h)->temp.tempint), 0) : 0), \ + obstack_blank_fast (h, (h)->temp.tempint)) + +# define obstack_alloc(h,length) \ + (obstack_blank ((h), (length)), obstack_finish ((h))) + +# define obstack_copy(h,where,length) \ + (obstack_grow ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_copy0(h,where,length) \ + (obstack_grow0 ((h), (where), (length)), obstack_finish ((h))) + +# define obstack_finish(h) \ +( ((h)->next_free == (h)->object_base \ + ? (((h)->maybe_empty_object = 1), 0) \ + : 0), \ + (h)->temp.tempptr = (h)->object_base, \ + (h)->next_free \ + = __PTR_ALIGN ((h)->object_base, (h)->next_free, \ + (h)->alignment_mask), \ + (((h)->next_free - (char *) (h)->chunk \ + > (h)->chunk_limit - (char *) (h)->chunk) \ + ? ((h)->next_free = (h)->chunk_limit) : 0), \ + (h)->object_base = (h)->next_free, \ + (h)->temp.tempptr) + +# define obstack_free(h,obj) \ +( (h)->temp.tempint = (char *) (obj) - (char *) (h)->chunk, \ + ((((h)->temp.tempint > 0 \ + && (h)->temp.tempint < (h)->chunk_limit - (char *) (h)->chunk)) \ + ? (((h)->next_free = (h)->object_base \ + = (h)->temp.tempint + (char *) (h)->chunk), 0) \ + : ((obstack_free_func) ((h), (h)->temp.tempint + (char *) (h)->chunk), 0))) + +#endif /* not __GNUC__ */ + +/* START LOCAL ADDITION */ +static inline int obstack_printf(struct obstack *obst, const char *fmt, ...) +{ + char buf[1024]; + va_list ap; + int len; + + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + obstack_grow(obst, buf, len); + va_end(ap); + + return len; +} +/* Determine default alignment. */ +union fooround +{ + uintmax_t i; + long double d; + void *p; +}; +struct fooalign +{ + char c; + union fooround u; +}; +/* If malloc were really smart, it would round addresses to DEFAULT_ALIGNMENT. + But in fact it might be less smart and round addresses to as much as + DEFAULT_ROUNDING. So we prepare for it to do that. */ +enum + { + DEFAULT_ALIGNMENT = offsetof (struct fooalign, u), + DEFAULT_ROUNDING = sizeof (union fooround) + }; + +/* When we copy a long block of data, this is the unit to do it with. + On some machines, copying successive ints does not work; + in such a case, redefine COPYING_UNIT to `long' (if that works) + or `char' as a last resort. */ +# ifndef COPYING_UNIT +# define COPYING_UNIT int +# endif + + +/* The functions allocating more room by calling `obstack_chunk_alloc' + jump to the handler pointed to by `obstack_alloc_failed_handler'. + This can be set to a user defined function which should either + abort gracefully or use longjump - but shouldn't return. This + variable by default points to the internal function + `print_and_abort'. */ +static void print_and_abort (void); + +# ifdef _LIBC +# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +/* A looong time ago (before 1994, anyway; we're not sure) this global variable + was used by non-GNU-C macros to avoid multiple evaluation. The GNU C + library still exports it because somebody might use it. */ +struct obstack *_obstack_compat; +compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); +# endif +# endif + +/* Define a macro that either calls functions with the traditional malloc/free + calling interface, or calls functions with the mmalloc/mfree interface + (that adds an extra first argument), based on the state of use_extra_arg. + For free, do not use ?:, since some compilers, like the MIPS compilers, + do not allow (expr) ? void : void. */ + +# define CALL_CHUNKFUN(h, size) \ + (((h) -> use_extra_arg) \ + ? (*(h)->chunkfun) ((h)->extra_arg, (size)) \ + : (*(struct _obstack_chunk *(*) (long)) (h)->chunkfun) ((size))) + +# define CALL_FREEFUN(h, old_chunk) \ + do { \ + if ((h) -> use_extra_arg) \ + (*(h)->freefun) ((h)->extra_arg, (old_chunk)); \ + else \ + (*(void (*) (void *)) (h)->freefun) ((old_chunk)); \ + } while (0) + + +/* Initialize an obstack H for use. Specify chunk size SIZE (0 means default). + Objects start on multiples of ALIGNMENT (0 means use default). + CHUNKFUN is the function to use to allocate chunks, + and FREEFUN the function to free them. + Return nonzero if successful, calls obstack_alloc_failed_handler if + allocation fails. */ + +static int _obstack_begin (struct obstack *h, + int size, int alignment, + void *(*chunkfun) (long), + void (*freefun) (void *)) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *, long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->use_extra_arg = 0; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) print_and_abort(); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +static int _obstack_begin_1 (struct obstack *h, int size, int alignment, + void *(*chunkfun) (void *, long), + void (*freefun) (void *, void *), + void *arg) +{ + register struct _obstack_chunk *chunk; /* points to new chunk */ + + if (alignment == 0) + alignment = DEFAULT_ALIGNMENT; + if (size == 0) + /* Default size is what GNU malloc can fit in a 4096-byte block. */ + { + /* 12 is sizeof (mhead) and 4 is EXTRA from GNU malloc. + Use the values for range checking, because if range checking is off, + the extra bytes won't be missed terribly, but if range checking is on + and we used a larger request, a whole extra 4096 bytes would be + allocated. + These number are irrelevant to the new GNU malloc. I suspect it is + less sensitive to the size of the request. */ + int extra = ((((12 + DEFAULT_ROUNDING - 1) & ~(DEFAULT_ROUNDING - 1)) + + 4 + DEFAULT_ROUNDING - 1) + & ~(DEFAULT_ROUNDING - 1)); + size = 4096 - extra; + } + + h->chunkfun = (struct _obstack_chunk * (*)(void *,long)) chunkfun; + h->freefun = (void (*) (void *, struct _obstack_chunk *)) freefun; + h->chunk_size = size; + h->alignment_mask = alignment - 1; + h->extra_arg = arg; + h->use_extra_arg = 1; + + chunk = h->chunk = CALL_CHUNKFUN (h, h -> chunk_size); + if (!chunk) print_and_abort(); + h->next_free = h->object_base = __PTR_ALIGN ((char *) chunk, chunk->contents, + alignment - 1); + h->chunk_limit = chunk->limit + = (char *) chunk + h->chunk_size; + chunk->prev = 0; + /* The initial chunk now contains no empty object. */ + h->maybe_empty_object = 0; + h->alloc_failed = 0; + return 1; +} + +/* Allocate a new current chunk for the obstack *H + on the assumption that LENGTH bytes need to be added + to the current object, or a new object of length LENGTH allocated. + Copies any partial object from the end of the old chunk + to the beginning of the new one. */ + +static void _obstack_newchunk (struct obstack *h, int length) +{ + register struct _obstack_chunk *old_chunk = h->chunk; + register struct _obstack_chunk *new_chunk; + register long new_size; + register long obj_size = h->next_free - h->object_base; + register long i; + long already; + char *object_base; + + /* Compute size for new chunk. */ + new_size = (obj_size + length) + (obj_size >> 3) + h->alignment_mask + 100; + if (new_size < h->chunk_size) + new_size = h->chunk_size; + + /* Allocate and initialize the new chunk. */ + new_chunk = CALL_CHUNKFUN (h, new_size); + if (!new_chunk) print_and_abort(); + h->chunk = new_chunk; + new_chunk->prev = old_chunk; + new_chunk->limit = h->chunk_limit = (char *) new_chunk + new_size; + + /* Compute an aligned object_base in the new chunk */ + object_base = + __PTR_ALIGN ((char *) new_chunk, new_chunk->contents, h->alignment_mask); + + /* Move the existing object to the new chunk. + Word at a time is fast and is safe if the object + is sufficiently aligned. */ + if (h->alignment_mask + 1 >= DEFAULT_ALIGNMENT) + { + for (i = obj_size / sizeof (COPYING_UNIT) - 1; + i >= 0; i--) + ((COPYING_UNIT *)object_base)[i] + = ((COPYING_UNIT *)h->object_base)[i]; + /* We used to copy the odd few remaining bytes as one extra COPYING_UNIT, + but that can cross a page boundary on a machine + which does not do strict alignment for COPYING_UNITS. */ + already = obj_size / sizeof (COPYING_UNIT) * sizeof (COPYING_UNIT); + } + else + already = 0; + /* Copy remaining bytes one by one. */ + for (i = already; i < obj_size; i++) + object_base[i] = h->object_base[i]; + + /* If the object just copied was the only data in OLD_CHUNK, + free that chunk and remove it from the chain. + But not if that chunk might contain an empty object. */ + if (! h->maybe_empty_object + && (h->object_base + == __PTR_ALIGN ((char *) old_chunk, old_chunk->contents, + h->alignment_mask))) + { + new_chunk->prev = old_chunk->prev; + CALL_FREEFUN (h, old_chunk); + } + + h->object_base = object_base; + h->next_free = h->object_base + obj_size; + /* The new chunk certainly contains no empty object yet. */ + h->maybe_empty_object = 0; +} + +/* Return nonzero if object OBJ has been allocated from obstack H. + This is here for debugging. + If you use it in a program, you are probably losing. */ + +/* Free objects in obstack H, including OBJ and everything allocate + more recently than OBJ. If OBJ is zero, free everything in H. */ +static void obstack_free_func (struct obstack *h, void *obj) +{ + register struct _obstack_chunk *lp; /* below addr of any objects in this chunk */ + register struct _obstack_chunk *plp; /* point to previous chunk if any */ + + lp = h->chunk; + /* We use >= because there cannot be an object at the beginning of a chunk. + But there can be an empty object at that address + at the end of another chunk. */ + while (lp != 0 && ((void *) lp >= obj || (void *) (lp)->limit < obj)) + { + plp = lp->prev; + CALL_FREEFUN (h, lp); + lp = plp; + /* If we switch chunks, we can't tell whether the new current + chunk contains an empty object, so assume that it may. */ + h->maybe_empty_object = 1; + } + if (lp) + { + h->object_base = h->next_free = (char *) (obj); + h->chunk_limit = lp->limit; + h->chunk = lp; + } + else if (obj != 0) + /* obj is not in any of the chunks! */ + abort (); +} + +static int _obstack_memory_used (struct obstack *h) +{ + register struct _obstack_chunk* lp; + register int nbytes = 0; + + for (lp = h->chunk; lp != 0; lp = lp->prev) + { + nbytes += lp->limit - (char *) lp; + } + return nbytes; +} + +static void __attribute__ ((noreturn)) print_and_abort (void) +{ + fprintf(stderr, "%s\n", "memory exhausted"); + exit(1); +} + +/* END LOCAL ADDITION */ + +#ifdef __cplusplus +} /* C++ */ +#endif + +#endif /* obstack.h */ diff --git a/packages/libelf/qsort_r.h b/packages/libelf/qsort_r.h new file mode 100644 index 000000000..58c5d97b4 --- /dev/null +++ b/packages/libelf/qsort_r.h @@ -0,0 +1,195 @@ +/* https://raw.githubusercontent.com/android/platform_bionic/master/libc/upstream-freebsd/lib/libc/stdlib/qsort.c */ + +#define I_AM_QSORT_R + +/*- + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +#ifdef I_AM_QSORT_R +typedef int cmp_t(void *, const void *, const void *); +#else +typedef int cmp_t(const void *, const void *); +#endif +static inline char *med3(char *, char *, char *, cmp_t *, void *); +static inline void swapfunc(char *, char *, int, int); + +#define min(a, b) (a) < (b) ? a : b + +/* + * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function". + */ +#define swapcode(TYPE, parmi, parmj, n) { \ + long i = (n) / sizeof (TYPE); \ + TYPE *pi = (TYPE *) (parmi); \ + TYPE *pj = (TYPE *) (parmj); \ + do { \ + TYPE t = *pi; \ + *pi++ = *pj; \ + *pj++ = t; \ + } while (--i > 0); \ +} + +#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \ + es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1; + +static inline void +swapfunc(a, b, n, swaptype) + char *a, *b; + int n, swaptype; +{ + if(swaptype <= 1) + swapcode(long, a, b, n) + else + swapcode(char, a, b, n) +} + +#define swap(a, b) \ + if (swaptype == 0) { \ + long t = *(long *)(a); \ + *(long *)(a) = *(long *)(b); \ + *(long *)(b) = t; \ + } else \ + swapfunc(a, b, es, swaptype) + +#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype) + +#ifdef I_AM_QSORT_R +#define CMP(t, x, y) (cmp((t), (x), (y))) +#else +#define CMP(t, x, y) (cmp((x), (y))) +#endif + +static inline char * +med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk +#ifndef I_AM_QSORT_R +__unused +#endif +) +{ + return CMP(thunk, a, b) < 0 ? + (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a )) + :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c )); +} + +#ifdef I_AM_QSORT_R +void +qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp) +#else +#define thunk NULL +void +qsort(void *a, size_t n, size_t es, cmp_t *cmp) +#endif +{ + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + size_t d, r; + int cmp_result; + int swaptype, swap_cnt; + +loop: SWAPINIT(a, es); + swap_cnt = 0; + if (n < 7) { + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + d = (n / 8) * es; + pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk); + pm = med3(pm - d, pm, pm + d, cmp, thunk); + pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk); + } + pm = med3(pl, pm, pn, cmp, thunk); + } + swap(a, pm); + pa = pb = (char *)a + es; + + pc = pd = (char *)a + (n - 1) * es; + for (;;) { + while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pa, pb); + pa += es; + } + pb += es; + } + while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swap(pc, pd); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swap(pb, pc); + swap_cnt = 1; + pb += es; + pc -= es; + } + if (swap_cnt == 0) { /* Switch to insertion sort */ + for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es) + for (pl = pm; + pl > (char *)a && CMP(thunk, pl - es, pl) > 0; + pl -= es) + swap(pl, pl - es); + return; + } + + pn = (char *)a + n * es; + r = min(pa - (char *)a, pb - pa); + vecswap(a, pb - r, r); + r = min(pd - pc, pn - pd - es); + vecswap(pb, pn - r, r); + if ((r = pb - pa) > es) +#ifdef I_AM_QSORT_R + qsort_r(a, r / es, es, thunk, cmp); +#else + qsort(a, r / es, es, cmp); +#endif + if ((r = pd - pc) > es) { + /* Iterate rather than recurse to save stack space */ + a = pn - r; + n = r / es; + goto loop; + } +/* qsort(pn - r, r / es, es, cmp);*/ +} + diff --git a/packages/libelf/ranlib.c.patch b/packages/libelf/ranlib.c.patch new file mode 100644 index 000000000..2c5da693b --- /dev/null +++ b/packages/libelf/ranlib.c.patch @@ -0,0 +1,15 @@ +diff -u -r ../elfutils-0.166/src/ranlib.c ./src/ranlib.c +--- ../elfutils-0.166/src/ranlib.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./src/ranlib.c 2016-05-04 14:18:56.314550152 -0400 +@@ -138,11 +138,6 @@ + + assert (off + n <= len); + +- /* Tell the kernel we will read all the pages sequentially. */ +- size_t ps = sysconf (_SC_PAGESIZE); +- if (n > 2 * ps) +- posix_madvise (rawfile + (off & ~(ps - 1)), n, POSIX_MADV_SEQUENTIAL); +- + return write_retry (newfd, rawfile + off, n) != (ssize_t) n; + } + diff --git a/packages/libelf/readelf.c.patch b/packages/libelf/readelf.c.patch new file mode 100644 index 000000000..76dd5c878 --- /dev/null +++ b/packages/libelf/readelf.c.patch @@ -0,0 +1,38 @@ +diff -u -r ../elfutils-0.166/src/readelf.c ./src/readelf.c +--- ../elfutils-0.166/src/readelf.c 2016-03-02 11:25:38.000000000 -0500 ++++ ./src/readelf.c 2016-05-04 14:13:42.967553723 -0400 +@@ -43,6 +43,7 @@ + #include + #include + #include ++#include + + #include + #include "../libelf/libelfP.h" +@@ -6128,7 +6129,7 @@ + + printf (" %*s%-20s (%s) %s\n", + (int) (level * 2), "", dwarf_attr_name (attr), +- dwarf_form_name (form), nl_langinfo (flag ? YESSTR : NOSTR)); ++ dwarf_form_name (form), flag ? "yes" : "no"); + break; + + case DW_FORM_flag_present: +@@ -6136,7 +6137,7 @@ + break; + printf (" %*s%-20s (%s) %s\n", + (int) (level * 2), "", dwarf_attr_name (attr), +- dwarf_form_name (form), nl_langinfo (YESSTR)); ++ dwarf_form_name (form), "yes"); + break; + + case DW_FORM_exprloc: +@@ -7646,7 +7647,7 @@ + if (readp + 1 > readendp) + goto invalid_data; + val = *readp++; +- printf (" %s", nl_langinfo (val != 0 ? YESSTR : NOSTR)); ++ printf (" %s", val != 0 ? "yes" : "no"); + break; + + case DW_FORM_string: diff --git a/packages/libelf/stdio_ext.h b/packages/libelf/stdio_ext.h new file mode 100644 index 000000000..114230774 --- /dev/null +++ b/packages/libelf/stdio_ext.h @@ -0,0 +1,47 @@ +#ifndef STDIO_EXT_H_INCLUDED +#define STDIO_EXT_H_INCLUDED + +#include + +/* http://linux.die.net/man/3/__fsetlocking */ +#define FSETLOCKING_INTERNAL 1 +#define FSETLOCKING_BYCALLER 2 +#define FSETLOCKING_QUERY 3 +static inline int __fsetlocking(FILE *stream, int type) +{ + (void) stream; + (void) type; + return FSETLOCKING_INTERNAL; +} + +static inline int feof_unlocked(FILE *stream) +{ + return feof(stream); +} + +static inline int ferror_unlocked(FILE *stream) +{ + return ferror(stream); +} + +static inline int fputs_unlocked(const char *s, FILE *stream) +{ + return fputs(s, stream); +} + +static inline int fputc_unlocked(int c, FILE *stream) +{ + return fputc(c, stream); +} + +static inline size_t fread_unlocked(void *data, size_t size, size_t count, FILE *stream) +{ + return fread(data, size, count, stream); +} + +static inline size_t fwrite_unlocked(const void *data, size_t size, size_t count, FILE *stream) +{ + return fwrite(data, size, count, stream); +} + +#endif diff --git a/packages/libelf/strings.c.patch b/packages/libelf/strings.c.patch new file mode 100644 index 000000000..bf8e5b23f --- /dev/null +++ b/packages/libelf/strings.c.patch @@ -0,0 +1,11 @@ +diff -u -r ../elfutils-0.166/src/strings.c ./src/strings.c +--- ../elfutils-0.166/src/strings.c 2015-11-27 08:36:29.000000000 -0500 ++++ ./src/strings.c 2016-05-04 14:19:55.593602311 -0400 +@@ -494,7 +494,6 @@ + if (mem != MAP_FAILED) + { + /* We will go through the mapping sequentially. */ +- (void) posix_madvise (mem, map_size, POSIX_MADV_SEQUENTIAL); + break; + } + if (errno != EINVAL && errno != ENOMEM) diff --git a/packages/libelf/strip.c.patch b/packages/libelf/strip.c.patch new file mode 100644 index 000000000..f9f4fff0d --- /dev/null +++ b/packages/libelf/strip.c.patch @@ -0,0 +1,20 @@ +diff -u -r ../elfutils-0.166/src/strip.c ./src/strip.c +--- ../elfutils-0.166/src/strip.c 2016-03-02 11:25:38.000000000 -0500 ++++ ./src/strip.c 2016-05-04 14:03:53.052913249 -0400 +@@ -323,8 +323,14 @@ + + /* If we have to preserve the timestamp, we need it in the + format utimes() understands. */ +- tv[0] = pre_st.st_atim; +- tv[1] = pre_st.st_mtim; ++ struct timespec atime; ++ atime.tv_sec = pre_st.st_atime; ++ atime.tv_nsec = pre_st.st_atime_nsec; ++ struct timespec mtime; ++ mtime.tv_sec = pre_st.st_mtime; ++ mtime.tv_nsec = pre_st.st_mtime_nsec; ++ tv[0] = atime; ++ tv[1] = mtime; + } + + /* Open the file. */ diff --git a/packages/libelf/system.h.patch b/packages/libelf/system.h.patch deleted file mode 100644 index b63071197..000000000 --- a/packages/libelf/system.h.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff -u -r ../elfutils-0.159/lib/system.h ./lib/system.h ---- ../elfutils-0.159/lib/system.h 2014-02-05 01:21:43.000000000 +0100 -+++ ./lib/system.h 2014-05-30 15:10:19.914184259 +0200 -@@ -29,7 +29,9 @@ - #ifndef LIB_SYSTEM_H - #define LIB_SYSTEM_H 1 - -+#ifndef __ANDROID__ - #include -+#endif - #include - #include - #include diff --git a/packages/libelf/unstrip.c.patch b/packages/libelf/unstrip.c.patch new file mode 100644 index 000000000..4ae3b8c6a --- /dev/null +++ b/packages/libelf/unstrip.c.patch @@ -0,0 +1,24 @@ +diff -u -r ../elfutils-0.166/src/unstrip.c ./src/unstrip.c +--- ../elfutils-0.166/src/unstrip.c 2016-01-12 07:49:19.000000000 -0500 ++++ ./src/unstrip.c 2016-05-04 15:22:24.975567076 -0400 +@@ -294,6 +294,7 @@ + static void + make_directories (const char *path) + { ++ size_t substr_len; + const char *lastslash = strrchr (path, '/'); + if (lastslash == NULL) + return; +@@ -303,7 +304,11 @@ + if (lastslash == path) + return; + +- char *dir = strndupa (path, lastslash - path); ++ substr_len = lastslash - path; ++ char *dir = alloca(substr_len+1); ++ strncpy(dir, path, substr_len); ++ dir[substr_len] = 0; ++ + while (mkdir (dir, 0777) < 0 && errno != EEXIST) + if (errno == ENOENT) + make_directories (dir);