diff --git a/src/common.h b/src/common.h index e41c717..3718b3f 100644 --- a/src/common.h +++ b/src/common.h @@ -71,7 +71,7 @@ __attribute__ ((unused)) allocate_elf (int fildes, void *map_address, int64_t offset, size_t maxsize, Elf_Cmd cmd, Elf *parent, Elf_Kind kind, size_t extra) { - Elf *result = (Elf *) calloc (1, sizeof (Elf) + extra); + Elf *result = calloc (1, sizeof (Elf) + extra); if (result == NULL) __libelf_seterrno (ELF_E_NOMEM); else diff --git a/src/elf32_updatefile.c b/src/elf32_updatefile.c index f67e626..1ff5890 100644 --- a/src/elf32_updatefile.c +++ b/src/elf32_updatefile.c @@ -218,7 +218,7 @@ __elfw2(LIBELFBITS,updatemmap) (Elf *elf, int change_bo, size_t shnum) return 1; Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns; - Elf_Scn **scns = (Elf_Scn **) malloc (shnum * sizeof (Elf_Scn *)); + Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *)); if (unlikely (scns == NULL)) { __libelf_seterrno (ELF_E_NOMEM); @@ -688,7 +688,7 @@ __elfw2(LIBELFBITS,updatefile) (Elf *elf, int change_bo, size_t shnum) /* Get all sections into the array and sort them. */ Elf_ScnList *list = &elf->state.ELFW(elf,LIBELFBITS).scns; - Elf_Scn **scns = (Elf_Scn **) malloc (shnum * sizeof (Elf_Scn *)); + Elf_Scn **scns = malloc (shnum * sizeof (Elf_Scn *)); if (unlikely (scns == NULL)) { free (shdr_data_mem); diff --git a/src/elf_begin.c b/src/elf_begin.c index 32648c1..93d1e12 100644 --- a/src/elf_begin.c +++ b/src/elf_begin.c @@ -774,7 +774,7 @@ read_long_names (Elf *elf) /* Due to the stupid format of the long name table entry (which are not NUL terminted) we have to provide an appropriate representation anyhow. Therefore we always make a copy which has the appropriate form. */ - newp = (char *) malloc (len); + newp = malloc (len); if (newp != NULL) { char *runp; diff --git a/src/elf_getarsym.c b/src/elf_getarsym.c index 1f031fc..05ebf6a 100644 --- a/src/elf_getarsym.c +++ b/src/elf_getarsym.c @@ -198,7 +198,7 @@ elf_getarsym (Elf *elf, size_t *ptr) /* Now we can allocate the arrays needed to store the index. */ size_t ar_sym_len = (n + 1) * sizeof (Elf_Arsym); - elf->state.ar.ar_sym = (Elf_Arsym *) malloc (ar_sym_len); + elf->state.ar.ar_sym = malloc (ar_sym_len); if (elf->state.ar.ar_sym != NULL) { void *file_data; /* unit32_t[n] or uint64_t[n] */ @@ -216,8 +216,7 @@ elf_getarsym (Elf *elf, size_t *ptr) file_data = temp_data; ar_sym_len += index_size - n * w; - Elf_Arsym *newp = (Elf_Arsym *) realloc (elf->state.ar.ar_sym, - ar_sym_len); + Elf_Arsym *newp = realloc (elf->state.ar.ar_sym, ar_sym_len); if (newp == NULL) { free (elf->state.ar.ar_sym); diff --git a/src/elf_getdata.c b/src/elf_getdata.c index 6ed4450..475c6de 100644 --- a/src/elf_getdata.c +++ b/src/elf_getdata.c @@ -146,7 +146,7 @@ convert_data (Elf_Scn *scn, int eclass, scn->data_base = scn->rawdata_base; else { - scn->data_base = (char *) malloc (size); + scn->data_base = malloc (size); if (scn->data_base == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -161,7 +161,7 @@ convert_data (Elf_Scn *scn, int eclass, { xfct_t fp; - scn->data_base = (char *) malloc (size); + scn->data_base = malloc (size); if (scn->data_base == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -175,7 +175,7 @@ convert_data (Elf_Scn *scn, int eclass, rawdata_source = scn->rawdata_base; else { - rawdata_source = (char *) malloc (size); + rawdata_source = malloc (size); if (rawdata_source == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -328,8 +328,7 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn) /* We have to read the data from the file. Allocate the needed memory. */ - scn->rawdata_base = scn->rawdata.d.d_buf - = (char *) malloc (size); + scn->rawdata_base = scn->rawdata.d.d_buf = malloc (size); if (scn->rawdata.d.d_buf == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -384,7 +383,18 @@ __libelf_set_rawdata_wrlock (Elf_Scn *scn) which should be uncommon. */ align = align ?: 1; if (type != SHT_NOBITS && align > offset) - align = offset; + { + /* Align the offset to the next power of two. Uses algorithm from + https://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 */ + align = offset - 1; + align |= align >> 1; + align |= align >> 2; + align |= align >> 4; + align |= align >> 8; + align |= align >> 16; + align |= align >> 32; + align++; + } scn->rawdata.d.d_align = align; if (elf->class == ELFCLASS32 || (offsetof (struct Elf, state.elf32.ehdr) diff --git a/src/elf_getscn.c b/src/elf_getscn.c index e1fbaaa..be9c76f 100644 --- a/src/elf_getscn.c +++ b/src/elf_getscn.c @@ -68,7 +68,7 @@ elf_getscn (Elf *elf, size_t idx) Elf_Scn *scn0 = &runp->data[0]; if (elf->class == ELFCLASS32) { - scn0->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr)); + scn0->shdr.e32 = calloc (1, sizeof (Elf32_Shdr)); if (scn0->shdr.e32 == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -77,7 +77,7 @@ elf_getscn (Elf *elf, size_t idx) } else { - scn0->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr)); + scn0->shdr.e64 = calloc (1, sizeof (Elf64_Shdr)); if (scn0->shdr.e64 == NULL) { __libelf_seterrno (ELF_E_NOMEM); diff --git a/src/elf_newdata.c b/src/elf_newdata.c index 896f22c..0063d59 100644 --- a/src/elf_newdata.c +++ b/src/elf_newdata.c @@ -106,7 +106,7 @@ elf_newdata (Elf_Scn *scn) } /* Create a new, empty data descriptor. */ - result = (Elf_Data_List *) calloc (1, sizeof (Elf_Data_List)); + result = calloc (1, sizeof (Elf_Data_List)); if (result == NULL) { __libelf_seterrno (ELF_E_NOMEM); diff --git a/src/elf_newscn.c b/src/elf_newscn.c index d15a642..d6bdf15 100644 --- a/src/elf_newscn.c +++ b/src/elf_newscn.c @@ -94,9 +94,9 @@ elf_newscn (Elf *elf) 1 #endif ) - newp = (Elf_ScnList *) calloc (sizeof (Elf_ScnList) - + ((elf->state.elf.scnincr *= 2) - * sizeof (Elf_Scn)), 1); + newp = calloc (sizeof (Elf_ScnList) + + ((elf->state.elf.scnincr *= 2) + * sizeof (Elf_Scn)), 1); if (newp == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -122,7 +122,7 @@ elf_newscn (Elf *elf) /* Create a section header for this section. */ if (elf->class == ELFCLASS32) { - result->shdr.e32 = (Elf32_Shdr *) calloc (1, sizeof (Elf32_Shdr)); + result->shdr.e32 = calloc (1, sizeof (Elf32_Shdr)); if (result->shdr.e32 == NULL) { __libelf_seterrno (ELF_E_NOMEM); @@ -131,7 +131,7 @@ elf_newscn (Elf *elf) } else { - result->shdr.e64 = (Elf64_Shdr *) calloc (1, sizeof (Elf64_Shdr)); + result->shdr.e64 = calloc (1, sizeof (Elf64_Shdr)); if (result->shdr.e64 == NULL) { __libelf_seterrno (ELF_E_NOMEM); diff --git a/src/elf_readall.c b/src/elf_readall.c index 384d251..0a3a233 100644 --- a/src/elf_readall.c +++ b/src/elf_readall.c @@ -107,7 +107,7 @@ __libelf_readall (Elf *elf) } /* Allocate all the memory we need. */ - mem = (char *) malloc (elf->maximum_size); + mem = malloc (elf->maximum_size); if (mem != NULL) { /* Read the file content. */ diff --git a/src/elf_strptr.c b/src/elf_strptr.c index 76f2caf..79a24d2 100644 --- a/src/elf_strptr.c +++ b/src/elf_strptr.c @@ -56,7 +56,9 @@ get_zdata (Elf_Scn *strscn) static bool validate_str (const char *str, size_t from, size_t to) { #if HAVE_DECL_MEMRCHR - return memrchr (&str[from], '\0', to - from) != NULL; + // Check end first, which is likely a zero terminator, to prevent function call + return ((to > 0 && str[to - 1] == '\0') + || (to - from > 0 && memrchr (&str[from], '\0', to - from - 1) != NULL)); #else do { if (to <= from) diff --git a/src/eu-config.h b/src/eu-config.h index f0e3d07..c7d7cbb 100644 --- a/src/eu-config.h +++ b/src/eu-config.h @@ -176,27 +176,68 @@ asm (".section predict_data, \"aw\"; .previous\n" /* This macro is used by the tests conditionalize for standalone building. */ #define ELFUTILS_HEADER(name) +/* Don't reorder with global asm blocks or optimize away. (Doesn't reliably + keep it in the same LTO partition, though; -flto-partition=none may be + still needed for some gcc versions < 10.) */ +#ifdef __has_attribute +# if __has_attribute(no_reorder) +# define used_in_asm __attribute__ ((externally_visible, no_reorder)) +# endif +#endif +#ifndef used_in_asm +# define used_in_asm /* empty */ +#endif #ifdef SYMBOL_VERSIONING -# define OLD_VERSION(name, version) \ - asm (".globl _compat." #version "." #name "\n" \ - "_compat." #version "." #name " = " #name "\n" \ - ".symver _compat." #version "." #name "," #name "@" #version); -# define NEW_VERSION(name, version) \ - asm (".symver " #name "," #name "@@@" #version); -# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ - asm (".symver _compat." #version "." #name "," #name "@" #version); \ +# define NEW_INTDEF(name) __typeof (name) INTUSE(name) \ + __attribute__ ((alias ("_new." #name))) attribute_hidden; +# ifdef __has_attribute +# if __has_attribute(symver) +# define NEW_VERSION(name, version) \ + __typeof (name) name __asm__ ("_new." #name) \ + __attribute__ ((symver (#name "@@" #version))); +# define OLD_VERSION(name, version) _OLD_VERSION1(name, __COUNTER__, version) +# define _OLD_VERSION1(name, num, version) _OLD_VERSION2(name, num, version) +# define _OLD_VERSION2(name, num, version) \ + __typeof (name) _compat_old##num##_##name \ + __asm__ ("_compat." #version "." #name) \ + __attribute__ ((alias ("_new." #name), symver (#name "@" #version))); +# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ __typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \ - asm ("_compat." #version "." #name); -# define COMPAT_VERSION(name, version, prefix) \ + __asm__ ("_compat." #version "." #name) \ + __attribute__ ((symver (#name "@" #version))); +# define COMPAT_VERSION(name, version, prefix) \ asm (".symver _compat." #version "." #name "," #name "@" #version); \ - __typeof (name) _compat_##prefix##_##name asm ("_compat." #version "." #name); + __typeof (name) _compat_##prefix##_##name \ + __asm__ ("_compat." #version "." #name) \ + __attribute__ ((symver (#name "@" #version))); +# endif +# endif +# ifndef NEW_VERSION +# define OLD_VERSION(name, version) \ + asm (".globl _compat." #version "." #name "\n\t" \ + "_compat." #version "." #name " = _new." #name "\n\t" \ + ".symver _compat." #version "." #name "," #name "@" #version); +# define NEW_VERSION(name, version) \ + __typeof (name) name __asm__ ("_new." #name) used_in_asm; \ + asm (".symver _new." #name ", " #name "@@" #version); +# define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ + __typeof (_compat_##prefix##_##name) _compat_##prefix##_##name \ + __asm__ ("_compat." #version "." #name) used_in_asm; \ + asm (".symver _compat." #version "." #name ", " #name "@" #version); +# define COMPAT_VERSION(name, version, prefix) \ + __typeof (name) _compat_##prefix##_##name \ + __asm__ ("_compat." #version "." #name) used_in_asm; \ + asm (".symver _compat." #version "." #name ", " #name "@" #version); +# endif #else +# define NEW_INTDEF(name) INTDEF(name) # define OLD_VERSION(name, version) /* Nothing for static linking. */ # define NEW_VERSION(name, version) /* Nothing for static linking. */ # define COMPAT_VERSION_NEWPROTO(name, version, prefix) \ error "should use #ifdef SYMBOL_VERSIONING" -# define COMPAT_VERSION(name, version, prefix) error "should use #ifdef SYMBOL_VERSIONING" +# define COMPAT_VERSION(name, version, prefix) \ + error "should use #ifdef SYMBOL_VERSIONING" #endif #ifndef FALLTHROUGH diff --git a/src/fixedsizehash.h b/src/fixedsizehash.h index dac2a5f..14f0fb8 100644 --- a/src/fixedsizehash.h +++ b/src/fixedsizehash.h @@ -30,17 +30,11 @@ #include #include #include -#include #include -#ifdef __CONCAT -#define CONCAT(t1,t2) __CONCAT (t1,t2) -#else -#define STROF(t2) t2 #define CONCAT_EXPANDED(t1,t2) t1 ## t2 #define CONCAT(t1,t2) CONCAT_EXPANDED(t1,t2) -#endif /* Before including this file the following macros must be defined: diff --git a/src/system.h b/src/system.h index cdf18ed..edbc848 100644 --- a/src/system.h +++ b/src/system.h @@ -29,8 +29,9 @@ #ifndef LIB_SYSTEM_H #define LIB_SYSTEM_H 1 +#include + #include -#include #include #include #include @@ -38,6 +39,17 @@ #include #include #include +#include +#include + +#if defined(HAVE_ERROR_H) +#include +#elif defined(HAVE_ERR_H) +extern int error_message_count; +void error(int status, int errnum, const char *format, ...); +#else +#error "err.h or error.h must be available" +#endif #if __BYTE_ORDER == __LITTLE_ENDIAN # define LE32(n) (n) @@ -70,6 +82,19 @@ ((void *) ((char *) memcpy (dest, src, n) + (size_t) n)) #endif +#if !HAVE_DECL_REALLOCARRAY +static inline void * +reallocarray (void *ptr, size_t nmemb, size_t size) +{ + if (size > 0 && nmemb > SIZE_MAX / size) + { + errno = ENOMEM; + return NULL; + } + return realloc (ptr, nmemb * size); +} +#endif + /* Return TRUE if the start of STR matches PREFIX, FALSE otherwise. */ static inline int