From 8ab480dda7c2b2bf14b2627dc68784ce7b62c827 Mon Sep 17 00:00:00 2001 From: Aditya Alok Date: Fri, 3 Sep 2021 23:37:15 +0530 Subject: [PATCH] libelf: enable full elfutils package (#7431) --- packages/argp/fix-segfault.patch | 34 + ...-nested-functions-with-macros-part-1.patch | 108 --- ...e-Blocks-instead-of-nested-functions.patch | 484 ---------- packages/libelf/aligned_alloc.c | 59 +- packages/libelf/build.sh | 45 +- packages/libelf/configure-ac.patch | 29 + packages/libelf/debuginfod-client.c.patch | 23 + .../libelf/debuginfod-makefile-pthread.patch | 20 + packages/libelf/debuginfod.cxx.patch | 38 + packages/libelf/dwfl_error.c.patch | 22 - packages/libelf/elf_update.c.patch | 11 - packages/libelf/elfutils.subpackage.sh | 3 + packages/libelf/error.h | 25 - packages/libelf/libdebuginfod.subpackage.sh | 2 + packages/libelf/libdwflP.h.patch | 14 - packages/libelf/obstack.h | 838 +++++++++--------- packages/libelf/qsort_r.h | 260 +++--- packages/libelf/search/hcreate.c | 67 ++ packages/libelf/search/hcreate_r.c | 62 ++ packages/libelf/search/hdestroy_r.c | 42 + packages/libelf/search/hsearch.h | 40 + packages/libelf/search/hsearch_r.c | 144 +++ packages/libelf/search/search.h | 225 +++++ packages/libelf/src-ar-search.patch | 11 + packages/libelf/src-elflint.patch | 11 + packages/libelf/src-makefile-search.patch | 23 + packages/libelf/src-readelf.c.patch | 11 - packages/libelf/src-readelf.patch | 26 + packages/libelf/stdio_ext.h | 41 +- packages/libelf/system.h.patch | 12 + 30 files changed, 1411 insertions(+), 1319 deletions(-) create mode 100644 packages/argp/fix-segfault.patch delete mode 100644 packages/libelf/0002-Replace-libdwfl-nested-functions-with-macros-part-1.patch delete mode 100644 packages/libelf/0003-For-clang-use-Blocks-instead-of-nested-functions.patch create mode 100644 packages/libelf/configure-ac.patch create mode 100644 packages/libelf/debuginfod-client.c.patch create mode 100644 packages/libelf/debuginfod-makefile-pthread.patch create mode 100644 packages/libelf/debuginfod.cxx.patch delete mode 100644 packages/libelf/dwfl_error.c.patch delete mode 100644 packages/libelf/elf_update.c.patch create mode 100644 packages/libelf/elfutils.subpackage.sh delete mode 100644 packages/libelf/error.h create mode 100644 packages/libelf/libdebuginfod.subpackage.sh delete mode 100644 packages/libelf/libdwflP.h.patch create mode 100644 packages/libelf/search/hcreate.c create mode 100644 packages/libelf/search/hcreate_r.c create mode 100644 packages/libelf/search/hdestroy_r.c create mode 100644 packages/libelf/search/hsearch.h create mode 100644 packages/libelf/search/hsearch_r.c create mode 100644 packages/libelf/search/search.h create mode 100644 packages/libelf/src-ar-search.patch create mode 100644 packages/libelf/src-elflint.patch create mode 100644 packages/libelf/src-makefile-search.patch delete mode 100644 packages/libelf/src-readelf.c.patch create mode 100644 packages/libelf/src-readelf.patch create mode 100644 packages/libelf/system.h.patch diff --git a/packages/argp/fix-segfault.patch b/packages/argp/fix-segfault.patch new file mode 100644 index 000000000..e2b7a6cf8 --- /dev/null +++ b/packages/argp/fix-segfault.patch @@ -0,0 +1,34 @@ +similar to https://www.gnu.org/software/gnutls/clang/report-NwyD8A.html + +--- argp-standalone-1.3/argp-help.c 2003-12-11 14:07:05.000000000 +0530 ++++ argp-standalone-1.3-patch/argp-help.c 2021-08-30 20:06:23.807999907 +0530 +@@ -726,15 +726,20 @@ + canon_doc_option (const char **name) + { + int non_opt; +- /* Skip initial whitespace. */ +- while (isspace ( (unsigned char) **name)) +- (*name)++; +- /* Decide whether this looks like an option (leading `-') or not. */ +- non_opt = (**name != '-'); +- /* Skip until part of name used for sorting. */ +- while (**name && !isalnum ( (unsigned char) **name)) +- (*name)++; +- return non_opt; ++ ++ if(!*name) ++ non_opt = 1; ++ else { ++ /* Skip initial whitespace. */ ++ while (isspace ( (unsigned char) **name)) ++ (*name)++; ++ /* Decide whether this looks like an option (leading `-') or not. */ ++ non_opt = (**name != '-'); ++ /* Skip until part of name used for sorting. */ ++ while (**name && !isalnum ( (unsigned char) **name)) ++ (*name)++; ++ return non_opt; ++ } + } + + /* Order ENTRY1 & ENTRY2 by the order which they should appear in a help diff --git a/packages/libelf/0002-Replace-libdwfl-nested-functions-with-macros-part-1.patch b/packages/libelf/0002-Replace-libdwfl-nested-functions-with-macros-part-1.patch deleted file mode 100644 index e10a58aab..000000000 --- a/packages/libelf/0002-Replace-libdwfl-nested-functions-with-macros-part-1.patch +++ /dev/null @@ -1,108 +0,0 @@ -From 05d21996ba7b8cb7c8708ad8f7a6678d406e0936 Mon Sep 17 00:00:00 2001 -From: Chih-Hung Hsieh -Date: Sun, 31 May 2020 14:03:51 +0100 -Subject: [PATCH 2/3] Replace libdwfl nested functions with macros, part 1. - -Prepare to compile with clang. ---- - libdwfl/elf-from-memory.c | 77 +++++++++++++++++++++------------------ - 1 file changed, 42 insertions(+), 35 deletions(-) - -diff --git a/libdwfl/elf-from-memory.c b/libdwfl/elf-from-memory.c -index c54c1b9..143e124 100644 ---- a/libdwfl/elf-from-memory.c -+++ b/libdwfl/elf-from-memory.c -@@ -229,29 +229,33 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, - segments_end, segments_end_mem and loadbase (if not - found_base yet). Returns true if sanity checking failed, - false otherwise. */ -- inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, -- GElf_Xword filesz, GElf_Xword memsz) -- { -- /* Sanity check the segment load aligns with the pagesize. */ -- if (((vaddr - offset) & (pagesize - 1)) != 0) -- return true; -- -- GElf_Off segment_end = ((offset + filesz + pagesize - 1) -- & -pagesize); -- -- if (segment_end > (GElf_Off) contents_size) -- contents_size = segment_end; -- -- if (!found_base && (offset & -pagesize) == 0) -- { -- loadbase = ehdr_vma - (vaddr & -pagesize); -- found_base = true; -- } -- -- segments_end = offset + filesz; -- segments_end_mem = offset + memsz; -- return false; -- } -+ #define handle_segment(_vaddr, _offset, _filesz, _memsz) \ -+ ( { \ -+ bool result; \ -+ GElf_Addr vaddr = _vaddr; \ -+ GElf_Off offset = _offset; \ -+ GElf_Xword filesz = _filesz; \ -+ GElf_Xword memsz = _memsz; \ -+ /* Sanity check the segment load aligns with the pagesize. */ \ -+ if (((vaddr - offset) & (pagesize - 1)) != 0) \ -+ result = true; \ -+ else \ -+ { \ -+ result = false; \ -+ GElf_Off segment_end = ((offset + filesz + pagesize - 1) \ -+ & -pagesize); \ -+ if (segment_end > (GElf_Off) contents_size) \ -+ contents_size = segment_end; \ -+ if (!found_base && (offset & -pagesize) == 0) \ -+ { \ -+ loadbase = ehdr_vma - (vaddr & -pagesize); \ -+ found_base = true; \ -+ } \ -+ segments_end = offset + filesz; \ -+ segments_end_mem = offset + memsz; \ -+ } \ -+ result; \ -+ } ) - - case ELFCLASS32: - if (elf32_xlatetom (&xlateto, &xlatefrom, -@@ -309,18 +313,21 @@ elf_from_remote_memory (GElf_Addr ehdr_vma, - { - /* Reads the given segment. Returns true if reading fails, - false otherwise. */ -- inline bool handle_segment (GElf_Addr vaddr, GElf_Off offset, -- GElf_Xword filesz) -- { -- GElf_Off start = offset & -pagesize; -- GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; -- if (end > (GElf_Off) contents_size) -- end = contents_size; -- nread = (*read_memory) (arg, buffer + start, -- (loadbase + vaddr) & -pagesize, -- end - start, end - start); -- return nread <= 0; -- } -+ #undef handle_segment -+ #define handle_segment(_vaddr, _offset, _filesz) \ -+ ( { \ -+ GElf_Addr vaddr = _vaddr; \ -+ GElf_Off offset = _offset; \ -+ GElf_Xword filesz = _filesz; \ -+ GElf_Off start = offset & -pagesize; \ -+ GElf_Off end = (offset + filesz + pagesize - 1) & -pagesize; \ -+ if (end > (GElf_Off) contents_size) \ -+ end = contents_size; \ -+ nread = (*read_memory) (arg, buffer + start, \ -+ (loadbase + vaddr) & -pagesize, \ -+ end - start, end - start); \ -+ (nread <= 0); \ -+ } ) - - case ELFCLASS32: - for (uint_fast16_t i = 0; i < phnum; ++i) --- -2.26.2 - diff --git a/packages/libelf/0003-For-clang-use-Blocks-instead-of-nested-functions.patch b/packages/libelf/0003-For-clang-use-Blocks-instead-of-nested-functions.patch deleted file mode 100644 index 68d33e849..000000000 --- a/packages/libelf/0003-For-clang-use-Blocks-instead-of-nested-functions.patch +++ /dev/null @@ -1,484 +0,0 @@ -From e0785056a91f893ef4235aefb2a26bed3b17537f Mon Sep 17 00:00:00 2001 -From: Chih-Hung Hsieh -Date: Sun, 31 May 2020 14:06:12 +0100 -Subject: [PATCH 3/3] For clang use Blocks instead of nested functions. - -* Clang has Blocks like closures that can serve similar - purpose as the nested functions in gnu99. - Syntax of Blocks is similar to nested functions that - *NESTED_FUNC macro can be used for the function/block - declarations. - See spec in http://clang.llvm.org/docs/BlockLanguageSpec.html -* Local variables used in a closure should have __BLOCK - attribute unless they are constants. -* Formal parameters used in a closure should be copied - to local variable and declared as __BLOCK. -* Cannot goto and jump over __BLOCK variables, so these - variables have been moved to be declared before goto. -* Clang Blocks cannot copy an array to a closure, - and gcc complains about unbounded stack usage from alloca. ---- - lib/nested_func.h | 85 +++++++++++++++++++ - libdwfl/dwfl_segment_report_module.c | 117 ++++++++++++++++----------- - libdwfl/link_map.c | 31 ++++--- - 3 files changed, 174 insertions(+), 59 deletions(-) - create mode 100644 lib/nested_func.h - -diff --git a/lib/nested_func.h b/lib/nested_func.h -new file mode 100644 -index 0000000..be44a31 ---- /dev/null -+++ b/lib/nested_func.h -@@ -0,0 +1,85 @@ -+/* Copyright (C) 2015 Red Hat, Inc. -+ This file is part of elfutils. -+ Written by Chih-Hung Hsieh , 2015. -+ -+ This file is free software; you can redistribute it and/or modify -+ it under the terms of either -+ -+ * the GNU Lesser General Public License as published by the Free -+ Software Foundation; either version 3 of the License, or (at -+ your option) any later version -+ -+ or -+ -+ * the GNU General Public License as published by the Free -+ Software Foundation; either version 2 of the License, or (at -+ your option) any later version -+ -+ or both in parallel, as here. -+ -+ elfutils is distributed in the hope that it will be useful, but -+ WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -+ General Public License for more details. -+ -+ You should have received copies of the GNU General Public License and -+ the GNU Lesser General Public License along with this program. If -+ not, see . */ -+ -+#ifndef _NESTED_FUNC_H -+#define _NESTED_FUNC_H 1 -+ -+#if __clang__ -+ -+ #define __BLOCK __block -+ -+ #define NESTED_FUNC(return_type, function_name, \ -+ arg_types, arg_types_and_names) \ -+ return_type (^function_name) arg_types = \ -+ ^ return_type arg_types_and_names -+ -+ /* Clang does not like inline keyword before a block variable. */ -+ #define INLINE_NESTED_FUNC(r, f, t, a) \ -+ NESTED_FUNC (r, f, t, a) -+ -+ #define INLINE_INTUSE_NESTED_FUNC(r, f, t, a) \ -+ NESTED_FUNC (r, INTUSE(f), t, a) -+ -+ /* Recrusive blocks need to be declared before used. */ -+ #define RECURSIVE_NESTED_FUNC(return_type, function_name, \ -+ arg_types, arg_types_and_names) \ -+ __BLOCK return_type (^function_name) arg_types; \ -+ function_name = ^ return_type arg_types_and_names -+ -+ #define INLINE_RECURSIVE_NESTED_FUNC(r, f, t, a) \ -+ RECURSIVE_NESTED_FUNC (r, f, t, a) -+ -+ #define INLINE_INTUSE_RECURSIVE_NESTED_FUNC(r, f, t, a) \ -+ RECURSIVE_NESTED_FUNC (r, INTUSE(f), t, a) -+ -+#else /* gcc nested function */ -+ -+ #define __BLOCK -+ -+ #define NESTED_FUNC(return_type, function_name, \ -+ arg_types, arg_types_and_names) \ -+ return_type function_name arg_types_and_names -+ -+ #define INLINE_NESTED_FUNC(r, f, t, a) \ -+ inline NESTED_FUNC (r, f, t, a) -+ -+ #define INLINE_INTUSE_NESTED_FUNC(r, f, t, a) \ -+ inline NESTED_FUNC (r, INTUSE(f), t, a) -+ -+ #define RECURSIVE_NESTED_FUNC(r, f, t, a) \ -+ NESTED_FUNC (r, f, t, a) -+ -+ #define INLINE_RECURSIVE_NESTED_FUNC(r, f, t, a) \ -+ inline RECURSIVE_NESTED_FUNC (r, f, t, a) -+ -+ #define INLINE_INTUSE_RECURSIVE_NESTED_FUNC(r, f, t, a) \ -+ INLINE_RECURSIVE_NESTED_FUNC (r, INTUSE(f), t, a) -+ -+#endif -+ -+#endif /* _NESTED_FUNC_H */ -diff --git a/libdwfl/dwfl_segment_report_module.c b/libdwfl/dwfl_segment_report_module.c -index 430e13d..b7c6733 100644 ---- a/libdwfl/dwfl_segment_report_module.c -+++ b/libdwfl/dwfl_segment_report_module.c -@@ -31,6 +31,7 @@ - #undef _ - #include "libdwflP.h" - #include "common.h" -+#include "nested_func.h" - - #include - #include -@@ -257,19 +258,23 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - - GElf_Addr start = dwfl->lookup_addr[segment]; - -- inline bool segment_read (int segndx, -- void **buffer, size_t *buffer_available, -- GElf_Addr addr, size_t minread) -+ INLINE_NESTED_FUNC (bool, segment_read, -+ (int , void **, size_t *, GElf_Addr, size_t), -+ (int segndx, -+ void **buffer, size_t *buffer_available, -+ GElf_Addr addr, size_t minread)) - { - return ! (*memory_callback) (dwfl, segndx, buffer, buffer_available, - addr, minread, memory_callback_arg); -- } -+ }; - -- inline void release_buffer (void **buffer, size_t *buffer_available) -+ INLINE_NESTED_FUNC (void, release_buffer, -+ (void **, size_t *), -+ (void **buffer, size_t *buffer_available)) - { - if (*buffer != NULL) - (void) segment_read (-1, buffer, buffer_available, 0, 0); -- } -+ }; - - /* First read in the file header and check its sanity. */ - -@@ -282,7 +287,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - here so we can always safely free it. */ - void *phdrsp = NULL; - -- inline int finish (void) -+ INLINE_NESTED_FUNC (int, finish, (void), (void)) - { - free (phdrsp); - release_buffer (&buffer, &buffer_available); -@@ -291,15 +296,17 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - if (fd != -1) - close (fd); - return ndx; -- } -+ }; - - if (segment_read (ndx, &buffer, &buffer_available, - start, sizeof (Elf64_Ehdr)) - || memcmp (buffer, ELFMAG, SELFMAG) != 0) - return finish (); - -- inline bool read_portion (void **data, size_t *data_size, -- GElf_Addr vaddr, size_t filesz) -+ INLINE_NESTED_FUNC (bool, read_portion, -+ (void **, size_t *, GElf_Addr, size_t), -+ (void **data, size_t *data_size, -+ GElf_Addr vaddr, size_t filesz)) - { - /* Check whether we will have to read the segment data, or if it - can be returned from the existing buffer. */ -@@ -320,13 +327,15 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - *data = vaddr - start + buffer; - *data_size = 0; - return false; -- } -+ }; - -- inline void finish_portion (void **data, size_t *data_size) -+ INLINE_NESTED_FUNC (void, finish_portion, -+ (void **, size_t *), -+ (void **data, size_t *data_size)) - { - if (*data_size != 0) - release_buffer (data, data_size); -- } -+ }; - - /* Extract the information we need from the file header. */ - const unsigned char *e_ident; -@@ -342,13 +351,13 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - uint_fast16_t phnum; - uint_fast16_t phentsize; - GElf_Off shdrs_end; -- Elf_Data xlatefrom = -+ __BLOCK Elf_Data xlatefrom = - { - .d_type = ELF_T_EHDR, - .d_buf = (void *) buffer, - .d_version = EV_CURRENT, - }; -- Elf_Data xlateto = -+ __BLOCK Elf_Data xlateto = - { - .d_type = ELF_T_EHDR, - .d_buf = &ehdr, -@@ -433,32 +442,33 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - xlateto.d_size = phdrsp_bytes; - - /* Track the bounds of the file visible in memory. */ -- GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ -- GElf_Off file_end = 0; /* Rounded up to effective page size. */ -- GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ -- GElf_Off total_filesz = 0; /* Total size of data to read. */ -+ __BLOCK GElf_Off file_trimmed_end = 0; /* Proper p_vaddr + p_filesz end. */ -+ __BLOCK GElf_Off file_end = 0; /* Rounded up to effective page size. */ -+ __BLOCK GElf_Off contiguous = 0; /* Visible as contiguous file from START. */ -+ __BLOCK GElf_Off total_filesz = 0; /* Total size of data to read. */ - - /* Collect the bias between START and the containing PT_LOAD's p_vaddr. */ -- GElf_Addr bias = 0; -- bool found_bias = false; -+ __BLOCK GElf_Addr bias = 0; -+ __BLOCK bool found_bias = false; - - /* Collect the unbiased bounds of the module here. */ -- GElf_Addr module_start = -1l; -- GElf_Addr module_end = 0; -- GElf_Addr module_address_sync = 0; -+ __BLOCK GElf_Addr module_start = -1l; -+ __BLOCK GElf_Addr module_end = 0; -+ __BLOCK GElf_Addr module_address_sync = 0; - - /* If we see PT_DYNAMIC, record it here. */ -- GElf_Addr dyn_vaddr = 0; -- GElf_Xword dyn_filesz = 0; -+ __BLOCK GElf_Addr dyn_vaddr = 0; -+ __BLOCK GElf_Xword dyn_filesz = 0; - - /* Collect the build ID bits here. */ -- void *build_id = NULL; -- size_t build_id_len = 0; -- GElf_Addr build_id_vaddr = 0; -+ __BLOCK void *build_id = NULL; -+ __BLOCK size_t build_id_len = 0; -+ __BLOCK GElf_Addr build_id_vaddr = 0; - - /* Consider a PT_NOTE we've found in the image. */ -- inline void consider_notes (GElf_Addr vaddr, GElf_Xword filesz, -- GElf_Xword align) -+ INLINE_NESTED_FUNC (void, consider_notes, -+ (GElf_Addr, GElf_Xword, GElf_Xword), -+ (GElf_Addr vaddr, GElf_Xword filesz, GElf_Xword align)) - { - /* If we have already seen a build ID, we don't care any more. */ - if (build_id != NULL || filesz == 0) -@@ -535,13 +545,18 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - if (notes != data) - free (notes); - finish_portion (&data, &data_size); -- } -+ }; - - /* Consider each of the program headers we've read from the image. */ -- inline void consider_phdr (GElf_Word type, -- GElf_Addr vaddr, GElf_Xword memsz, -- GElf_Off offset, GElf_Xword filesz, -- GElf_Xword align) -+ INLINE_NESTED_FUNC (void, consider_phdr, -+ (GElf_Word, -+ GElf_Addr, GElf_Xword, -+ GElf_Off, GElf_Xword, -+ GElf_Xword), -+ (GElf_Word type, -+ GElf_Addr vaddr, GElf_Xword memsz, -+ GElf_Off offset, GElf_Xword filesz, -+ GElf_Xword align)) - { - switch (type) - { -@@ -604,7 +619,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - module_end = vaddr_end; - break; - } -- } -+ }; - - Elf32_Phdr (*p32)[phnum] = phdrsp; - Elf64_Phdr (*p64)[phnum] = phdrsp; -@@ -751,11 +766,12 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - We need its DT_STRTAB and DT_STRSZ to decipher DT_SONAME, - and they also tell us the essential portion of the file - for fetching symbols. */ -- GElf_Addr soname_stroff = 0; -- GElf_Addr dynstr_vaddr = 0; -- GElf_Xword dynstrsz = 0; -- bool execlike = false; -- inline bool consider_dyn (GElf_Sxword tag, GElf_Xword val) -+ __BLOCK GElf_Addr soname_stroff = 0; -+ __BLOCK GElf_Addr dynstr_vaddr = 0; -+ __BLOCK GElf_Xword dynstrsz = 0; -+ __BLOCK bool execlike = false; -+ INLINE_NESTED_FUNC (bool, consider_dyn, (GElf_Sxword, GElf_Xword), -+ (GElf_Sxword tag, GElf_Xword val)) - { - switch (tag) - { -@@ -780,7 +796,7 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - } - - return soname_stroff != 0 && dynstr_vaddr != 0 && dynstrsz != 0; -- } -+ }; - - const size_t dyn_entsize = (ei_class == ELFCLASS32 - ? sizeof (Elf32_Dyn) : sizeof (Elf64_Dyn)); -@@ -915,25 +931,30 @@ dwfl_segment_report_module (Dwfl *dwfl, int ndx, const char *name, - if (unlikely (contents == NULL)) - return finish (); - -- inline void final_read (size_t offset, GElf_Addr vaddr, size_t size) -+ INLINE_NESTED_FUNC (void, final_read, -+ (size_t, GElf_Addr, size_t), -+ (size_t offset, GElf_Addr vaddr, size_t size)) - { - void *into = contents + offset; - size_t read_size = size; - (void) segment_read (addr_segndx (dwfl, segment, vaddr, false), - &into, &read_size, vaddr, size); -- } -+ }; - - if (contiguous < file_trimmed_end) - { - /* We can't use the memory image verbatim as the file image. - So we'll be reading into a local image of the virtual file. */ - -- inline void read_phdr (GElf_Word type, GElf_Addr vaddr, -- GElf_Off offset, GElf_Xword filesz) -+ INLINE_NESTED_FUNC (void, read_phdr, -+ (GElf_Word, GElf_Addr, -+ GElf_Off, GElf_Xword), -+ (GElf_Word type, GElf_Addr vaddr, -+ GElf_Off offset, GElf_Xword filesz)) - { - if (type == PT_LOAD) - final_read (offset, vaddr + bias, filesz); -- } -+ }; - - if (ei_class == ELFCLASS32) - for (uint_fast16_t i = 0; i < phnum; ++i) -diff --git a/libdwfl/link_map.c b/libdwfl/link_map.c -index 29307c7..05f4da2 100644 ---- a/libdwfl/link_map.c -+++ b/libdwfl/link_map.c -@@ -30,6 +30,7 @@ - #include "libdwflP.h" - #include "../libdw/memory-access.h" - #include "system.h" -+#include "nested_func.h" - - #include - #include -@@ -245,20 +246,27 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, - struct r_debug_info *r_debug_info) - { - /* Skip r_version, to aligned r_map field. */ -- GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); -+ __BLOCK GElf_Addr read_vaddr = r_debug_vaddr + addrsize (elfclass); - - void *buffer = NULL; - size_t buffer_available = 0; -- inline int release_buffer (int result) -+ INLINE_NESTED_FUNC (int, release_buffer, (int), (int result)) - { - if (buffer != NULL) - (void) (*memory_callback) (dwfl, -1, &buffer, &buffer_available, 0, 0, - memory_callback_arg); - return result; -- } -+ }; - -+#if __clang__ -+ /* Clang Blocks cannot copy an array to a closure. */ -+ __BLOCK GElf_Addr *addrs = alloca(4 * sizeof (GElf_Addr)); -+#else -+ /* gcc complains about unbounded stack usage from alloca. */ - GElf_Addr addrs[4]; -- inline bool read_addrs (GElf_Addr vaddr, size_t n) -+#endif -+ INLINE_NESTED_FUNC (bool, read_addrs, -+ (GElf_Addr, size_t), (GElf_Addr vaddr, size_t n)) - { - size_t nb = n * addrsize (elfclass); /* Address words -> bytes to read. */ - -@@ -301,7 +309,7 @@ report_r_debug (uint_fast8_t elfclass, uint_fast8_t elfdata, - } - - return false; -- } -+ }; - - if (unlikely (read_addrs (read_vaddr, 1))) - return release_buffer (-1); -@@ -754,12 +762,13 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, - } - - /* If we found the phdr dimensions, search phdrs for PT_DYNAMIC. */ -- GElf_Addr dyn_vaddr = 0; -- GElf_Xword dyn_filesz = 0; -- GElf_Addr dyn_bias = (GElf_Addr) -1; -+ __BLOCK GElf_Addr dyn_vaddr = 0; -+ __BLOCK GElf_Xword dyn_filesz = 0; -+ __BLOCK GElf_Addr dyn_bias = (GElf_Addr) -1; - -- inline bool consider_phdr (GElf_Word type, -- GElf_Addr vaddr, GElf_Xword filesz) -+ INLINE_NESTED_FUNC (bool, consider_phdr, -+ (GElf_Word, GElf_Addr, GElf_Xword), -+ (GElf_Word type, GElf_Addr vaddr, GElf_Xword filesz)) - { - switch (type) - { -@@ -781,7 +790,7 @@ dwfl_link_map_report (Dwfl *dwfl, const void *auxv, size_t auxv_size, - } - - return false; -- } -+ }; - - if (phdr != 0 && phnum != 0) - { ---- a/libdw/Makefile.am 2020-05-31 15:31:02.096994754 +0100 -+++ b/libdw/Makefile.am 2020-05-31 15:31:38.456994741 +0100 -@@ -109,7 +109,7 @@ - ../libcpu/libcpu_pic.a libdw_pic.a ../libdwelf/libdwelf_pic.a \ - ../libdwfl/libdwfl_pic.a - libdw_so_DEPS = ../lib/libeu.a ../libelf/libelf.so --libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(zip_LIBS) -pthread -+libdw_so_LDLIBS = $(libdw_so_DEPS) -ldl -lz $(argp_LDADD) $(zip_LIBS) -pthread -lBlocksRuntime - libdw_so_SOURCES = - libdw.so$(EXEEXT): $(srcdir)/libdw.map $(libdw_so_LIBS) $(libdw_so_DEPS) - $(AM_V_CCLD)$(LINK) $(dso_LDFLAGS) -o $@ \ -diff --git a/libdwfl/Makefile.am b/libdwfl/Makefile.am -index 47bd62a..cba562f 100644 ---- a/libdwfl/Makefile.am -+++ b/libdwfl/Makefile.am -@@ -40,6 +40,7 @@ noinst_LIBRARIES += libdwfl_pic.a - pkginclude_HEADERS = libdwfl.h - - -+AM_CFLAGS += -fblocks - libdwfl_a_SOURCES = dwfl_begin.c dwfl_end.c dwfl_error.c dwfl_version.c \ - dwfl_module.c dwfl_report_elf.c relocate.c \ - dwfl_module_build_id.c dwfl_module_report_build_id.c \ ---- a/config/libdw.pc.in 2020-05-31 15:57:15.036994154 +0100 -+++ b/config/libdw.pc.in 2020-05-31 15:57:46.646994142 +0100 -@@ -19,4 +19,4 @@ - # data structures or functions. zlib (gz) is always required, bzip2 (bz2) - # lzma (xz) and zstd () are optional. But bzip2 doesn't have a pkg-config file. - Requires.private: zlib @LIBLZMA@ @LIBZSTD@ --Libs.private: @BZ2_LIB@ -+Libs.private: @BZ2_LIB@ BlocksRuntime --- -2.26.2 diff --git a/packages/libelf/aligned_alloc.c b/packages/libelf/aligned_alloc.c index 08840b7aa..0851b949a 100644 --- a/packages/libelf/aligned_alloc.c +++ b/packages/libelf/aligned_alloc.c @@ -19,49 +19,46 @@ *****************************************************************************/ #ifdef HAVE_CONFIG_H -# include +#include #endif #include -#include #include -#if !defined (HAVE_POSIX_MEMALIGN) -# include +#include +#if !defined(HAVE_POSIX_MEMALIGN) +#include #endif -void *aligned_alloc(size_t align, size_t size) -{ - /* align must be a power of 2 */ - /* size must be a multiple of align */ - if ((align & (align - 1)) || (size & (align - 1))) - { - errno = EINVAL; - return NULL; - } +void *aligned_alloc(size_t align, size_t size) { + /* align must be a power of 2 */ + /* size must be a multiple of align */ + if ((align & (align - 1)) || (size & (align - 1))) { + errno = EINVAL; + return NULL; + } #ifdef __ANDROID__ - if (align < sizeof (void *)) /* POSIX does not allow small alignment */ - align = sizeof (void *); + if (align < sizeof(void *)) /* POSIX does not allow small alignment */ + align = sizeof(void *); - void *ptr; - int err = posix_memalign(&ptr, align, size); - if (err) - { - errno = err; - ptr = NULL; - } - return ptr; + void *ptr; + int err = posix_memalign(&ptr, align, size); + if (err) { + errno = err; + ptr = NULL; + } + return ptr; #elif defined(HAVE_MEMALIGN) - return memalign(align, size); -#elif defined (_WIN32) && defined(__MINGW32__) - return __mingw_aligned_malloc(size, align); -#elif defined (_WIN32) && defined(_MSC_VER) - return _aligned_malloc(size, align); + return memalign(align, size); +#elif defined(_WIN32) && defined(__MINGW32__) + return __mingw_aligned_malloc(size, align); +#elif defined(_WIN32) && defined(_MSC_VER) + return _aligned_malloc(size, align); #else #warning unsupported aligned allocation! - if (size > 0) - errno = ENOMEM; - return NULL; + if (size > 0) + errno = ENOMEM; + return NULL; #endif } diff --git a/packages/libelf/build.sh b/packages/libelf/build.sh index 8eaa8ebb1..81ec298a7 100644 --- a/packages/libelf/build.sh +++ b/packages/libelf/build.sh @@ -2,22 +2,22 @@ TERMUX_PKG_HOMEPAGE=https://sourceware.org/elfutils/ TERMUX_PKG_DESCRIPTION="ELF object file access library" TERMUX_PKG_LICENSE="GPL-2.0" TERMUX_PKG_MAINTAINER="@termux" -# NOTE: We only build the libelf part of elfutils for now, -# as other parts are not clang compatible. -TERMUX_PKG_VERSION=0.182 -TERMUX_PKG_SRCURL=ftp://sourceware.org/pub/elfutils/${TERMUX_PKG_VERSION}/elfutils-${TERMUX_PKG_VERSION}.tar.bz2 -TERMUX_PKG_SHA256=ecc406914edf335f0b7fc084ebe6c460c4d6d5175bfdd6688c1c78d9146b8858 +TERMUX_PKG_VERSION=0.185 +TERMUX_PKG_SRCURL="https://sourceware.org/elfutils/ftp/${TERMUX_PKG_VERSION}/elfutils-${TERMUX_PKG_VERSION}.tar.bz2" +TERMUX_PKG_SHA256=dc8d3e74ab209465e7f568e1b3bb9a5a142f8656e2b57d10049a73da2ae6b5a6 # libandroid-support for langinfo. -TERMUX_PKG_DEPENDS="libandroid-support, zlib, libcurl" -TERMUX_PKG_BUILD_DEPENDS="argp" -TERMUX_PKG_EXTRA_CONFIGURE_ARGS="ac_cv_c99=yes --disable-symbol-versioning --disable-debuginfod" -TERMUX_PKG_CONFLICTS="elfutils, libelf-dev" -TERMUX_PKG_REPLACES="elfutils, libelf-dev" +TERMUX_PKG_DEPENDS="libandroid-support, zlib, libcurl, libmicrohttpd, libsqlite, libarchive" +TERMUX_PKG_BUILD_DEPENDS="argp, libbz2, liblzma, zstd" +TERMUX_PKG_EXTRA_CONFIGURE_ARGS="ac_cv_c99=yes --disable-symbol-versioning" +TERMUX_PKG_CONFLICTS="libelf-dev" +TERMUX_PKG_REPLACES="libelf-dev" +TERMUX_PKG_BUILD_IN_SRC=true termux_step_pre_configure() { + CXXFLAGS+=" -Wno-unused-const-variable" CFLAGS+=" -Wno-error=unused-value -Wno-error=format-nonliteral -Wno-error" - # Exposes ACCESSPERMS in which elfutils uses: + # Exposes ACCESSPERMS in which elfutils uses CFLAGS+=" -D__USE_BSD" CFLAGS+=" -DFNM_EXTMATCH=0" @@ -26,30 +26,11 @@ termux_step_pre_configure() { CFLAGS="${CFLAGS/-Oz/-O1}" fi - 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 . cp $TERMUX_PKG_BUILDER_DIR/aligned_alloc.c libelf - autoreconf -if -} + cp -r $TERMUX_PKG_BUILDER_DIR/search src/ -termux_step_make() { - make -j $TERMUX_MAKE_PROCESSES -C lib - make -j $TERMUX_MAKE_PROCESSES -C libelf - make -j $TERMUX_MAKE_PROCESSES -C libdwfl - make -j $TERMUX_MAKE_PROCESSES -C libebl - make -j $TERMUX_MAKE_PROCESSES -C backends - make -j $TERMUX_MAKE_PROCESSES -C libcpu - make -j $TERMUX_MAKE_PROCESSES -C libdwelf - make -j $TERMUX_MAKE_PROCESSES -C libdw -} - -termux_step_make_install() { - make -j $TERMUX_MAKE_PROCESSES -C libelf install - make -j $TERMUX_MAKE_PROCESSES -C libdwfl install - make -j $TERMUX_MAKE_PROCESSES -C libdw install - make -j $TERMUX_MAKE_PROCESSES -C libasm install - make install-pkgincludeHEADERS - make -C config install + autoreconf -ivf } diff --git a/packages/libelf/configure-ac.patch b/packages/libelf/configure-ac.patch new file mode 100644 index 000000000..5ff9b9f32 --- /dev/null +++ b/packages/libelf/configure-ac.patch @@ -0,0 +1,29 @@ +--- elfutils-0.185/configure.ac 2021-08-29 20:49:11.091999844 +0530 ++++ elfutils-0.185-patch/configure.ac 2021-08-30 15:42:30.083999825 +0530 +@@ -575,16 +575,6 @@ + esac + AC_SUBST([fts_LIBS]) + +-saved_LIBS="$LIBS" +-AC_SEARCH_LIBS([_obstack_free], [obstack]) +-LIBS="$saved_LIBS" +-case "$ac_cv_search__obstack_free" in +- no) AC_MSG_FAILURE([failed to find _obstack_free]) ;; +- -l*) obstack_LIBS="$ac_cv_search__obstack_free" ;; +- *) obstack_LIBS= ;; +-esac +-AC_SUBST([obstack_LIBS]) +- + dnl The directories with content. + + dnl Documentation. +@@ -747,8 +737,7 @@ + fi + ]) + +-AC_CHECK_LIB(pthread, pthread_setname_np, [ +- AC_DEFINE([HAVE_PTHREAD_SETNAME_NP],[1],[Enable pthread_setname_np])]) ++ AC_DEFINE([HAVE_PTHREAD_SETNAME_NP],[1],[Enable pthread_setname_np]) + + AS_IF([test "x$enable_libdebuginfod" = "xyes" || test "x$enable_libdebuginfod" = "xdummy"], + [AC_DEFINE([ENABLE_LIBDEBUGINFOD], [1], [Enable libdebuginfod])]) diff --git a/packages/libelf/debuginfod-client.c.patch b/packages/libelf/debuginfod-client.c.patch new file mode 100644 index 000000000..7e4dd04f2 --- /dev/null +++ b/packages/libelf/debuginfod-client.c.patch @@ -0,0 +1,23 @@ +--- elfutils-0.185/debuginfod/debuginfod-client.c 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/debuginfod/debuginfod-client.c 2021-08-28 22:14:21.559999738 +0530 +@@ -85,6 +85,20 @@ + #include + #include + ++static int futimes(int fd, const struct timeval tv[2]) { ++ if (tv == NULL) ++ return syscall(__NR_utimensat, fd, NULL, NULL, 0); ++ if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 || tv[1].tv_usec < 0 || ++ tv[1].tv_usec >= 1000000) { ++ return -1; ++ } ++ // Convert timeval to timespec. ++ struct timespec ts[2]; ++ TIMEVAL_TO_TIMESPEC(tv, ts); ++ ++ return syscall(__NR_utimensat, fd, NULL, ts, 0); ++} ++ + /* If fts.h is included before config.h, its indirect inclusions may not + give us the right LFS aliases of these functions, so map them manually. */ + #ifdef BAD_FTS diff --git a/packages/libelf/debuginfod-makefile-pthread.patch b/packages/libelf/debuginfod-makefile-pthread.patch new file mode 100644 index 000000000..d4a130d48 --- /dev/null +++ b/packages/libelf/debuginfod-makefile-pthread.patch @@ -0,0 +1,20 @@ +--- elfutils-0.185/debuginfod/Makefile.am 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/debuginfod/Makefile.am 2021-08-29 00:51:31.449999941 +0530 +@@ -42,7 +42,7 @@ + + if BUILD_STATIC + libasm = ../libasm/libasm.a +-libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl -lpthread ++libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) $(libebl) -ldl + libelf = ../libelf/libelf.a -lz + if DUMMY_LIBDEBUGINFOD + libdebuginfod = ./libdebuginfod.a +@@ -70,7 +70,7 @@ + endif + + debuginfod_SOURCES = debuginfod.cxx +-debuginfod_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(argp_LDADD) $(fts_LIBS) $(libmicrohttpd_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -lpthread -ldl ++debuginfod_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(argp_LDADD) $(fts_LIBS) $(libmicrohttpd_LIBS) $(sqlite3_LIBS) $(libarchive_LIBS) -ldl + + debuginfod_find_SOURCES = debuginfod-find.c + debuginfod_find_LDADD = $(libdw) $(libelf) $(libeu) $(libdebuginfod) $(argp_LDADD) $(fts_LIBS) diff --git a/packages/libelf/debuginfod.cxx.patch b/packages/libelf/debuginfod.cxx.patch new file mode 100644 index 000000000..0943c73d3 --- /dev/null +++ b/packages/libelf/debuginfod.cxx.patch @@ -0,0 +1,38 @@ +--- elfutils-0.185/debuginfod/debuginfod.cxx 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/debuginfod/debuginfod.cxx 2021-08-28 23:44:30.087999769 +0530 +@@ -58,7 +58,6 @@ + #include + #include + +- + /* If fts.h is included before config.h, its indirect inclusions may not + give us the right LFS aliases of these functions, so map them manually. */ + #ifdef BAD_FTS +@@ -93,6 +92,7 @@ + #include + + #include ++#include + + #if MHD_VERSION >= 0x00097002 + // libmicrohttpd 0.9.71 broke API +@@ -116,6 +116,19 @@ + #define tid() pthread_self() + #endif + ++static int futimes(int fd, const struct timeval tv[2]) { ++ if (tv == NULL) ++ return syscall(__NR_utimensat, fd, NULL, NULL, 0); ++ if (tv[0].tv_usec < 0 || tv[0].tv_usec >= 1000000 || tv[1].tv_usec < 0 || ++ tv[1].tv_usec >= 1000000) { ++ return -1; ++ } ++ // Convert timeval to timespec. ++ struct timespec ts[2]; ++ TIMEVAL_TO_TIMESPEC(tv, ts); ++ ++ return syscall(__NR_utimensat, fd, NULL, ts, 0); ++} + + inline bool + string_endswith(const string& haystack, const string& needle) diff --git a/packages/libelf/dwfl_error.c.patch b/packages/libelf/dwfl_error.c.patch deleted file mode 100644 index acaa692df..000000000 --- a/packages/libelf/dwfl_error.c.patch +++ /dev/null @@ -1,22 +0,0 @@ -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/elf_update.c.patch b/packages/libelf/elf_update.c.patch deleted file mode 100644 index fd5cd6f5d..000000000 --- a/packages/libelf/elf_update.c.patch +++ /dev/null @@ -1,11 +0,0 @@ -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" - -+#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/elfutils.subpackage.sh b/packages/libelf/elfutils.subpackage.sh new file mode 100644 index 000000000..4f5f99eff --- /dev/null +++ b/packages/libelf/elfutils.subpackage.sh @@ -0,0 +1,3 @@ +TERMUX_SUBPKG_DESCRIPTION="A collection of utilities to read, create and modify ELF binary files" +TERMUX_SUBPKG_INCLUDE="bin/eu-* bin/debuginfod* etc/profile.d/debuginfod.* share/man/man8/* share/man/man1/*" +TERMUX_SUBPKG_DEPENDS="libasm, libdw, libdebuginfod" diff --git a/packages/libelf/error.h b/packages/libelf/error.h deleted file mode 100644 index 9f2230b70..000000000 --- a/packages/libelf/error.h +++ /dev/null @@ -1,25 +0,0 @@ -#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/libdebuginfod.subpackage.sh b/packages/libelf/libdebuginfod.subpackage.sh new file mode 100644 index 000000000..f51ef290e --- /dev/null +++ b/packages/libelf/libdebuginfod.subpackage.sh @@ -0,0 +1,2 @@ +TERMUX_SUBPKG_DESCRIPTION="Library for debuginfod" +TERMUX_SUBPKG_INCLUDE="lib/libdebuginfod*.so* include/elfutils/debuginfod.h lib/pkgconfig/libdebuginfod.pc share/man/man3/debuginfod_*" diff --git a/packages/libelf/libdwflP.h.patch b/packages/libelf/libdwflP.h.patch deleted file mode 100644 index 74014ca52..000000000 --- a/packages/libelf/libdwflP.h.patch +++ /dev/null @@ -1,14 +0,0 @@ -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/obstack.h b/packages/libelf/obstack.h index f68d1c9e6..466145d40 100644 --- a/packages/libelf/obstack.h +++ b/packages/libelf/obstack.h @@ -1,6 +1,6 @@ /* obstack.h - object stack macros Copyright (C) 1988-1994,1996-1999,2003,2004,2005,2009,2011,2012 - Free Software Foundation, Inc. + 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 @@ -86,20 +86,19 @@ 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.) + 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 @@ -108,19 +107,21 @@ Summary: #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__ +#define PTR_INT_TYPE __PTRDIFF_TYPE__ #else -# include -# define PTR_INT_TYPE ptrdiff_t +#include +#define PTR_INT_TYPE ptrdiff_t #endif +#include + /* 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. */ @@ -134,58 +135,56 @@ extern "C" { 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) +#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. */ +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 */ + 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 */ +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 - { + 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. */ + } 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. */ + 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); +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) +#define obstack_base(h) ((void *)(h)->object_base) /* Size for allocating ordinary chunks. */ @@ -193,210 +192,221 @@ extern int obstack_exit_failure; /* Pointer to next byte not yet allocated in current chunk. */ -#define obstack_next_free(h) ((h)->next_free) +#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_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_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(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_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_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_freefun(h, newfreefun) \ + ((h)->freefun = (void (*)(void *, struct _obstack_chunk *))(newfreefun)) -#define obstack_1grow_fast(h,achar) (*((h)->next_free)++ = (achar)) +#define obstack_1grow_fast(h, achar) (*((h)->next_free)++ = (achar)) -#define obstack_blank_fast(h,n) ((h)->next_free += (n)) +#define obstack_blank_fast(h, n) ((h)->next_free += (n)) + +#define obstack_memory_used(h) _obstack_memory_used(h) -#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 +#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_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_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_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_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_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_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; }) +#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_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_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_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_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_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_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_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); }) +#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_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); \ + }) -# 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_object_size(h) (unsigned)((h)->next_free - (h)->object_base) -# define obstack_room(h) \ - (unsigned) ((h)->chunk_limit - (h)->next_free) +#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)) +#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 @@ -404,129 +414,129 @@ __extension__ \ 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_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_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_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_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_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_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_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_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_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_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_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_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_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))) +#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; +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); + va_start(ap, fmt); + len = vsnprintf(buf, sizeof(buf), fmt, ap); + obstack_grow(obst, buf, len); + va_end(ap); - return len; + return len; } /* Determine default alignment. */ -union fooround -{ +union fooround { uintmax_t i; long double d; void *p; }; -struct fooalign -{ +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) - }; +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 - +#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'. @@ -534,17 +544,17 @@ enum 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); +static void print_and_abort(void); -# ifdef _LIBC -# if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_3_4) +#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 +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 @@ -552,20 +562,19 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); 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_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)); \ +#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, @@ -573,43 +582,40 @@ compat_symbol (libc, _obstack_compat, _obstack, GLIBC_2_0); 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 *)) -{ +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; - } + /* 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->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 = 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; @@ -617,44 +623,42 @@ static int _obstack_begin (struct obstack *h, return 1; } -static int _obstack_begin_1 (struct obstack *h, int size, int alignment, - void *(*chunkfun) (void *, long), - void (*freefun) (void *, void *), - void *arg) -{ +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; - } + /* 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->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 = 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; @@ -668,8 +672,7 @@ static int _obstack_begin_1 (struct obstack *h, int size, int alignment, 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) -{ +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; @@ -684,31 +687,28 @@ static void _obstack_newchunk (struct obstack *h, int length) new_size = h->chunk_size; /* Allocate and initialize the new chunk. */ - new_chunk = CALL_CHUNKFUN (h, new_size); - if (!new_chunk) print_and_abort(); + 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; + 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); + __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 + 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++) @@ -717,14 +717,12 @@ static void _obstack_newchunk (struct obstack *h, int length) /* 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); - } + 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; @@ -738,57 +736,51 @@ static void _obstack_newchunk (struct obstack *h, int length) /* 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 */ +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 (); + 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; +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; - } + 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); +static void __attribute__((noreturn)) print_and_abort(void) { + fprintf(stderr, "%s\n", "memory exhausted"); + exit(1); } /* END LOCAL ADDITION */ #ifdef __cplusplus -} /* C++ */ +} /* C++ */ #endif #endif /* obstack.h */ diff --git a/packages/libelf/qsort_r.h b/packages/libelf/qsort_r.h index 58c5d97b4..5cc06cd1a 100644 --- a/packages/libelf/qsort_r.h +++ b/packages/libelf/qsort_r.h @@ -1,10 +1,8 @@ -/* https://raw.githubusercontent.com/android/platform_bionic/master/libc/upstream-freebsd/lib/libc/stdlib/qsort.c */ - -#define I_AM_QSORT_R - /*- + * SPDX-License-Identifier: BSD-3-Clause + * * Copyright (c) 1992, 1993 - * The Regents of the University of California. All rights reserved. + * 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 @@ -31,56 +29,41 @@ * SUCH DAMAGE. */ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93"; +#endif /* LIBC_SCCS and not lint */ #include +// __FBSDID("$FreeBSD: head/lib/libc/stdlib/qsort.c 334928 2018-06-10 17:54:44Z +// kib $"); + #include #ifdef I_AM_QSORT_R -typedef int cmp_t(void *, const void *, const void *); +typedef int cmp_t(void *, const void *, const void *); #else -typedef int cmp_t(const void *, const void *); +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); +static inline char *med3(char *, char *, char *, cmp_t *, void *); -#define min(a, b) (a) < (b) ? a : b +#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); \ + +static inline void swapfunc(char *a, char *b, size_t es) { + char t; + + do { + t = *a; + *a++ = *b; + *b++ = t; + } while (--es > 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) +#define vecswap(a, b, n) \ + if ((n) > 0) \ + swapfunc(a, b, n) #ifdef I_AM_QSORT_R #define CMP(t, x, y) (cmp((t), (x), (y))) @@ -88,108 +71,123 @@ swapfunc(a, b, n, swaptype) #define CMP(t, x, y) (cmp((x), (y))) #endif -static inline char * -med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk +static inline char *med3(char *a, char *b, char *c, cmp_t *cmp, + void *thunk #ifndef I_AM_QSORT_R -__unused + __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 )); +) { + 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) +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) +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; + char *pa, *pb, *pc, *pd, *pl, *pm, *pn; + size_t d1, d2; + int cmp_result; + int 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; +loop: + 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) + swapfunc(pl, pl - es, es); + return; + } + pm = (char *)a + (n / 2) * es; + if (n > 7) { + pl = a; + pn = (char *)a + (n - 1) * es; + if (n > 40) { + size_t d = (n / 8) * 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; - } + 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); + } + swapfunc(a, pm, es); + pa = pb = (char *)a + es; - 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) + 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; + swapfunc(pa, pb, es); + pa += es; + } + pb += es; + } + while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) { + if (cmp_result == 0) { + swap_cnt = 1; + swapfunc(pc, pd, es); + pd -= es; + } + pc -= es; + } + if (pb > pc) + break; + swapfunc(pb, pc, es); + 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) + swapfunc(pl, pl - es, es); + return; + } + + pn = (char *)a + n * es; + d1 = MIN(pa - (char *)a, pb - pa); + vecswap(a, pb - d1, d1); + d1 = MIN(pd - pc, pn - pd - es); + vecswap(pb, pn - d1, d1); + + d1 = pb - pa; + d2 = pd - pc; + if (d1 <= d2) { + /* Recurse on left partition, then iterate on right partition */ + if (d1 > es) { #ifdef I_AM_QSORT_R - qsort_r(a, r / es, es, thunk, cmp); + qsort_r(a, d1 / es, es, thunk, cmp); #else - qsort(a, r / es, es, cmp); + qsort(a, d1 / 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);*/ + } + if (d2 > es) { + /* Iterate rather than recurse to save stack space */ + /* qsort(pn - d2, d2 / es, es, cmp); */ + a = pn - d2; + n = d2 / es; + goto loop; + } + } else { + /* Recurse on right partition, then iterate on left partition */ + if (d2 > es) { +#ifdef I_AM_QSORT_R + qsort_r(pn - d2, d2 / es, es, thunk, cmp); +#else + qsort(pn - d2, d2 / es, es, cmp); +#endif + } + if (d1 > es) { + /* Iterate rather than recurse to save stack space */ + /* qsort(a, d1 / es, es, cmp); */ + n = d1 / es; + goto loop; + } + } } - diff --git a/packages/libelf/search/hcreate.c b/packages/libelf/search/hcreate.c new file mode 100644 index 000000000..0f18c117b --- /dev/null +++ b/packages/libelf/search/hcreate.c @@ -0,0 +1,67 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 +//__FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate.c 326193 2017-11-25 17:12:48Z +//pfg $"); + +#include "search.h" +#include +#include + +/* + * Thread unsafe interface: use a single process-wide hash table and + * forward calls to *_r() functions. + */ + +static struct hsearch_data global_hashtable; +static bool global_hashtable_initialized = false; + +int hcreate(size_t nel) { return (1); } + +void hdestroy(void) { + + /* Destroy global hash table if present. */ + if (global_hashtable_initialized) { + hdestroy_r(&global_hashtable); + global_hashtable_initialized = false; + } +} + +ENTRY *hsearch(ENTRY item, ACTION action) { + ENTRY *retval; + + /* Create global hash table if needed. */ + if (!global_hashtable_initialized) { + if (hcreate_r(0, &global_hashtable) == 0) + return (NULL); + global_hashtable_initialized = true; + } + if (hsearch_r(item, action, &retval, &global_hashtable) == 0) + return (NULL); + return (retval); +} diff --git a/packages/libelf/search/hcreate_r.c b/packages/libelf/search/hcreate_r.c new file mode 100644 index 000000000..d6f9a67fa --- /dev/null +++ b/packages/libelf/search/hcreate_r.c @@ -0,0 +1,62 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 +// __FBSDID("$FreeBSD: head/lib/libc/stdlib/hcreate_r.c 292767 2015-12-27 +// 07:50:11Z ed $"); + +#include "search.h" +#include + +#include "hsearch.h" + +int hcreate_r(size_t nel, struct hsearch_data *htab) { + struct __hsearch *hsearch; + + /* + * Allocate a hash table object. Ignore the provided hint and start + * off with a table of sixteen entries. In most cases this hint is + * just a wild guess. Resizing the table dynamically if the use + * increases a threshold does not affect the worst-case running time. + */ + hsearch = malloc(sizeof(*hsearch)); + if (hsearch == NULL) + return 0; + hsearch->entries = calloc(16, sizeof(ENTRY)); + if (hsearch->entries == NULL) { + free(hsearch); + return 0; + } + + /* + * Pick a random initialization for the FNV-1a hashing. This makes it + * hard to come up with a fixed set of keys to force hash collisions. + */ + arc4random_buf(&hsearch->offset_basis, sizeof(hsearch->offset_basis)); + hsearch->index_mask = 0xf; + hsearch->entries_used = 0; + htab->__hsearch = hsearch; + return 1; +} diff --git a/packages/libelf/search/hdestroy_r.c b/packages/libelf/search/hdestroy_r.c new file mode 100644 index 000000000..3d959a74c --- /dev/null +++ b/packages/libelf/search/hdestroy_r.c @@ -0,0 +1,42 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 +// __FBSDID("$FreeBSD: head/lib/libc/stdlib/hdestroy_r.c 292767 2015-12-27 +// 07:50:11Z ed $"); + +#include "search.h" +#include + +#include "hsearch.h" + +void hdestroy_r(struct hsearch_data *htab) { + struct __hsearch *hsearch; + + /* Free hash table object and its entries. */ + hsearch = htab->__hsearch; + free(hsearch->entries); + free(hsearch); +} diff --git a/packages/libelf/search/hsearch.h b/packages/libelf/search/hsearch.h new file mode 100644 index 000000000..c371521ac --- /dev/null +++ b/packages/libelf/search/hsearch.h @@ -0,0 +1,40 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD: head/lib/libc/stdlib/hsearch.h 292767 2015-12-27 07:50:11Z ed $ + */ + +#ifndef HSEARCH_H +#define HSEARCH_H + +#include "search.h" + +struct __hsearch { + size_t offset_basis; /* Initial value for FNV-1a hashing. */ + size_t index_mask; /* Bitmask for indexing the table. */ + size_t entries_used; /* Number of entries currently used. */ + ENTRY *entries; /* Hash table entries. */ +}; + +#endif diff --git a/packages/libelf/search/hsearch_r.c b/packages/libelf/search/hsearch_r.c new file mode 100644 index 000000000..796e9cd26 --- /dev/null +++ b/packages/libelf/search/hsearch_r.c @@ -0,0 +1,144 @@ +/*- + * Copyright (c) 2015 Nuxi, https://nuxi.nl/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (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 +// __FBSDID("$FreeBSD: head/lib/libc/stdlib/hsearch_r.c 292767 2015-12-27 +// 07:50:11Z ed $"); + +#include "search.h" +#include +#include +#include +#include +#include + +#include "hsearch.h" + +/* + * Look up an unused entry in the hash table for a given hash. For this + * implementation we use quadratic probing. Quadratic probing has the + * advantage of preventing primary clustering. + */ +static ENTRY *hsearch_lookup_free(struct __hsearch *hsearch, size_t hash) { + size_t index, i; + + for (index = hash, i = 0;; index += ++i) { + ENTRY *entry = &hsearch->entries[index & hsearch->index_mask]; + if (entry->key == NULL) + return (entry); + } +} + +/* + * Computes an FNV-1a hash of the key. Depending on the pointer size, this + * either uses the 32- or 64-bit FNV prime. + */ +static size_t hsearch_hash(size_t offset_basis, const char *str) { + size_t hash; + + hash = offset_basis; + while (*str != '\0') { + hash ^= (uint8_t)*str++; + if (sizeof(size_t) * CHAR_BIT <= 32) + hash *= UINT32_C(16777619); + else + hash *= UINT64_C(1099511628211); + } + return (hash); +} + +int hsearch_r(ENTRY item, ACTION action, ENTRY **retval, + struct hsearch_data *htab) { + struct __hsearch *hsearch; + ENTRY *entry, *old_entries, *new_entries; + size_t hash, index, i, old_hash, old_count, new_count; + + hsearch = htab->__hsearch; + hash = hsearch_hash(hsearch->offset_basis, item.key); + + /* + * Search the hash table for an existing entry for this key. + * Stop searching if we run into an unused hash table entry. + */ + for (index = hash, i = 0;; index += ++i) { + entry = &hsearch->entries[index & hsearch->index_mask]; + if (entry->key == NULL) + break; + if (strcmp(entry->key, item.key) == 0) { + *retval = entry; + return (1); + } + } + + /* Only perform the insertion if action is set to ENTER. */ + if (action == FIND) { + errno = ESRCH; + return (0); + } + + if (hsearch->entries_used * 2 >= hsearch->index_mask) { + /* Preserve the old hash table entries. */ + old_count = hsearch->index_mask + 1; + old_entries = hsearch->entries; + + /* + * Allocate and install a new table if insertion would + * yield a hash table that is more than 50% used. By + * using 50% as a threshold, a lookup will only take up + * to two steps on average. + */ + new_count = (hsearch->index_mask + 1) * 2; + new_entries = calloc(new_count, sizeof(ENTRY)); + if (new_entries == NULL) + return (0); + hsearch->entries = new_entries; + hsearch->index_mask = new_count - 1; + + /* Copy over the entries from the old table to the new table. */ + for (i = 0; i < old_count; ++i) { + entry = &old_entries[i]; + if (entry->key != NULL) { + old_hash = hsearch_hash(hsearch->offset_basis, entry->key); + *hsearch_lookup_free(hsearch, old_hash) = *entry; + } + } + + /* Destroy the old hash table entries. */ + free(old_entries); + + /* + * Perform a new lookup for a free table entry, so that + * we insert the entry into the new hash table. + */ + hsearch = htab->__hsearch; + entry = hsearch_lookup_free(hsearch, hash); + } + + /* Insert the new entry into the hash table. */ + *entry = item; + ++hsearch->entries_used; + *retval = entry; + return (1); +} diff --git a/packages/libelf/search/search.h b/packages/libelf/search/search.h new file mode 100644 index 000000000..29b5e6fa8 --- /dev/null +++ b/packages/libelf/search/search.h @@ -0,0 +1,225 @@ +/*- + * Written by J.T. Conklin + * Public domain. + * + * $NetBSD: search.h,v 1.12 1999/02/22 10:34:28 christos Exp $ + * $FreeBSD: release/9.0.0/include/search.h 105250 2002-10-16 14:29:23Z robert $ + */ + +#pragma once + +/** + * @file search.h + * @brief Queues, hash tables, trees, and linear array searches. + */ + +#include +#include + +/** See hsearch()/hsearch_r(). */ +typedef enum { FIND, ENTER } ACTION; + +/** See hsearch()/hsearch_r(). */ +typedef struct entry { + /** The string key. */ + char *key; + /** The associated data. */ + void *data; +} ENTRY; + +/** + * Constants given to the twalk() visitor. + * Note that the constant names are misleading. + */ +typedef enum { + /** + * If this is the first visit to a non-leaf node. + * Use this for *preorder* traversal. + */ + preorder, + /** + * If this is the second visit to a non-leaf node. + * Use this for *inorder* traversal. + */ + postorder, + /** + * If this is the third visit to a non-leaf node. + * Use this for *postorder* traversal. + */ + endorder, + /** If this is the first and only visit to a leaf node. */ + leaf +} VISIT; + +#if defined(__USE_BSD) || defined(__USE_GNU) +/** The hash table type for hcreate_r()/hdestroy_r()/hsearch_r(). */ +struct hsearch_data { + struct __hsearch *__hsearch; +}; +#endif + +__BEGIN_DECLS + +/** + * [insque(3)](http://man7.org/linux/man-pages/man3/insque.3.html) inserts + * an item in a queue (an intrusive doubly-linked list). + * + * Available since API level 21. + */ +void insque(void *__element, void *__previous) ; + +/** + * [remque(3)](http://man7.org/linux/man-pages/man3/remque.3.html) removes + * an item from a queue (an intrusive doubly-linked list). + * + * Available since API level 21. + */ +void remque(void *__element) ; + +/** + * [hcreate(3)](http://man7.org/linux/man-pages/man3/hcreate.3.html) + * initializes the global hash table, with space for at least `__n` elements. + * + * See hcreate_r() if you need more than one hash table. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * + * Available since API level 28. + */ +int hcreate(size_t __n) ; + +/** + * [hdestroy(3)](http://man7.org/linux/man-pages/man3/hdestroy.3.html) destroys + * the global hash table. + * + * See hdestroy_r() if you need more than one hash table. + * + * Available since API level 28. + */ +void hdestroy(void) ; + +/** + * [hsearch(3)](http://man7.org/linux/man-pages/man3/hsearch.3.html) finds or + * inserts `__entry` in the global hash table, based on `__action`. + * + * See hsearch_r() if you need more than one hash table. + * + * Returns a pointer to the entry on success, and returns NULL and sets + * `errno` on failure. + * + * Available since API level 28. + */ +ENTRY *hsearch(ENTRY __entry, ACTION __action) ; + +#if defined(__USE_BSD) || defined(__USE_GNU) + +/** + * [hcreate_r(3)](http://man7.org/linux/man-pages/man3/hcreate_r.3.html) + * initializes a hash table `__table` with space for at least `__n` elements. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * + * Available since API level 28. + */ +int hcreate_r(size_t __n, struct hsearch_data *__table) ; + +/** + * [hdestroy_r(3)](http://man7.org/linux/man-pages/man3/hdestroy_r.3.html) + * destroys the hash table `__table`. + * + * Available since API level 28. + */ +void hdestroy_r(struct hsearch_data *__table) ; + +/** + * [hsearch_r(3)](http://man7.org/linux/man-pages/man3/hsearch_r.3.html) finds + * or inserts `__entry` in the hash table `__table`, based on `__action`. + * + * Returns *non-zero* on success and returns 0 and sets `errno` on failure. + * A pointer to the entry is returned in `*__result`. + * + * Available since API level 28. + */ +int hsearch_r(ENTRY __entry, ACTION __action, ENTRY **__result, + struct hsearch_data *__table) ; + +#endif + +/** + * [lfind(3)](http://man7.org/linux/man-pages/man3/lfind.3.html) brute-force + * searches the unsorted array `__array` (of `__count` items each of size + * `__size`) for `__key`, using `__comparator`. + * + * See bsearch() if you have a sorted array. + * + * Returns a pointer to the matching element on success, or NULL on failure. + * + * Available since API level 21. + */ +void *lfind(const void *__key, const void *__array, size_t *__count, + size_t __size, int (*__comparator)(const void *, const void *)) + ; + +/** + * [lsearch(3)](http://man7.org/linux/man-pages/man3/lsearch.3.html) brute-force + * searches the unsorted array `__array` (of `__count` items each of size + * `__size`) for `__key`, using `__comparator`. + * + * Unlike lfind(), on failure lsearch() will *insert* `__key` at the end of + * `__array` and increment `*__count`. + * + * Returns a pointer to the matching element on success, or to the newly-added + * element on failure. + * + * Available since API level 21. + */ +void *lsearch(const void *__key, void *__array, size_t *__count, size_t __size, + int (*__comparator)(const void *, const void *)) + ; + +/** + * [tdelete(3)](http://man7.org/linux/man-pages/man3/tdelete.3.html) searches + * for and removes an element in the tree `*__root_ptr`. The search is performed + * using `__comparator`. + * + * Returns a pointer to the parent of the deleted node, or NULL on failure. + */ +void *tdelete(const void *__key, void **__root_ptr, + int (*__comparator)(const void *, const void *)); + +/** + * [tdestroy(3)](http://man7.org/linux/man-pages/man3/tdestroy.3.html) destroys + * the hash table `__root` using `__free_fn` on each node. + */ +void tdestroy(void *__root, void (*__free_fn)(void *)); + +/** + * [tfind(3)](http://man7.org/linux/man-pages/man3/tfind.3.html) searches + * for an element in the tree `*__root_ptr`. The search is performed using + * `__comparator`. + * + * Returns a pointer to the matching node, or NULL on failure. + */ +void *tfind(const void *__key, void *const *__root_ptr, + int (*__comparator)(const void *, const void *)); + +/** + * [tsearch(3)](http://man7.org/linux/man-pages/man3/tsearch.3.html) searches + * for an element in the tree `*__root_ptr`. The search is performed using + * `__comparator`. + * + * Unlike tfind(), on failure tsearch() will *insert* `__key` into the tree. + * + * Returns a pointer to the matching node, or to the newly-added node. + */ +void *tsearch(const void *__key, void **__root_ptr, + int (*__comparator)(const void *, const void *)); + +/** + * [twalk(3)](http://man7.org/linux/man-pages/man3/twalk.3.html) calls + * `__visitor` on every node in the tree. + */ +void twalk(const void *__root, void (*__visitor)(const void *, VISIT, int)) + ; + +__END_DECLS diff --git a/packages/libelf/src-ar-search.patch b/packages/libelf/src-ar-search.patch new file mode 100644 index 000000000..44d165354 --- /dev/null +++ b/packages/libelf/src-ar-search.patch @@ -0,0 +1,11 @@ +--- elfutils-0.185/src/ar.c 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/src/ar.c 2021-08-29 20:21:23.873999934 +0530 +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include "search/search.h" + #include + #include + #include diff --git a/packages/libelf/src-elflint.patch b/packages/libelf/src-elflint.patch new file mode 100644 index 000000000..96fa9fb11 --- /dev/null +++ b/packages/libelf/src-elflint.patch @@ -0,0 +1,11 @@ +--- elfutils-0.185/src/elflint.c 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/src/elflint.c 2021-08-29 21:49:43.425999943 +0530 +@@ -3434,7 +3434,7 @@ + return p - (const unsigned char *) data->d_buf; + } + +-inline size_t ++static inline size_t + buffer_left (Elf_Data *data, const unsigned char *p) + { + return (const unsigned char *) data->d_buf + data->d_size - p; diff --git a/packages/libelf/src-makefile-search.patch b/packages/libelf/src-makefile-search.patch new file mode 100644 index 000000000..d971074f7 --- /dev/null +++ b/packages/libelf/src-makefile-search.patch @@ -0,0 +1,23 @@ +--- elfutils-0.185/src/Makefile.am 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/src/Makefile.am 2021-08-29 20:44:45.441999945 +0530 +@@ -33,6 +33,11 @@ + + libar_a_SOURCES = arlib.c arlib2.c arlib-argp.c + ++libar_a_SOURCES += search/hcreate.c \ ++ search/hcreate_r.c \ ++ search/hsearch_r.c \ ++ search/hdestroy_r.c ++ + EXTRA_DIST = arlib.h debugpred.h + + bin_SCRIPTS = make-debug-archive +@@ -41,7 +46,7 @@ + + if BUILD_STATIC + libasm = ../libasm/libasm.a +-libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) -ldl -lpthread ++libdw = ../libdw/libdw.a -lz $(zip_LIBS) $(libelf) -ldl + libelf = ../libelf/libelf.a -lz + else + libasm = ../libasm/libasm.so diff --git a/packages/libelf/src-readelf.c.patch b/packages/libelf/src-readelf.c.patch deleted file mode 100644 index 19594c3a0..000000000 --- a/packages/libelf/src-readelf.c.patch +++ /dev/null @@ -1,11 +0,0 @@ -diff -u -r ../elfutils-0.170/src/readelf.c ./src/readelf.c ---- ../elfutils-0.170/src/readelf.c 2017-08-02 14:06:25.000000000 +0200 -+++ ./src/readelf.c 2017-12-10 01:14:25.898858528 +0100 -@@ -43,6 +43,7 @@ - #include - #include - #include -+#include - - #include - #include diff --git a/packages/libelf/src-readelf.patch b/packages/libelf/src-readelf.patch new file mode 100644 index 000000000..83d054cf3 --- /dev/null +++ b/packages/libelf/src-readelf.patch @@ -0,0 +1,26 @@ +--- elfutils-0.185/src/readelf.c 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/src/readelf.c 2021-08-29 13:17:30.120999962 +0530 +@@ -8763,13 +8763,16 @@ + /* Apply the "operation advance" from a special opcode + or DW_LNS_advance_pc (as per DWARF4 6.2.5.1). */ + unsigned int op_addr_advance; +- inline void advance_pc (unsigned int op_advance) +- { +- op_addr_advance = minimum_instr_len * ((op_index + op_advance) +- / max_ops_per_instr); +- address += op_addr_advance; +- op_index = (op_index + op_advance) % max_ops_per_instr; +- } ++ #define advance_pc(op_advance_arg) \ ++ ({ \ ++ unsigned int op_advance = op_advance_arg; \ ++ op_addr_advance = \ ++ minimum_instr_len * ((op_index + (op_advance)) / max_ops_per_instr); \ ++ address += (op_advance); \ ++ op_index = (op_index + (op_advance)) % max_ops_per_instr; \ ++ }) ++ ++ + + if (max_ops_per_instr == 0) + { diff --git a/packages/libelf/stdio_ext.h b/packages/libelf/stdio_ext.h index 114230774..c625c3bc6 100644 --- a/packages/libelf/stdio_ext.h +++ b/packages/libelf/stdio_ext.h @@ -7,41 +7,28 @@ #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 __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 fputs_unlocked(const char *s, FILE *stream) { + return fputs(s, stream); } -static inline int ferror_unlocked(FILE *stream) -{ - return ferror(stream); +static inline int fputc_unlocked(int c, FILE *stream) { + return fputc(c, stream); } -static inline int fputs_unlocked(const char *s, FILE *stream) -{ - return fputs(s, 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 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); +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/system.h.patch b/packages/libelf/system.h.patch new file mode 100644 index 000000000..29289eb42 --- /dev/null +++ b/packages/libelf/system.h.patch @@ -0,0 +1,12 @@ +--- elfutils-0.185/lib/system.h 2021-05-22 23:55:24.000000000 +0530 ++++ elfutils-0.185-patch/lib/system.h 2021-08-29 15:35:57.670999911 +0530 +@@ -39,6 +39,9 @@ + #include + #include + ++extern char* __progname; ++#define program_invocation_short_name __progname ++ + #if __BYTE_ORDER == __LITTLE_ENDIAN + # define LE32(n) (n) + # define LE64(n) (n)