diff options
34 files changed, 1028 insertions, 617 deletions
| @@ -1,6 +1,6 @@  ISC License -© 2023 Mattias Andrée <maandree@kth.se> +© 2023 Mattias Andrée <m@maandree.se>  Permission to use, copy, modify, and/or distribute this software for any  purpose with or without fee is hereby granted, provided that the above @@ -106,6 +106,7 @@ OBJ =\  	libsyscalls_get_syscall_display_info.o\  	libsyscalls_get_syscall_errors.o\  	libsyscalls_get_syscall_range.o\ +	libsyscalls_find_named_number.o\  	libsyscalls_make_signed_integer.o\  	libsyscalls_parse_signed_integer.o\  	libsyscalls_perror.o\ @@ -151,6 +152,7 @@ TESTUTILS =\  	testutil/section-value.tu\  	testutil/strerror-all.tu\  	testutil/strerror-bad.tu\ +	testutil/test-search.tu\  	testutil/to-tracee-endian.tu\  	testutil/to-tracer-endian.tu\  	testutil/unsection-value.tu @@ -57,12 +57,16 @@  #define COMMA , -#define MISALIGNMENT(ADDR, ALIGN) (((ADDR) - ((ADDR) % (uintptr_t)(ALIGN))) % (uintptr_t)(ALIGN)) -#define ALIGN_BUF(BUF, ALIGN) (&(BUF)[(size_t)MISALIGNMENT((uintptr_t)(char *)(BUF), (ALIGN))]) +#define MISALIGNMENT(ADDR, ALIGN) ((ADDR) & ((uintptr_t)(ALIGN) - 1U)) +#define ALIGNMENT_ADJUSTMENT(ADDR, ALIGN) MISALIGNMENT((ALIGN) - MISALIGNMENT((ADDR), (ALIGN)), (ALIGN)) +#define ALIGN_BUF(BUF, ALIGN) (&(BUF)[(size_t)ALIGNMENT_ADJUSTMENT((uintptr_t)(char *)(BUF), (ALIGN))])  #define ELEMSOF(ARR) (sizeof(ARR) / sizeof *(ARR))  #define MAX(A, B) ((A) > (B) ? (A) : (B))  #define LOWEST_BIT(X) ((X) & ~((X) - 1)) -#define POST_HIGHEST_OF_CONSECUTIVELY_BITS(X) ((X) + LOWEST_BIT(X)) +#define POST_HIGHEST_OF_CONSECUTIVELY_BITS(X) ((X) + LOWEST_BIT((X))) +#define IS_NOT_2POW(X) ((X) & ((X) - 1)) +#define SET_MASK_TRAIL(X) ((X) | ((X) - 1U)) +#define USAT_MINUS(A, B) ((A) < (B) ? 0 : (A) - (B))  struct libsyscalls_symbol_printer_data { @@ -76,54 +80,54 @@ enum endian {  	Little  }; - -/* Don't forget to update SUPPORTED_ARCHES in Makefile */ -#define LIST_ARCH_SPECS(X, D) /*             byte  intptr  size_t  endian    sign  */\ -	X(LIBSYSCALLS_ARCH_ALPHA_LE,         8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_ALPHA_BE,         8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_AMD64,            8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_AMD64_X32,        8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ +                              /*             [------ size ------]  [align]                 */ +#define LIST_ARCH_SPECS(X, D) /*             byte  intptr  size_t  intmax  endian    sign  */\ +	X(LIBSYSCALLS_ARCH_ALPHA_LE,         8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_ALPHA_BE,         8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_AMD64,            8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_AMD64_X32,        8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\  	/* -	X(LIBSYSCALLS_ARCH_ARM_OABI_LE,      8,    TODO,   TODO,   Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_ARM_OABI_BE,      8,    TODO,   TODO,   Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_ARM_EABI_LE,      8,    TODO,   TODO,   Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_ARM_EABI_BE,      8,    TODO,   TODO,   Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_ARM_OABI_LE,      8,    TODO,   TODO,   32,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_ARM_OABI_BE,      8,    TODO,   TODO,   32,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_ARM_EABI_LE,      8,    TODO,   TODO,   64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_ARM_EABI_BE,      8,    TODO,   TODO,   64,     Big,      TWOS_COMPLEMENT) D\  	*/\ -	X(LIBSYSCALLS_ARCH_IA64_LE,          8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_IA64_BE,          8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_IA64_P32_LE,      8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_IA64_P32_BE,      8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_M68K,             8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_LE, 8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_BE, 8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_LE, 8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_BE, 8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_O32_LE,      8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_O32_BE,      8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_N32_LE,      8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_N32_BE,      8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_N64_LE,      8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_MIPS_N64_BE,      8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_PARISC_32,        8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_PARISC_64,        8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_32_LE,    8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_32_BE,    8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_64_LE,    8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_64_BE,    8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE, 8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE, 8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_SPU_LE,   8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_POWERPC_SPU_BE,   8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_S390_32,          8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_S390_64,          8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_SH_LE,            8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_SH_BE,            8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_SPARC_32,         8,    32,     32,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_SPARC_64_LE,      8,    64,     64,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_SPARC_64_BE,      8,    64,     64,     Big,      TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_I386,             8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_XTENSA_LE,        8,    32,     32,     Little,   TWOS_COMPLEMENT) D\ -	X(LIBSYSCALLS_ARCH_XTENSA_BE,        8,    32,     32,     Big,      TWOS_COMPLEMENT) +	X(LIBSYSCALLS_ARCH_IA64_LE,          8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_IA64_BE,          8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_IA64_P32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_IA64_P32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_M68K,             8,    32,     32,     16,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_LE, 8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MICROBLAZE_32_BE, 8,    32,     32,     32,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_LE, 8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MICROBLAZE_64_BE, 8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_O32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_O32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_N32_LE,      8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_N32_BE,      8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_N64_LE,      8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_MIPS_N64_BE,      8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_PARISC_32,        8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_PARISC_64,        8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_32_LE,    8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_32_BE,    8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_64_LE,    8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_64_BE,    8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE, 8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE, 8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_SPU_LE,   8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_POWERPC_SPU_BE,   8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_S390_32,          8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_S390_64,          8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_SH_LE,            8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_SH_BE,            8,    32,     32,     32,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_SPARC_32,         8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_SPARC_64_LE,      8,    64,     64,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_SPARC_64_BE,      8,    64,     64,     64,     Big,      TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_I386,             8,    32,     32,     32,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_XTENSA_LE,        8,    32,     32,     64,     Little,   TWOS_COMPLEMENT) D\ +	X(LIBSYSCALLS_ARCH_XTENSA_BE,        8,    32,     32,     64,     Big,      TWOS_COMPLEMENT) +	/* Don't forget to update SUPPORTED_ARCHES in Makefile */  #include "generated/oses.h" @@ -23,6 +23,19 @@ LDFLAGS  =  # which returns the index, plus 1, of the least significant set bit  # or 0 for 0, you can add -DHAVE_BUILTIN_FFSLL to CPPFLAGS; if you  # are using GCC>=3.4 or clang>=5, this is added automatically. +# Additionally, you can add -DUSE_INTERPOLATION_SEARCH to CPPFLAGS +# if you want the library to use interpolation search instead of +# binary search, this is probably a bad idea on platforms that do +# not support division natively, even on amd64, it does not seem to +# make any difference at the moment. If you add -DUSE_INTERPOLATION_SEARCH, +# you may also add `-DINTERPOLATION_SEARCH_FLOAT=long double` (default), +# `-DINTERPOLATION_SEARCH_FLOAT=double` or `-DINTERPOLATION_SEARCH_FLOAT=float` +# to specify which floating point type interpolation search should use +# if it cannot used integers; which option is best depends on the +# platform, as some platforms can work natively with any of the types +# and those `float` is most performant, and other platforms (such as +# i386) can only work natively with a specific type (`long double` in +# the case of i386) and thus performs best with that type.  DOWNLOAD = curl -- diff --git a/libsyscalls.h b/libsyscalls.h index f2d5fdd..df4de69 100644 --- a/libsyscalls.h +++ b/libsyscalls.h @@ -16,7 +16,7 @@   *                             the enum value name of the error (identifier),   *                             and the description of the error (string literal)   * @param  D:code              Macro that expands between each expansion of X - * + *    * The primary purpose of the existance of this macro   * is to ease implementation of the library; it will   * probably not disappear (no promises) @@ -119,28 +119,34 @@ enum libsyscalls_datatype {  	/* You can use these macros classify and convert data types */  #define LIBSYSCALLS_TYPEBITSMASK                0xF000  #define LIBSYSCALLS_TYPEBITS_SCALAR             0x0000 /* predefined total width, even if aggregate */ -#define LIBSYSCALLS_TYPEBITS_ARRAY              0x1000 /* count is stored in next parameter, and is updated with fill -                                                        * or returned if no outputable to the next parameter */ -#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is in no way returned, -                                                        * this chould either be because the array is always (unless an -                                                        * error is returned) entirely filled or because the end is -                                                        * infered from the contents (e.g. null byte termination) */ +#define LIBSYSCALLS_TYPEBITS_ARRAY              0x1000 /* count is stored in next parameter, and is +                                                        * updated with fill or returned if no outputable +                                                        * to the next parameter */ +#define LIBSYSCALLS_TYPEBITS_ARRAY_UNKNOWN_FILL 0x2000 /* count is stored in next parameter, fill is +                                                        * in no way returned, this chould either be +                                                        * because the array is always (unless an error +                                                        * is returned) entirely filled or because the +                                                        * end is inferred from the contents (e.g. null +                                                        * byte termination) */  #define LIBSYSCALLS_LIST_SPECIAL_TYPES(X, SUFFIX, D, FIRST)\ -	/* the type used in the system call has not yet be added recorded in the library */\ +	/* the type used in the system call has not yet be +	 * added recorded in the library */\  	X(LIBSYSCALLS_TYPE_UNKNOWN ## SUFFIX, FIRST, "(unknown type)") D\  	/* the type depends on the system call input or output */\  	X(LIBSYSCALLS_TYPE_DYNAMIC ## SUFFIX,, "(undetermined type)") D\ -	/* the system call should never returned to the calling process (return to tracer is usually expected) */\ +	/* the system call should never returned to the calling +	 * process (return to tracer is usually expected) */\  	X(LIBSYSCALLS_TYPE_NO_RETURN ## SUFFIX,, "no_return") D\ -	/* either used as return type, to skip a register in the parameters -	 * (do not dismiss this, on some architectures a system call -	 * may need padding with dummy arguments to align latter -	 * register pairs; an application printing the system call -	 * must choose between omitting, printing the argument, or -	 * indicating that there is a dummy parameter (of course -	 * the latter two can be combined)), or to add padding -	 * (or reserved space for future expansion) to a struct */\ +	/* either used as return type, to skip a register in the +	 * parameters (do not dismiss this, on some architectures +	 * a system call may need padding with dummy arguments to +	 * align latter register pairs; an application printing +	 * the system call must choose between omitting, printing +	 * the argument, or indicating that there is a dummy +	 * parameter (of course the latter two can be combined)), +	 * or to add padding (or reserved space for future +	 * expansion) to a struct */\  	X(LIBSYSCALLS_TYPE_VOID ## SUFFIX,, "void")  #define LIBSYSCALLS_LIST_SPLIT_PRIMITIVES(X, SUFFIX, D, FIRST)\ @@ -332,17 +338,17 @@ enum libsyscalls_syscall_category {  	 */  	LIBSYSCALLS_CAT_NOT_IMPLEMENTED, -	LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC,  /**< See enum libsyscalls_network_enabled_ipc_syscall_subcategory */ -	LIBSYSCALLS_CAT_IPC,                  /**< See enum libsyscalls_ipc_syscall_subcategory */ -	LIBSYSCALLS_CAT_FILESYSTEM,           /**< See enum libsyscalls_filesystem_syscall_subcategory */ -	LIBSYSCALLS_CAT_FILE_DESCRIPTORS,     /**< See enum libsyscalls_file_descriptors_syscall_subcategory */ -	LIBSYSCALLS_CAT_PROCESSES,            /**< See enum libsyscalls_processes_syscall_subcategory */ -	LIBSYSCALLS_CAT_LOGGING,              /**< See enum libsyscalls_logging_syscall_subcategory */ -	LIBSYSCALLS_CAT_TIME,                 /**< See enum libsyscalls_time_syscall_subcategory */ -	LIBSYSCALLS_CAT_SIGNALS,              /**< See enum libsyscalls_singals_syscall_subcategory */ -	LIBSYSCALLS_CAT_MEMORY,               /**< See enum libsyscalls_memory_syscall_subcategory */ -	LIBSYSCALLS_CAT_SYSTEM,               /**< See enum libsyscalls_system_syscall_subcategory */ -	LIBSYSCALLS_CAT_SCHEDULING            /**< See enum libsyscalls_scheduling_syscall_subcategory */ +	LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC, /**< See enum libsyscalls_network_enabled_ipc_syscall_subcategory */ +	LIBSYSCALLS_CAT_IPC,                 /**< See enum libsyscalls_ipc_syscall_subcategory */ +	LIBSYSCALLS_CAT_FILESYSTEM,          /**< See enum libsyscalls_filesystem_syscall_subcategory */ +	LIBSYSCALLS_CAT_FILE_DESCRIPTORS,    /**< See enum libsyscalls_file_descriptors_syscall_subcategory */ +	LIBSYSCALLS_CAT_PROCESSES,           /**< See enum libsyscalls_processes_syscall_subcategory */ +	LIBSYSCALLS_CAT_LOGGING,             /**< See enum libsyscalls_logging_syscall_subcategory */ +	LIBSYSCALLS_CAT_TIME,                /**< See enum libsyscalls_time_syscall_subcategory */ +	LIBSYSCALLS_CAT_SIGNALS,             /**< See enum libsyscalls_singals_syscall_subcategory */ +	LIBSYSCALLS_CAT_MEMORY,              /**< See enum libsyscalls_memory_syscall_subcategory */ +	LIBSYSCALLS_CAT_SYSTEM,              /**< See enum libsyscalls_system_syscall_subcategory */ +	LIBSYSCALLS_CAT_SCHEDULING           /**< See enum libsyscalls_scheduling_syscall_subcategory */  };  /** @@ -1473,17 +1479,17 @@ enum libsyscalls_scheduling_syscall_subcategory {   * LIBSYSCALLS_CAT_SUPPORT_PENDING or LIBSYSCALLS_CAT_NOT_IMPLEMENTED   */  union libsyscalls_syscall_subcategory { -	enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc; /**< Use for LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC */ -	enum_libsyscalls_ipc_syscall_subcategory ipc;                                 /**< Use for LIBSYSCALLS_CAT_IPC */ -	enum_libsyscalls_filesystem_syscall_subcategory filesystem;                   /**< Use for LIBSYSCALLS_CAT_FILESYSTEM */ -	enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors;       /**< Use for LIBSYSCALLS_CAT_FILE_DESCRIPTORS */ -	enum_libsyscalls_processes_syscall_subcategory processes;                     /**< Use for LIBSYSCALLS_CAT_PROCESSES */ -	enum_libsyscalls_logging_syscall_subcategory logging;                         /**< Use for LIBSYSCALLS_CAT_LOGGING */ -	enum_libsyscalls_time_syscall_subcategory time;                               /**< Use for LIBSYSCALLS_CAT_TIME */ -	enum_libsyscalls_signals_syscall_subcategory signals;                         /**< Use for LIBSYSCALLS_CAT_SIGNALS */ -	enum_libsyscalls_memory_syscall_subcategory memory;                           /**< Use for LIBSYSCALLS_CAT_MEMORY */ -	enum_libsyscalls_system_syscall_subcategory system;                           /**< Use for LIBSYSCALLS_CAT_SYSTEM */ -	enum_libsyscalls_scheduling_syscall_subcategory scheduling;                   /**< Use for LIBSYSCALLS_CAT_SCHEDULING */ +	enum_libsyscalls_network_enabled_ipc_syscall_subcategory network_enabled_ipc; /**< If LIBSYSCALLS_CAT_NETWORK_ENABLED_IPC */ +	enum_libsyscalls_ipc_syscall_subcategory ipc;                                 /**< If LIBSYSCALLS_CAT_IPC */ +	enum_libsyscalls_filesystem_syscall_subcategory filesystem;                   /**< If LIBSYSCALLS_CAT_FILESYSTEM */ +	enum_libsyscalls_file_descriptors_syscall_subcategory file_descriptors;       /**< If LIBSYSCALLS_CAT_FILE_DESCRIPTORS */ +	enum_libsyscalls_processes_syscall_subcategory processes;                     /**< If LIBSYSCALLS_CAT_PROCESSES */ +	enum_libsyscalls_logging_syscall_subcategory logging;                         /**< If LIBSYSCALLS_CAT_LOGGING */ +	enum_libsyscalls_time_syscall_subcategory time;                               /**< If LIBSYSCALLS_CAT_TIME */ +	enum_libsyscalls_signals_syscall_subcategory signals;                         /**< If LIBSYSCALLS_CAT_SIGNALS */ +	enum_libsyscalls_memory_syscall_subcategory memory;                           /**< If LIBSYSCALLS_CAT_MEMORY */ +	enum_libsyscalls_system_syscall_subcategory system;                           /**< If LIBSYSCALLS_CAT_SYSTEM */ +	enum_libsyscalls_scheduling_syscall_subcategory scheduling;                   /**< If LIBSYSCALLS_CAT_SCHEDULING */  };  /** @@ -1567,7 +1573,8 @@ struct libsyscalls_syscall_abi {  	 */  	unsigned short int queer : 1; -	short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT, 4*16 + 2*6 + 3*1); +	short int : LIBSYSCALLS_PAD_(sizeof(short int)/sizeof(char)*CHAR_BIT, +	                             4*16 + 2*6 + 3*1);  	/**  	 * This is used internally by `libsyscalls_get_syscall_display_info` @@ -1714,7 +1721,9 @@ struct libsyscalls_named_number {   *                       none was found. The returned string may be stored   *                       in `data` and those override at the next call.   */ -typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *, unsigned long long int *, char *); +typedef const char *libsyscalls_symbol_printer_function(LIBSYSCALLS_SYMBOL_PRINTER_DATA *data, +                                                        unsigned long long int *valuep, +                                                        char *fallback_out);  /**   * Information about a system call parameter or return value @@ -1739,7 +1748,8 @@ struct libsyscalls_syscall_type_info {  	 */  	enum_libsyscalls_datatype type; -	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), sizeof(enum_libsyscalls_datatype)/sizeof(char) + 1)]; +	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), +	                                sizeof(enum_libsyscalls_datatype)/sizeof(char) + 1)];  	unsigned char : CHAR_BIT - 1;  	/** @@ -1792,8 +1802,8 @@ struct libsyscalls_syscall_display_info {   */  enum libsyscalls_datatype_sign_representation {  	/** -	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN or -	 * LIBSYSCALLS_TYPE_DYNAMIC +	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN +	 * or LIBSYSCALLS_TYPE_DYNAMIC  	 */  	LIBSYSCALLS_SIGN_UNDETERMINED, @@ -1844,43 +1854,45 @@ enum libsyscalls_datatype_annotation {  	LIBSYSCALLS_ANNOTATION_NONE,  	/** -	 * The value represents an operating system signal (e.g. SIGKILL) +	 * The value represents an operating system signal +	 * (e.g. SIGKILL)  	 *  -	 * This affords the application the opportunity to print -	 * more detail information about a signal (such as when -	 * it is used, whether it is a realtime signal, default -	 * action, whether it can be caught, and what its normal -	 * usage is) +	 * This affords the application the opportunity +	 * to print more detail information about a signal +	 * (such as when it is used, whether it is a +	 * realtime signal, default action, whether it +	 * can be caught, and what its normal usage is)  	 */  	LIBSYSCALLS_ANNOTATION_SIGNAL,  	/**  	 * The value represents a file descriptor  	 *  -	 * This affords the application the opportunity to print -	 * file information (such as file name, address, file type, -	 * and offset) +	 * This affords the application the opportunity +	 * toprint file information (such as file name, +	 * address, file type, and offset)  	 */  	LIBSYSCALLS_ANNOTATION_FD,  	/** -	 * The value represents a file descriptor or a special value -	 * for a known file such as AT_FDCWD +	 * The value represents a file descriptor or a +	 * special value for a known file such as AT_FDCWD  	 *  -	 * This affords the application the opportunity to print -	 * file information (such as file name, address, file type, -	 * and offset) +	 * This affords the application the opportunity +	 * to print file information (such as file name, +	 * address, file type, and offset)  	 */  	LIBSYSCALLS_ANNOTATION_ATFD  };  /** - * Register-split/struct field-split information for a data type + * Register-split/struct field-split information + * for a data type   */  enum libsyscalls_datatype_section {  	/** -	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN or -	 * LIBSYSCALLS_TYPE_DYNAMIC +	 * The data type was LIBSYSCALLS_TYPE_UNKNOWN +	 * or LIBSYSCALLS_TYPE_DYNAMIC  	 */  	LIBSYSCALLS_SECTION_UNDETERMINED, @@ -1891,12 +1903,15 @@ enum libsyscalls_datatype_section {  	 */  	LIBSYSCALLS_SECTION_WHOLE, -	/* +	/**  	 * This whether a data type represents a half section  	 * of larger data type  	 *  -	 * @param   S:enum libsyscalls_datatype_section  The data type section information -	 * @return  :int                                 Whether the larger that type was split into two halves +	 * @param   S:enum libsyscalls_datatype_section +	 *                  The data type section information +	 *  +	 * @return  :int    Whether the larger that type was +	 *                  split into two halves  	 */  #define LIBSYSCALLS_IS_SECTION_HALF(S)\  	(((S) >= LIBSYSCALLS_SECTION_UPPER_HALF) &&\ @@ -1998,12 +2013,15 @@ enum libsyscalls_datatype_section {  	 */  	LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF, -	/* +	/**  	 * This whether a data type represents a quarter section  	 * of larger data type  	 *  -	 * @param   S:enum libsyscalls_datatype_section  The data type section information -	 * @return  :int                                 Whether the larger that type was split into four quarters +	 * @param   S:enum libsyscalls_datatype_section +	 *                  The data type section information +	 *  +	 * @return  :int    Whether the larger that type was +	 *                  split into four quarters  	 */  #define LIBSYSCALLS_IS_SECTION_QUARTER(S)\  	(((S) >= LIBSYSCALLS_SECTION_UPPER_QUARTER) &&\ @@ -2061,18 +2079,73 @@ enum libsyscalls_datatype_section {  	 */  	LIBSYSCALLS_SECTION_LOWER_QUARTER -	/* -	 * Get the number of registers/fields the data type was split into +	/** +	 * Get the number of registers/fields the data type +	 * was split into +	 *  +	 * @param   S:enum libsyscalls_datatype_section +	 *                  The data type section information  	 *  -	 * @param   S:enum libsyscalls_datatype_section  The data type section information -	 * @return  :unsigned int                        The number registers/fields the data type was split into; -	 *                                               invalid if `S` is LIBSYSCALLS_SECTION_UNDETERMINED +	 * @return  :unsigned int +	 *                  The number registers/fields the data +	 *                  type was split into; invalid if `S` +	 *                  is LIBSYSCALLS_SECTION_UNDETERMINED  	 */  #define LIBSYSCALLS_GET_SECTION_FRACTION(S)\  	(LIBSYSCALLS_IS_SECTION_HALF(S) ? 2U :\  	 LIBSYSCALLS_IS_SECTION_QUARTER(S) ? 4U : 1U)  }; + +/** + * Macro for enumerating type-split sections + *  + * The numbers are stored in `enum libsyscalls_datatype_section` + *  + * @param  X:macro(NAME, ...)  Macro that expands, will a number of arguments: + *                             1) The name of the enum value + *                             2) 1 if the section is both compatible with 16-bit + *                                integers and is the first section with its + *                                pattern of covered bits for 16-bit integers, + *                                0 otherwise + *                             3) Mask of bits the section covers for a 16-bit integer + *                             4) 1 if the section is both compatible with 32-bit + *                                integers and is the first section with its + *                                pattern of covered bits for 32-bit integers, + *                                0 otherwise + *                             5) Mask of bits the section covers for a 32-bit integer + *                             6) 1 if the section is both compatible with 64-bit + *                                integers and is the first section with its + *                                pattern of covered bits for 64-bit integers, + *                                0 otherwise + *                             7) Mask of bits the section covers for a 64-bit integer + *                             Arguments 3, 5, and 7 are `0` when the section is not + *                             compatible with the data type and otherwise a `0x` + *                             prefixed uppercase hexadecimal number without any type + *                             suffix. + *                             Addition arguments may be added in the future. + * @param  D:code              Macro that expands between each expansion of X + *  + * The primary purpose of the existance of this macro + * is to ease implementation of the library; it will + * probably not disappear (no promises) + */ +#define LIBSYSCALLS_LIST_SECTIONS(X, D)\ +	X(LIBSYSCALLS_SECTION_WHOLE,                 1, 0xFFFF, 1, 0xFFFFFFFF, 1, 0xFFFFFFFFFFFFFFFF) D\ +	X(LIBSYSCALLS_SECTION_UPPER_HALF,            1, 0xFF00, 1, 0xFFFF0000, 1, 0xFFFFFFFF00000000) D\ +	X(LIBSYSCALLS_SECTION_LOWER_HALF,            1, 0x00FF, 1, 0x0000FFFF, 1, 0x00000000FFFFFFFF) D\ +	X(LIBSYSCALLS_SECTION_INNER_HALF,            0, 0,      1, 0x00FFFF00, 1, 0x0000FFFFFFFF0000) D\ +	X(LIBSYSCALLS_SECTION_OUTER_HALF,            0, 0,      1, 0xFF0000FF, 1, 0xFFFF00000000FFFF) D\ +	X(LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF, 0, 0,      1, 0x00FF00FF, 1, 0x0000FFFF0000FFFF) D\ +	X(LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF,  0, 0,      1, 0xFF00FF00, 1, 0xFFFF0000FFFF0000) D\ +	X(LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF,    0, 0,      0, 0x00FF00FF, 1, 0x00FF00FF00FF00FF) D\ +	X(LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF,     0, 0,      0, 0xFF00FF00, 1, 0xFF00FF00FF00FF00) D\ +	X(LIBSYSCALLS_SECTION_UPPER_QUARTER,         0, 0,      1, 0xFF000000, 1, 0xFFFF000000000000) D\ +	X(LIBSYSCALLS_SECTION_UPPER_MID_QUARTER,     0, 0,      1, 0x00FF0000, 1, 0x0000FFFF00000000) D\ +	X(LIBSYSCALLS_SECTION_LOWER_MID_QUARTER,     0, 0,      1, 0x0000FF00, 1, 0x00000000FFFF0000) D\ +	X(LIBSYSCALLS_SECTION_LOWER_QUARTER,         0, 0,      1, 0x000000FF, 1, 0x000000000000FFFF) + +  /**   * Information on how an instance of data type is to be parsed   *  @@ -2176,7 +2249,8 @@ struct libsyscalls_datatype_description {  	 */  	unsigned min_is_minus_max : 1; -	int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT, 2*5 + 4*1); +	int padding__ : LIBSYSCALLS_PAD_(sizeof(int)/sizeof(char)*CHAR_BIT, +	                                 2*5 + 4*1);  	/**  	 * Only used if .is_signed is 1 @@ -2231,20 +2305,25 @@ struct libsyscalls_datatype_description {  	unsigned char byteorder[32];  	/** -	 * Test whether a value in `struct libsyscalls_datatype_description.byteorder` -	 * marks the end of the byteorder's shift value (testing -	 * that the value is ~0). Using this macro helps avoiding -	 * bugs caused by integer type promotion. +	 * Test whether a value in `struct +	 * libsyscalls_datatype_description.byteorder` +	 * marks the end of the byteorder's shift value +	 * (testing that the value is ~0). Using this +	 * macro helps avoiding bugs caused by integer +	 * type promotion.  	 *  -	 * @param   SHIFT  The value to test `struct libsyscalls_datatype_description.byteorder` +	 * @param   SHIFT  The value to test `struct +	 *                 libsyscalls_datatype_description.byteorder`  	 * @return  :int   Whether the value is ~0  	 */  #ifdef UINTMAX_C  # define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\ -	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(UINTMAX_C(1), struct libsyscalls_datatype_description, byteorder[0]))) +	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(UINTMAX_C(1),\ +		struct libsyscalls_datatype_description, byteorder[0])))  #else  # define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\ -	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(1ULL, struct libsyscalls_datatype_description, byteorder[0]))) +	(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(1ULL,\ +		struct libsyscalls_datatype_description, byteorder[0])))  #endif  	/** @@ -2252,8 +2331,8 @@ struct libsyscalls_datatype_description {  	 * the (post-last) end of `DESC->byteorder`  	 */  #define LIBSYSCALLS_IS_BYTEORDER_END_AT(DESC, INDEX)\ -		((size_t)(INDEX) == sizeof((DESC)->byteorder) / sizeof(*(DESC)->byteorder) || \ -		 LIBSYSCALLS_IS_BYTEORDER_END((DESC)->byteorder[INDEX])) +	((size_t)(INDEX) == sizeof((DESC)->byteorder) / sizeof(*(DESC)->byteorder) || \ +	 LIBSYSCALLS_IS_BYTEORDER_END((DESC)->byteorder[INDEX]))  };  /** @@ -2506,7 +2585,8 @@ struct libsyscalls_structure_description {  # if !LIBSYSCALLS_CAN_ALIGN_(7, 16, CHAR_BIT)  #  error Sorry, we require that the a byte is no longer than (7*16) bits while evenly dividing (7*16) bits  # endif -	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), (7*16)/CHAR_BIT)]; +	char padding__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), +	                                (7*16)/CHAR_BIT)];  #endif  	/** @@ -2520,11 +2600,13 @@ struct libsyscalls_structure_description {   * Return a description of a libsyscalls error   *    * @param   error  The libsyscalls error - * @return         Description of the error, the first character will be in uppercase + * @return         Description of the error, the first + *                 character will be in uppercase   */  LIBSYSCALLS_GCC_ATTRIBUTES_(__const__, __returns_nonnull__, __warn_unused_result__)  const char * -libsyscalls_strerror(enum libsyscalls_error); +libsyscalls_strerror(enum libsyscalls_error error); +  /**   * Print a line with a description of a @@ -2535,21 +2617,25 @@ libsyscalls_strerror(enum libsyscalls_error);   * @param   error   The libsyscalls error   */  void -libsyscalls_perror(const char *, enum libsyscalls_error); +libsyscalls_perror(const char *prefix, enum libsyscalls_error err); +  /**   * Get the valid range system call numbers   *  - * @param   os       The operating system the range shall valid for - * @param   arch     The architecture the range shall valid for - * @param   min_out  Output parameter for the lowest used system call number (may be NULL) - * @param   max_out  Output parameter for the highest used system call number (may be NULL) - * @return           LIBSYSCALLS_E_OK        - On success - *                   LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for - *                                             the selected operating system (`os`) - *                   LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for - *                                             the selected architecture (`arch`) on the - *                                             selected operating system (`os`) + * @param  os       The operating system the range shall valid for + * @param  arch     The architecture the range shall valid for + * @param  min_out  Output parameter for the lowest used + *                  system call number (may be NULL) + * @param  max_out  Output parameter for the highest used + *                  system call number (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK        - On success + *          LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for + *                                    the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for + *                                    the selected architecture (`arch`) on the + *                                    selected operating system (`os`)   *    * This function always fails if the selected combination   * of operating system (`os`) and architecture (`arch`) is @@ -2559,36 +2645,45 @@ libsyscalls_perror(const char *, enum libsyscalls_error);   * (not [*min_out, *max_out - 1]) but there may still be numbers within   * this range that does not correspond to a system call   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __access__(__write_only__, 3), __access__(__write_only__, 4)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, +                            __access__(__write_only__, 3), +                            __access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_get_syscall_range(enum libsyscalls_os, enum libsyscalls_arch, long long int *, long long int *); +libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch, +                              long long int *min_out, long long int *max_out); +  /**   * Get the description of a system call   *  - * @param   os           The operating system the range shall valid for - * @param   arch         The architecture the range shall valid for - * @param   syscallnr    The system call's number - * @param   syscall_out  Output parameter for the system call description - *                       (the argument may be NULL, *syscall_out will - *                       never be set to NULL) - * @return               LIBSYSCALLS_E_OK            - On success - *                       LIBSYSCALLS_E_OSNOSUP       - The library is not compiled with support for - *                                                     the selected operating system (`os`) - *                       LIBSYSCALLS_E_ARCHNOSUP     - The library is not compiled with support for - *                                                     the selected architecture (`arch`) on the - *                                                     selected operating system (`os`) - *                       LIBSYSCALLS_E_NOSUCHSYSCALL - `syscallnr` does not correspond to a known - *                                                     system call for the selected architecture (`arch`) - *                                                     on the selected operating system (`os`) + * @param  os           The operating system the range shall valid for + * @param  arch         The architecture the range shall valid for + * @param  syscall_nr   The system call's number + * @param  syscall_out  Output parameter for the system call description + *                      (the argument may be NULL, *syscall_out will + *                      never be set to NULL) + *  + * @return  LIBSYSCALLS_E_OK            - On success + *          LIBSYSCALLS_E_OSNOSUP       - The library is not compiled with support for + *                                        the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP     - The library is not compiled with support for + *                                        the selected architecture (`arch`) on the + *                                        selected operating system (`os`) + *          LIBSYSCALLS_E_NOSUCHSYSCALL - `syscall_nr` does not correspond to a known + *                                        system call for the selected architecture (`arch`) + *                                        on the selected operating system (`os`)   *    * This function always fails if the selected combination   * of operating system (`os`) and architecture (`arch`) is   * unsupported   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __access__(__write_only__, 4)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, +                            __access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long int, const struct libsyscalls_syscall **); +libsyscalls_get_syscall(enum libsyscalls_os os, enum libsyscalls_arch arch, +                        long long int syscall_nr, +                        const struct libsyscalls_syscall **syscall_out); +  /**   * Get the system call errors defined by an operating system @@ -2599,27 +2694,36 @@ libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long in   * The returned listing will be sorted by the error numbers   * in ascending order   *  - * @param   os              The operating system whose errors shall be returned - * @param   arch            The architecture the error numbers shall be valid for - * @param   errors_out      Output parameter for the error list (may be NULL, never filled with NULL) - * @param   num_errors_out  Output parameter for the number of errors returned in `*errors_out` (may be NULL) - *                          (if `errors_out` is NULL, the number that would be returned is stored) - * @param   are_signed_out  Output parameter for whether the error numbers are signed (may be NULL) - * @return                  LIBSYSCALLS_E_OK        - On success - *                          LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for - *                                                    the selected operating system (`os`) - *                          LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for - *                                                    the selected architecture (`arch`) on the - *                                                    selected operating system (`os`) - *                          LIBSYSCALLS_E_NOERRORS  - The operating system does not use named error numbers + * @param  os              The operating system whose errors shall be returned + * @param  arch            The architecture the error numbers shall be valid for + * @param  errors_out      Output parameter for the error list + *                         (may be NULL, never filled with NULL) + * @param  num_errors_out  Output parameter for the number of errors returned + *                         in `*errors_out` (may be NULL) (if `errors_out` is NULL, + *                         the number that would be returned is stored) + * @param  are_signed_out  Output parameter for whether the error numbers are + *                         signed (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK        - On success + *          LIBSYSCALLS_E_OSNOSUP   - The library is not compiled with support for + *                                    the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP - The library is not compiled with support for + *                                    the selected architecture (`arch`) on the + *                                    selected operating system (`os`) + *          LIBSYSCALLS_E_NOERRORS  - The operating system does not use named error numbers   *   * This function will always fail if the operating system (`os`)   * is not supported, however it may be successful even if the   * architecture (`arch`) not supported   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3), __access__(__write_only__, 4), __access__(__write_only__, 5)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3), +                            __access__(__write_only__, 4), +                            __access__(__write_only__, 5))  enum libsyscalls_error -libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *, int *); +libsyscalls_get_syscall_errors(enum libsyscalls_os os, enum libsyscalls_arch arch, +                               const struct libsyscalls_named_number **errors_out, +                               size_t *num_errors_out, int *are_signed_out); +  /**   * Get the system signals defined by an operating system @@ -2630,58 +2734,140 @@ libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const   * The returned listing will be sorted by the signal   * numbers in ascending order   *  - * @param   os               The operating system whose errors shall be returned - * @param   arch             The architecture the error numbers shall be valid for - * @param   signals_out      Output parameter for the signal list (may be NULL, never filled with NULL) - * @param   num_signals_out  Output parameter for the number of signals returned in `*signals_out` (may be NULL) - *                           (if `signals_out` is NULL, the number that would be returned is stored) - * @param   are_signed_ out  Output parameter for whether the signal numbers are signed (may be NULL) - * @return                   LIBSYSCALLS_E_OK         - On success - *                           LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for - *                                                      the selected operating system (`os`) - *                           LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for - *                                                      the selected architecture (`arch`) on the - *                                                      selected operating system (`os`) - *                           LIBSYSCALLS_E_NOSIGNALS  - The operating system does not use named signal numbers + * @param  os               The operating system whose errors shall be returned + * @param  arch             The architecture the error numbers shall be valid for + * @param  signals_out      Output parameter for the signal list + *                          (may be NULL, never filled with NULL) + * @param  num_signals_out  Output parameter for the number of signals returned + *                          in `*signals_out` (may be NULL) (if `signals_out` is + *                          NULL, the number that would be returned is stored) + * @param  are_signed_out   Output parameter for whether the signal numbers are + *                          signed (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK         - On success + *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for + *                                     the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for + *                                     the selected architecture (`arch`) on the + *                                     selected operating system (`os`) + *          LIBSYSCALLS_E_NOSIGNALS  - The operating system does not use named signal numbers   *   * This function will always fail if the operating system (`os`)   * is not supported, however it may be successful even if the   * architecture (`arch`) not supported   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3), __access__(__write_only__, 4), __access__(__write_only__, 5)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 3), +                            __access__(__write_only__, 4), +                            __access__(__write_only__, 5))  enum libsyscalls_error -libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *, int *); +libsyscalls_get_signals(enum libsyscalls_os os, enum libsyscalls_arch arch, +                        const struct libsyscalls_named_number **signals_out, +                        size_t *num_signals_out, int *are_signed_out); + + +/** + * Finds a named number in a sorted array by its signed number + *  + * @param   key   The signed number of the named number to find + * @param   base  The array of named numbers, sorted in ascending + *                order by their signed numbers + * @param   n     The number of elements in `base` + * @return        The element in `base` whose signed number is `key`, + *                `NULL` if not found + */ +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__, +                            __access__(__read_only__, 2, 3)) +const struct libsyscalls_named_number * +libsyscalls_find_signed_named_number(signed long long int key, +                                     const struct libsyscalls_named_number *base, size_t n); + + +/** + * Finds a named number in a sorted array by its unsigned number + *  + * @param   key   The unsigned number of the named number to find + * @param   base  The array of named numbers, sorted in ascending + *                order by their unsigned numbers + * @param   n     The number of elements in `base` + * @return        The element in `base` whose unsigned number is `key`, + *                `NULL` if not found + */ +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__, +                            __access__(__read_only__, 2, 3)) +const struct libsyscalls_named_number * +libsyscalls_find_unsigned_named_number(unsigned long long int key, +                                       const struct libsyscalls_named_number *base, size_t n); + + +/** + * Finds a named number in a sorted array by its number + *  + * @param   key        The number of the named number to find + * @param   is_signed  Whether the numbers are signed + * @param   base       The array of named numbers, sorted in ascending + *                     order by their numbers + * @param   n          The number of elements in `base` + * @return             The element in `base` whose number is `key`, + *                     `NULL` if not found + *  + * If `is_signed` is non-zero, `key` is reinterpreted (not cast) as a signed number; + * thus it is important that if `key` uses all bits in `long long int`, + * would be an error to take a `int`, reinterpret it as an `unsigned int`, + * and input it to as `key` casting it to `unsigned long long int`; rather + * an `int` must first be cast to `long long int`, and then reinterpreted + * as a `unsigned long long int` before it is input as `key`. Using + * `libsyscalls_find_signed_named_number` instead removes this complication + * in such a senario. + */ +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __pure__, +                            __access__(__read_only__, 3, 4)) +inline const struct libsyscalls_named_number * +libsyscalls_find_named_number(unsigned long long int key, int is_signed, +                              const struct libsyscalls_named_number *base, size_t n) +{ +	signed long long int skey = *(signed long long int *)&key; +	return is_signed ? libsyscalls_find_signed_named_number(skey, base, n) +	                 : libsyscalls_find_unsigned_named_number(key, base, n); +} +  /**   * Get system call information tweak for the arguments passed   * to the system call, as well as information about how to   * print named values in the arguments and return   *  - * @param   os                 The operating system the system call was invoked on - * @param   arch               The architecture the system call was invoked on - * @param   syscall            The ABI of the system call (see libsyscalls_get_syscall) - * @param   syscall_number     The system call's number - * @param   syscall_arguments  The values store in register (as upon system call entry) - *                             the used for the system call, in the order the registers - *                             are used as system call arguments - * @param   info_out           Output parameter for the additional system call information; - *                             the caller responsible for deallocating the `*info_out` - *                             with free(3) when it is no longer needed. Be aware that - *                             `*info_out` will only be set when LIBSYSCALLS_E_OK is - *                             returned. - * @return                     LIBSYSCALLS_E_OK         - On success - *                             LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for - *                                                        the selected operating system (`os`) - *                             LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for - *                                                        the selected architecture (`arch`) on the - *                                                        selected operating system (`os`) - *                             LIBSYSCALLS_E_NOMEM      - Failed to allocate memory for `*info_out` - *                             LIBSYSCALLS_E_INVAL      - One of the arguments was NULL + * @param  os                 The operating system the system call was invoked on + * @param  arch               The architecture the system call was invoked on + * @param  syscall            The ABI of the system call (see libsyscalls_get_syscall) + * @param  syscall_number     The system call's number + * @param  syscall_arguments  The values store in register (as upon system call entry) + *                            the used for the system call, in the order the registers + *                            are used as system call arguments + * @param  info_out           Output parameter for the additional system call information; + *                            the caller responsible for deallocating the `*info_out` + *                            with free(3) when it is no longer needed. Be aware that + *                            `*info_out` will only be set when LIBSYSCALLS_E_OK is + *                            returned. + *  + * @return  LIBSYSCALLS_E_OK         - On success + *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for + *                                     the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for + *                                     the selected architecture (`arch`) on the + *                                     selected operating system (`os`) + *          LIBSYSCALLS_E_NOMEM      - Failed to allocate memory for `*info_out` + *          LIBSYSCALLS_E_INVAL      - One of the arguments was NULL   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__, __access__(__read_only__, 3), __access__(__write_only__, 6)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __nonnull__, +                            __access__(__read_only__, 3), +                            __access__(__write_only__, 6))  enum libsyscalls_error -libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_syscall_abi *, -                                     long long int, const unsigned long long int *, struct libsyscalls_syscall_display_info **); +libsyscalls_get_syscall_display_info(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                     const struct libsyscalls_syscall_abi *syscall, +                                     long long int syscall_number, +                                     const unsigned long long int *syscall_arguments, +                                     struct libsyscalls_syscall_display_info **info_out); +  /**   * Get information on how an instance of non-struct, non-union @@ -2692,32 +2878,36 @@ libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch,   * in the structure's field, as it may contain   * important adjustments   *  - * @param   os               The operating system the data type is used on - * @param   arch             The architecture the data type is used on - * @param   datatype         The data type, `LIBSYSCALLS_TYPE_DYNAMIC` can - *                           be used to get the size of the registers used - *                           as system call parameters - * @param   description_out  Output parameter for the type description - * @return                   LIBSYSCALLS_E_OK         - On success - *                           LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for - *                                                      the selected operating system (`os`) - *                           LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for - *                                                      the selected architecture (`arch`) on the - *                                                      selected operating system (`os`) - *                           LIBSYSCALLS_E_INVAL      - `datatype` is not a valid data type - *                           LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected - *                                                      operating system (`os`) or architecture (`arch`) - *                           LIBSYSCALLS_E_ISSTRUCT   - `datatype` represents a structure or union, - *                                                      or an array of a structure or union + * @param  os               The operating system the data type is used on + * @param  arch             The architecture the data type is used on + * @param  datatype         The data type, `LIBSYSCALLS_TYPE_DYNAMIC` can + *                          be used to get the size of the registers used + *                          as system call parameters + * @param  description_out  Output parameter for the type description + *  + * @return  LIBSYSCALLS_E_OK         - On success + *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for + *                                     the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for + *                                     the selected architecture (`arch`) on the + *                                     selected operating system (`os`) + *          LIBSYSCALLS_E_INVAL      - `datatype` is not a valid data type + *          LIBSYSCALLS_E_NOSUCHTYPE - `datatype` does not exist on the selected + *                                     operating system (`os`) or architecture (`arch`) + *          LIBSYSCALLS_E_ISSTRUCT   - `datatype` represents a structure or union, + *                                     or an array of a structure or union   *    * The function may complete successfully for some data   * types even if it for other data types would return   * LIBSYSCALLS_E_OSNOSUP or LIBSYSCALLS_E_ARCHNOSUP   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __access__(__write_only__, 4)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, +                            __access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype, -                                     struct libsyscalls_datatype_description *); +libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                     enum libsyscalls_datatype datatype, +                                     struct libsyscalls_datatype_description *description_out); +  /**   * Get the alignment used for or a scalar integer data type @@ -2733,34 +2923,38 @@ libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch,   * optimal alignment), in such cases, that proscribed alignment will   * be returned instead.   *  - * @param   os             The operating system the data type is used on - * @param   arch           The architecture the data type is used on - * @param   width_in_bits  The width of the integer, in bits - * @param   alignment_out  Output parameter for the alignment, in bits - *                         (may be NULL, will never be filled with 0) - * @return                 LIBSYSCALLS_E_OK         - On success - *                         LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for - *                                                    the selected operating system (`os`) - *                         LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for - *                                                    the selected architecture (`arch`) on the - *                                                    selected operating system (`os`) - *                         LIBSYSCALLS_E_INVAL      - `width_in_bits` is 0 - *                         LIBSYSCALLS_E_NOSUCHTYPE - The selected architecture (`arch`) does not - *                                                    support any integer width the specified - *                                                    width (`width_in_bits`), or the operating - *                                                    system (`os`) does not support the data type - *                                                    (that would only be the case if the data type - *                                                    uses a new register that must be specifically - *                                                    supported in the operating system's context - *                                                    switching) + * @param  os             The operating system the data type is used on + * @param  arch           The architecture the data type is used on + * @param  width_in_bits  The width of the integer, in bits + * @param  alignment_out  Output parameter for the alignment, in bits + *                        (may be NULL, will never be filled with 0) + *  + * @return  LIBSYSCALLS_E_OK         - On success + *          LIBSYSCALLS_E_OSNOSUP    - The library is not compiled with support for + *                                     the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP  - The library is not compiled with support for + *                                     the selected architecture (`arch`) on the + *                                     selected operating system (`os`) + *          LIBSYSCALLS_E_INVAL      - `width_in_bits` is 0 + *          LIBSYSCALLS_E_NOSUCHTYPE - The selected architecture (`arch`) does not + *                                     support any integer width the specified + *                                     width (`width_in_bits`), or the operating + *                                     system (`os`) does not support the data type + *                                     (that would only be the case if the data type + *                                     uses a new register that must be specifically + *                                     supported in the operating system's context + *                                     switching)   *    * The function may complete successfully even if out ought to   * return LIBSYSCALLS_E_ARCHNOSUP, in such cases, the result   * is indeed reliable   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __access__(__write_only__, 4)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, +                            __access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_get_integer_alignment(enum libsyscalls_os, enum libsyscalls_arch, unsigned, unsigned *); +libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                  unsigned width_in_bits, unsigned *alignment_out); +  /**   * Parse a string of bits as a signed integer @@ -2768,20 +2962,26 @@ libsyscalls_get_integer_alignment(enum libsyscalls_os, enum libsyscalls_arch, un   * In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,   * the bits are parsed as an unsigned integer   *  - * @param   value_in        The bits to parse as a signed integer - * @param   representation  The sign representation used on the interger - * @param   bits            The number of bits in the integer - * @param   value_out       Output parameter for the absolute value of the signed integer (may be NULL) - * @param   negative_out    Output parameter for whether the signed integer is negative (may be NULL) - * @return                  LIBSYSCALLS_E_OK    - On success - *                          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library - *                          LIBSYSCALLS_E_INVAL - `bits` is 0 - *                          LIBSYSCALLS_E_INVAL - `bits` is greater than `sizeof(long long int) * CHAR_BIT` + * @param  value_in        The bits to parse as a signed integer + * @param  representation  The sign representation used on the interger + * @param  bits            The number of bits in the integer + * @param  value_out       Output parameter for the absolute value + *                         of the signed integer (may be NULL) + * @param  negative_out    Output parameter for whether the signed + *                         integer is negative (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library + *          LIBSYSCALLS_E_INVAL - `bits` is 0 + *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4), __access__(__write_only__, 5)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4), +                            __access__(__write_only__, 5))  enum libsyscalls_error -libsyscalls_parse_signed_integer(unsigned long long int, enum libsyscalls_datatype_sign_representation, -                                 size_t, unsigned long long int *, int *); +libsyscalls_parse_signed_integer(unsigned long long int value_in, +                                 enum libsyscalls_datatype_sign_representation representation, +                                 size_t bits, unsigned long long int *value_out, int *negative_out); +  /**   * Create a string of bits representing a signed integer @@ -2789,20 +2989,23 @@ libsyscalls_parse_signed_integer(unsigned long long int, enum libsyscalls_dataty   * In case `representation` is LIBSYSCALLS_SIGN_UNDETERMINED,   * the bit string will represent an unsigned integer   *  - * @param   value_in        The absolute value if the signed integer - * @param   negative        Whether the signed integer is negative - * @param   representation  The sign representation used on the interger - * @param   bits            The number of bits in the integer - * @param   value_out       Output parameter for the bit string (may be NULL) - * @return                  LIBSYSCALLS_E_OK    - On success - *                          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library - *                          LIBSYSCALLS_E_INVAL - `bits` is 0 - *                          LIBSYSCALLS_E_INVAL - `bits` is greater than `sizeof(long long int) * CHAR_BIT` + * @param  value_in        The absolute value if the signed integer + * @param  negative        Whether the signed integer is negative + * @param  representation  The sign representation used on the interger + * @param  bits            The number of bits in the integer + * @param  value_out       Output parameter for the bit string (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library + *          LIBSYSCALLS_E_INVAL - `bits` is 0 + *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`   */  LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 5))  enum libsyscalls_error -libsyscalls_make_signed_integer(unsigned long long int, int, enum libsyscalls_datatype_sign_representation, -                                size_t, unsigned long long int *); +libsyscalls_make_signed_integer(unsigned long long int value_in, int negative, +                                enum libsyscalls_datatype_sign_representation representation, +                                size_t bits, unsigned long long int *value_out); +  /**   * Take bits from a section of a split value @@ -2813,18 +3016,23 @@ libsyscalls_make_signed_integer(unsigned long long int, int, enum libsyscalls_da   * If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,   * no changes will be made   *  - * @param   value_in        The contiguous bits in the section of the value - * @param   bits            The number of bits in the section of the value - * @param   section         The section of the value - * @param   value_out       Output parameter for the value with its bits shifted into place (may be NULL) - * @return                  LIBSYSCALLS_E_OK    - On success - *                          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library - *                          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section` - *                          LIBSYSCALLS_E_INVAL - `bits` is greater than `sizeof(long long int) * CHAR_BIT` + * @param  value_in   The contiguous bits in the section of the value + * @param  bits       The number of bits in the section of the value + * @param  section    The section of the value + * @param  value_out  Output parameter for the value with its + *                    bits shifted into place (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library + *          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section` + *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`   */  LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_unsection_value(unsigned long long int, size_t, enum libsyscalls_datatype_section, unsigned long long int *); +libsyscalls_unsection_value(unsigned long long int value_in, size_t bits, +                            enum libsyscalls_datatype_section section, +                            unsigned long long int *value_out); +  /**   * Create a split section from a value @@ -2832,51 +3040,70 @@ libsyscalls_unsection_value(unsigned long long int, size_t, enum libsyscalls_dat   * If `section` is LIBSYSCALLS_SECTION_UNDETERMINED,   * no changes will be made   *  - * @param   value_in        The whole value - * @param   bits            The number of bits in the whole value - * @param   section         The section of the value to return - * @param   value_out       Output parameter for bits in the section value shifted into contiguity (may be NULL) - * @return                  LIBSYSCALLS_E_OK    - On success - *                          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library - *                          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section` - *                          LIBSYSCALLS_E_INVAL - `bits` is greater than `sizeof(long long int) * CHAR_BIT` + * @param  value_in   The whole value + * @param  bits       The number of bits in the whole value + * @param  section    The section of the value to return + * @param  value_out  Output parameter for bits in the section + *                    value shifted into contiguity (may be NULL) + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - `representation` is not recognised by the library + *          LIBSYSCALLS_E_INVAL - `bits` is invalid for `section` + *          LIBSYSCALLS_E_INVAL - `bits > sizeof(long long int) * CHAR_BIT`   */  LIBSYSCALLS_GCC_ATTRIBUTES_(__access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_section_value(unsigned long long int, size_t, enum libsyscalls_datatype_section, unsigned long long int *); +libsyscalls_section_value(unsigned long long int value_in, size_t bits, +                          enum libsyscalls_datatype_section section, +                          unsigned long long int *value_out); +  /**   * Converts a value from the tracee's endian to the tracer's endian   *  - * @param   value_in   Buffer containing the value to convert (does not need to be aligned) - * @param   offset_in  Offset in `value_in`, in bits - * @param   type       Details about the data type - * @param   value_out  Output parameter for the value in the tracer's endian - * @return             LIBSYSCALLS_E_OK    - On success - *                     LIBSYSCALLS_E_INVAL - Either parameter is NULL - *                     LIBSYSCALLS_E_INVAL - The data type is too wide + * @param  value_in   Buffer containing the value to convert + *                    (does not need to be aligned) + * @param  offset_in  Offset in `value_in`, in bits + * @param  type       Details about the data type + * @param  value_out  Output parameter for the value in the tracer's endian + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - Either parameter is NULL + *          LIBSYSCALLS_E_INVAL - The data type is too wide   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__, __access__(__read_only__, 1), __access__(__read_only__, 3), __access__(__write_only__, 4)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__, +                            __access__(__read_only__, 1), +                            __access__(__read_only__, 3), +                            __access__(__write_only__, 4))  enum libsyscalls_error -libsyscalls_to_tracer_endian(const void *, size_t, const struct libsyscalls_datatype_description *, unsigned long long int *); +libsyscalls_to_tracer_endian(const void *value_in, size_t offset_in, +                             const struct libsyscalls_datatype_description *type, +                             unsigned long long int *value_out); +  /**   * Converts a value from the tracer's endian to the tracee's endian   *  - * @param   value_in    Buffer containing the value to convert - * @param   type        Details about the data type - * @param   value_out   Output parameter for the value in the tracee's - *                      endian (does not need to be aligned); preexisting - *                      bits that do not overlap with the position of the - *                      value will be retained - * @param   out_offset  Offset in `value_out`, in bits - * @return              LIBSYSCALLS_E_OK    - On success - *                      LIBSYSCALLS_E_INVAL - Either parameter is NULL - *                      LIBSYSCALLS_E_INVAL - The data type is too wide + * @param  value_in    Buffer containing the value to convert + * @param  type        Details about the data type + * @param  value_out   Output parameter for the value in the tracee's + *                     endian (does not need to be aligned); preexisting + *                     bits that do not overlap with the position of the + *                     value will be retained + * @param  out_offset  Offset in `value_out`, in bits + *  + * @return  LIBSYSCALLS_E_OK    - On success + *          LIBSYSCALLS_E_INVAL - Either parameter is NULL + *          LIBSYSCALLS_E_INVAL - The data type is too wide   */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__, __access__(__read_only__, 2), __access__(__read_write__, 3)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__nonnull__, +                            __access__(__read_only__, 2), +                            __access__(__read_write__, 3))  enum libsyscalls_error -libsyscalls_to_tracee_endian(unsigned long long int, const struct libsyscalls_datatype_description *, void *, size_t); +libsyscalls_to_tracee_endian(unsigned long long int value_in, +                             const struct libsyscalls_datatype_description *type, +                             void *value_out, size_t out_offset); +  /**   * Get information on how an instance of struct or union is to be parsed @@ -2886,37 +3113,44 @@ libsyscalls_to_tracee_endian(unsigned long long int, const struct libsyscalls_da   * structure's field, as it may contain important   * adjustments   *  - * @param   os               The operating system the data type is used on - * @param   arch             The architecture the data type is used on - * @param   datatype         The data type - * @param   data             The data that is to be parsed (may be `NULL` if `data_size` is 0) - * @param   data_size        The number of bytes available in `data`, may be short or in excess - * @param   description_out  Output parameter for the type description; - *                           the caller responsible for deallocating the `*info_out` - *                           with free(3) when it is no longer needed. Be aware that - *                           `*info_out` will only be set when LIBSYSCALLS_E_OK is - *                           returned. - * @return                   LIBSYSCALLS_E_OK          - On success - *                           LIBSYSCALLS_E_OSNOSUP     - The library is not compiled with support for - *                                                       the selected operating system (`os`) - *                           LIBSYSCALLS_E_ARCHNOSUP   - The library is not compiled with support for - *                                                       the selected architecture (`arch`) on the - *                                                       selected operating system (`os`) - *                           LIBSYSCALLS_E_INVAL       - `datatype` is not a valid data type - *                           LIBSYSCALLS_E_NOSUCHTYPE  - `datatype` does not exist on the selected - *                                                       operating system (`os`) or architecture (`arch`) - *                           LIBSYSCALLS_E_ISNOTSTRUCT - `datatype` does not represent a structure or - *                                                       union, nor an array of structure or union + * @param  os               The operating system the data type is used on + * @param  arch             The architecture the data type is used on + * @param  datatype         The data type + * @param  data             The data that is to be parsed + *                          (may be `NULL` if `data_size` is 0) + * @param  data_size        The number of bytes available in `data`, + *                          may be short or in excess + * @param  description_out  Output parameter for the type description; + *                          the caller responsible for deallocating the `*info_out` + *                          with free(3) when it is no longer needed. Be aware that + *                          `*info_out` will only be set when LIBSYSCALLS_E_OK is + *                          returned. + *  + * @return  LIBSYSCALLS_E_OK          - On success + *          LIBSYSCALLS_E_OSNOSUP     - The library is not compiled with support for + *                                      the selected operating system (`os`) + *          LIBSYSCALLS_E_ARCHNOSUP   - The library is not compiled with support for + *                                      the selected architecture (`arch`) on the + *                                      selected operating system (`os`) + *          LIBSYSCALLS_E_INVAL       - `datatype` is not a valid data type + *          LIBSYSCALLS_E_NOSUCHTYPE  - `datatype` does not exist on the selected + *                                      operating system (`os`) or architecture (`arch`) + *          LIBSYSCALLS_E_ISNOTSTRUCT - `datatype` does not represent a structure or + *                                      union, nor an array of structure or union   *    * The function may complete successfully for some data   * types even if it for other data types would return   * LIBSYSCALLS_E_ARCHNOSUP   */  #if 0 /* work in progress */ -LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, __access__(__read_only__, 4, 5), __access__(__write_only__, 6)) +LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__, +                            __access__(__read_only__, 4, 5), +                            __access__(__write_only__, 6))  enum libsyscalls_error -libsyscalls_get_struct_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype, -                                   const void *, size_t, struct libsyscalls_structure_description **); +libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                   enum libsyscalls_datatype datatype, +                                   const void *data, size_t data_size, +                                   struct libsyscalls_structure_description **description_out);  #endif  /* TODO add libsyscalls_get_struct_display_info */ diff --git a/libsyscalls_find_named_number.c b/libsyscalls_find_named_number.c new file mode 100644 index 0000000..fe8bb47 --- /dev/null +++ b/libsyscalls_find_named_number.c @@ -0,0 +1,141 @@ +/* See LICENSE file for copyright and license details. */ +#include "common.h" + + +#ifdef USE_INTERPOLATION_SEARCH + +# ifndef INTERPOLATION_SEARCH_FLOAT +#  define INTERPOLATION_SEARCH_FLOAT long double +# endif + + +/* convertion to unsigned is a modulo (unsigned maximum + 1) operation */ +# define DIFF(TYPE, A, B) ((unsigned TYPE)(A) - (unsigned TYPE)(B)) + +# define INTERPOL_SEARCH(KEY, BASE, N, READ)\ +	do {\ +		INTERPOLATION_SEARCH_FLOAT guess_d;\ +		unsigned long long int guess;\ +		size_t h = (N);\ +		\ +		if (!h--)\ +			return NULL;\ +		\ +		if ((KEY) <= READ((BASE), 0))\ +			return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ +		if ((KEY) >= READ((BASE), h))\ +			return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ +		if (READ((BASE), 0) == READ((BASE), h))\ +			return NULL;\ +		\ +		goto use_double;\ +		guess = DIFF(long long int, (KEY), READ((BASE), 0));\ +		if (h > ULLONG_MAX / guess)\ +			goto use_double;\ +		\ +		for (;;) {\ +			guess = DIFF(long long int, (KEY), READ((BASE), 0));\ +			guess *= (unsigned long long int)h;\ +			guess /= DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ +			\ +			if (READ((BASE), guess) < (KEY)) {\ +				h -= guess += 1;\ +				(BASE) = &(BASE)[guess];\ +			} else if (READ((BASE), guess) > (KEY)) {\ +				h = guess -= 1;\ +			} else {\ +				return &(BASE)[guess];\ +			}\ +			\ +			if ((KEY) <= READ((BASE), 0))\ +				return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ +			if ((KEY) >= READ((BASE), h))\ +				return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ +			if (READ((BASE), 0) == READ((BASE), h))\ +				return NULL;\ +		}\ +		\ +	use_double:\ +		for (;;) {\ +			guess = DIFF(long long int, (KEY), READ((BASE), 0));\ +			guess_d = (INTERPOLATION_SEARCH_FLOAT)guess * (INTERPOLATION_SEARCH_FLOAT)h;\ +			guess = DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ +			guess_d /= (INTERPOLATION_SEARCH_FLOAT)guess;\ +			guess = (unsigned long long int)guess_d;\ +			\ +			if (READ((BASE), guess) < (KEY)) {\ +				h -= guess += 1;\ +				(BASE) = &(BASE)[guess];\ +			} else if (READ((BASE), guess) > (KEY)) {\ +				h = guess -= 1;\ +			} else {\ +				return &(BASE)[guess];\ +			}\ +			\ +			if ((KEY) <= READ((BASE), 0))\ +				return (KEY) == READ((BASE), 0) ? &(BASE)[0] : NULL;\ +			if ((KEY) >= READ((BASE), h))\ +				return (KEY) == READ((BASE), h) ? &(BASE)[h] : NULL;\ +			if (READ((BASE), 0) == READ((BASE), h))\ +				return NULL;\ +		}\ +	} while (0) + + +#else + + +PURE_FUNCTION +static int +signed_named_number_cmp(const void *a_, const void *b_) +{ +	const struct libsyscalls_named_number *a = a_, *b = b_; +	return a->number.s < b->number.s ? -1 : a->number.s > b->number.s; +} + + +PURE_FUNCTION +static int +unsigned_named_number_cmp(const void *a_, const void *b_) +{ +	const struct libsyscalls_named_number *a = a_, *b = b_; +	return a->number.u < b->number.u ? -1 : a->number.u > b->number.u; +} + + +#endif + + +const struct libsyscalls_named_number * +libsyscalls_find_signed_named_number(signed long long int key, +                                     const struct libsyscalls_named_number *base, size_t n) +{ +#ifdef USE_INTERPOLATION_SEARCH +# define X(ARR, I) ((ARR)[I].number.s) +	INTERPOL_SEARCH(key, base, n, X); +# undef X +#else +	struct libsyscalls_named_number struct_key = {.number.s = key}; +	return bsearch(&struct_key, base, n, sizeof(*base), &signed_named_number_cmp); +#endif +} + + +const struct libsyscalls_named_number * +libsyscalls_find_unsigned_named_number(unsigned long long int key, +                                       const struct libsyscalls_named_number *base, size_t n) +{ +#ifdef USE_INTERPOLATION_SEARCH +# define X(ARR, I) ((ARR)[I].number.u) +	INTERPOL_SEARCH(key, base, n, X); +# undef X +#else +	struct libsyscalls_named_number struct_key = {.number.u = key}; +	return bsearch(&struct_key, base, n, sizeof(*base), &unsigned_named_number_cmp); +#endif +} + + +extern inline const struct libsyscalls_named_number * +libsyscalls_find_named_number(unsigned long long int key, int is_signed, +                              const struct libsyscalls_named_number *base, size_t n); diff --git a/libsyscalls_get_datatype_description.c b/libsyscalls_get_datatype_description.c index a418eb3..974c0fe 100644 --- a/libsyscalls_get_datatype_description.c +++ b/libsyscalls_get_datatype_description.c @@ -5,7 +5,8 @@  #include "generated/types.c"  enum libsyscalls_error -libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, +libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                     enum libsyscalls_datatype datatype,                                       struct libsyscalls_datatype_description *description_out)  {  	struct libsyscalls_datatype_description description_discard, larger_type; @@ -19,7 +20,7 @@ libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_ar  	if (!description_out)  		description_out = &description_discard; -	if ((unsigned)datatype & ~(LIBSYSCALLS_TYPEBITSMASK | (LIBSYSCALLS_TYPEBITSMASK - 1U))) +	if ((unsigned)datatype & ~SET_MASK_TRAIL(LIBSYSCALLS_TYPEBITSMASK))  		return LIBSYSCALLS_E_INVAL;  	datatype ^= class = datatype & LIBSYSCALLS_TYPEBITSMASK; @@ -63,7 +64,7 @@ libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_ar  	memset(description_out->byteorder, ~0, sizeof(description_out->byteorder)); -#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\ +#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, INTMAX_ALIGN, ENDIAN, SIGN)\  	case ARCH: description_out->sign_representation = LIBSYSCALLS_SIGN_##SIGN; break  	switch ((int)arch) {  	LIST_ARCH_SPECS(CASE, ;); @@ -147,7 +148,8 @@ libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_ar  	} else if (datatype >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS) {  	unannotated: -		if (datatype - LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS >= COUNT_LIST(LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS)) { +		if (datatype - LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS +		    >= COUNT_LIST(LIBSYSCALLS_LIST_UNANNOTATED_NUMERICALS)) {  			return LIBSYSCALLS_E_INVAL;  		} else if (datatype == LIBSYSCALLS_TYPE_MEMORY_ADDRESS) {  			datatype = LIBSYSCALLS_TYPE_INTPTR; @@ -163,7 +165,8 @@ libsyscalls_get_datatype_description(enum libsyscalls_os os, enum libsyscalls_ar  	} else if (datatype >= LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES) {  		if (class != LIBSYSCALLS_TYPEBITS_SCALAR)  			return LIBSYSCALLS_E_INVAL; -		if (datatype - LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES >= COUNT_LIST(LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES)) +		if (datatype - LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES +		    >= COUNT_LIST(LIBSYSCALLS_LIST_COMPOSITE_PRIMITIVES))  			return LIBSYSCALLS_E_INVAL;  		datatype = LIBSYSCALLS_TYPE_MEMORY_ADDRESS;  		goto unannotated; @@ -258,7 +261,7 @@ arch_dependent:  		goto not_os_dependent;  	case LIBSYSCALLS_TYPE_INTPTR:  	case LIBSYSCALLS_TYPE_PTRDIFF: -#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\ +#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, INTMAX_ALIGN, ENDIAN, SIGN)\  		case ARCH: description_out->width_in_bits = INTPTR_BITS; break  		switch ((int)arch) {  		LIST_ARCH_SPECS(CASE, ;); @@ -268,7 +271,7 @@ arch_dependent:  		goto not_os_dependent;  #undef CASE  	case LIBSYSCALLS_TYPE_SSIZE: -#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\ +#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, INTMAX_ALIGN, ENDIAN, SIGN)\  		case ARCH: description_out->width_in_bits = SIZE_BITS; break  		switch ((int)arch) {  		LIST_ARCH_SPECS(CASE, ;); @@ -314,7 +317,7 @@ not_os_dependent:  	if (divide_array_size_with_type_size_out)  		description_out->array_size /= description_out->width_in_bits; -#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, ENDIAN, SIGN)\ +#define CASE(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, INTMAX_ALIGN, ENDIAN, SIGN)\  	case ARCH: charbits = CHARBITS; endian = ENDIAN; break  	switch ((int)arch) {  	LIST_ARCH_SPECS(CASE, ;); @@ -377,17 +380,12 @@ not_os_dependent:  		/* we known from the code above that we are working with split 64-bit integers */  		if (half == +1) -			coverage ^= 0xFFFFFFFFFFFFFFFFull; -		if      (coverage == 0xFFFFFFFF00000000ull) description_out->section = LIBSYSCALLS_SECTION_UPPER_HALF; -		else if (coverage == 0x00000000FFFFFFFFull) description_out->section = LIBSYSCALLS_SECTION_LOWER_HALF; -		else if (coverage == 0x0000FFFFFFFF0000ull) description_out->section = LIBSYSCALLS_SECTION_INNER_HALF; -		else if (coverage == 0xFFFF00000000FFFFull) description_out->section = LIBSYSCALLS_SECTION_OUTER_HALF; -		else if (coverage == 0x0000FFFF0000FFFFull) description_out->section = LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF; -		else if (coverage == 0xFFFF0000FFFF0000ull) description_out->section = LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF; -		else if (coverage == 0x00FF00FF00FF00FFull) description_out->section = LIBSYSCALLS_SECTION_EVEN_BYTES_AS_HALF; -		else if (coverage == 0xFF00FF00FF00FF00ull) description_out->section = LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF; -		else -			abort(); +			coverage ^= 0xFFFFFFFFFFFFFFFFULL; +#define CASE(SECTION, PAT16_FIRST, PAT16, PAT32_FIRST, PAT32, PAT64_FIRST, PAT64)\ +		if (PAT64_FIRST && LIBSYSCALLS_GET_SECTION_FRACTION(SECTION) && coverage == PAT64##ULL)\ +			description_out->section = SECTION +		LIBSYSCALLS_LIST_SECTIONS(CASE, ; else); else abort(); +#undef CASE  	}  	return LIBSYSCALLS_E_OK; diff --git a/libsyscalls_get_integer_alignment.c b/libsyscalls_get_integer_alignment.c index 1c2d10e..f13f40f 100644 --- a/libsyscalls_get_integer_alignment.c +++ b/libsyscalls_get_integer_alignment.c @@ -4,73 +4,26 @@  #include "generated/integers.c" +#define X(ARCH, CHARBITS, INTPTR_BITS, SIZE_BITS, INTMAX_ALIGN, ENDIAN, SIGN) [ARCH] = INTMAX_ALIGN +static const unsigned char aligntable[] = {LIST_ARCH_SPECS(X, COMMA)}; +#undef X +  enum libsyscalls_error -libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch, unsigned width_in_bits, unsigned *alignment_out) +libsyscalls_get_integer_alignment(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                  unsigned width_in_bits, unsigned *alignment_out)  {  	unsigned maxalign;  	if (!width_in_bits)  		return LIBSYSCALLS_E_INVAL; -	switch ((int)arch) { -	case LIBSYSCALLS_ARCH_M68K: /* https://m680x0.github.io/doc/abi.html#scalar-types -	                             * https://lists.nongnu.org/archive/html/qemu-devel/2015-02/msg04797.html */ -		maxalign = 16; -		break; - -	case LIBSYSCALLS_ARCH_I386: -	case LIBSYSCALLS_ARCH_ARM_OABI_LE: /* https://wiki.debian.org/ArmEabiPort#A64-bit_data_type_alignment */ -	case LIBSYSCALLS_ARCH_ARM_OABI_BE: -	case LIBSYSCALLS_ARCH_SH_LE: /* https://www.st.com/resource/en/reference_manual/rm0197-sh4-generic-and-c-specific-application-binary-interface-stmicroelectronics.pdf (page 12) */ -	case LIBSYSCALLS_ARCH_SH_BE: -	case LIBSYSCALLS_ARCH_MICROBLAZE_32_LE: /* https://www.ecb.torontomu.ca/~courses/ee8205/Data-Sheets/sopc/MicroBlaze_DataSheet.pdf */ -	case LIBSYSCALLS_ARCH_MICROBLAZE_32_BE: -		maxalign = 32; -		break; - -	case LIBSYSCALLS_ARCH_AMD64: -	case LIBSYSCALLS_ARCH_AMD64_X32: -	case LIBSYSCALLS_ARCH_ARM_EABI_LE: /* https://wiki.debian.org/ArmEabiPort#A64-bit_data_type_alignment */ -	case LIBSYSCALLS_ARCH_ARM_EABI_BE: -	case LIBSYSCALLS_ARCH_ALPHA_LE: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ -	case LIBSYSCALLS_ARCH_ALPHA_BE: -	case LIBSYSCALLS_ARCH_IA64_LE: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ -	case LIBSYSCALLS_ARCH_IA64_BE: -	case LIBSYSCALLS_ARCH_IA64_P32_LE: -	case LIBSYSCALLS_ARCH_IA64_P32_BE: -	case LIBSYSCALLS_ARCH_MIPS_O32_LE: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ -	case LIBSYSCALLS_ARCH_MIPS_O32_BE: -	case LIBSYSCALLS_ARCH_MIPS_N32_LE: /* https://s3-eu-west-1.amazonaws.com/downloads-mips/documents/MD00083-2B-MIPS64INT-AFP-05.04.pdf (page 40) */ -	case LIBSYSCALLS_ARCH_MIPS_N32_BE: -	case LIBSYSCALLS_ARCH_MIPS_N64_LE: -	case LIBSYSCALLS_ARCH_MIPS_N64_BE: -	case LIBSYSCALLS_ARCH_PARISC_32: /* https://www.ece.lsu.edu/ee4720/doc/pa1.1.pdf (page 26) */ -	case LIBSYSCALLS_ARCH_PARISC_64: -	case LIBSYSCALLS_ARCH_POWERPC_32_LE: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ -	case LIBSYSCALLS_ARCH_POWERPC_32_BE: -	case LIBSYSCALLS_ARCH_POWERPC_64_LE: /* https://www.slac.stanford.edu/exp/npa/software/eabi_app.pdf */ -	case LIBSYSCALLS_ARCH_POWERPC_64_BE: -	case LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE: -	case LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE: -	case LIBSYSCALLS_ARCH_POWERPC_SPU_LE: -	case LIBSYSCALLS_ARCH_POWERPC_SPU_BE: -	case LIBSYSCALLS_ARCH_S390_32: /* https://refspecs.linuxbase.org/ELF/zSeries/lzsabi0_s390.html */ -	case LIBSYSCALLS_ARCH_S390_64: -	case LIBSYSCALLS_ARCH_SPARC_32: /* https://www.gaisler.com/doc/sparcv8.pdf (page 46) */ -	case LIBSYSCALLS_ARCH_SPARC_64_LE: /* https://static.lwn.net/images/pdf/LDD3/ch11.pdf */ -	case LIBSYSCALLS_ARCH_SPARC_64_BE: -	case LIBSYSCALLS_ARCH_XTENSA_LE: /* https://loboris.eu/ESP32/Xtensa_lx%20Overview%20handbook.pdf (page 97) */ -	case LIBSYSCALLS_ARCH_XTENSA_BE: -	case LIBSYSCALLS_ARCH_MICROBLAZE_64_LE: /* https://www.amd.com/content/dam/xilinx/support/documents/sw_manuals/xilinx2021_2/ug984-vivado-microblaze-ref.pdf */ -	case LIBSYSCALLS_ARCH_MICROBLAZE_64_BE: -		maxalign = 64; -		break; - -	default: +	if ((size_t)arch >= ELEMSOF(aligntable)) +		return LIBSYSCALLS_E_ARCHNOSUP; +	maxalign = aligntable[(size_t)arch]; +	if (!maxalign)  		return LIBSYSCALLS_E_ARCHNOSUP; -	} -	if (width_in_bits & (width_in_bits - 1) || width_in_bits & 7 || width_in_bits > 64) +	if (IS_NOT_2POW(width_in_bits) || width_in_bits % 8 || width_in_bits > 64)  		return LIBSYSCALLS_E_NOSUCHTYPE;  	*alignment_out = width_in_bits < maxalign ? width_in_bits : maxalign; diff --git a/libsyscalls_get_struct_description.c b/libsyscalls_get_struct_description.c index 4d9ce68..cc1c42b 100644 --- a/libsyscalls_get_struct_description.c +++ b/libsyscalls_get_struct_description.c @@ -41,8 +41,9 @@ struct padding {  static enum libsyscalls_error -get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, const void *data, -                       size_t data_size, struct libsyscalls_structure_description **description_out, size_t *extra_sizep); +get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                       enum libsyscalls_datatype datatype, const void *data, size_t data_size, +                       struct libsyscalls_structure_description **description_out, size_t *extra_sizep);  static struct libsyscalls_structure_description * @@ -74,7 +75,8 @@ create_pad_description(enum libsyscalls_os os, enum libsyscalls_arch arch, unsig  static enum libsyscalls_error -shift_fields(enum libsyscalls_os os, enum libsyscalls_arch arch, struct libsyscalls_structure_description *description, +shift_fields(enum libsyscalls_os os, enum libsyscalls_arch arch, +             struct libsyscalls_structure_description *description,               const struct padding *paddings, size_t npaddings)  {  	signed short int shift, map[description->num_fields], abs, rel; @@ -201,22 +203,28 @@ move_in_subdescriptions(char *buffer, size_t *offsetp, struct libsyscalls_struct  static unsigned long long int  read_field(const void *data, size_t data_size, const size_t *field_offsets, -           const struct libsyscalls_structure_description *description, unsigned short int i, int *undetermined_out) +           const struct libsyscalls_structure_description *description, +           unsigned short int i, int *undetermined_out)  {  	size_t offset, width, bits = 0; -	enum libsyscalls_datatype type = description->fields[i].type; -	const struct libsyscalls_datatype_description *type_description = description->fields[i].type_description.nonstructure; +	enum libsyscalls_datatype type; +	const struct libsyscalls_datatype_description *type_description;  	unsigned splits, expected_splits, end;  	unsigned long long int result = 0, subresult;  	signed long long int sresult;  	int is_negative; +	type = description->fields[i].type; +	type_description = description->fields[i].type_description.nonstructure; +  	if ((type & LIBSYSCALLS_TYPEBITSMASK) != LIBSYSCALLS_TYPEBITS_SCALAR)  		abort();  	type ^= LIBSYSCALLS_TYPEBITS_SCALAR; -	if (type >= LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES && type < LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES) +	if (type >= LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES && +	    type < LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES)  		splits = LIBSYSCALLS_GET_SECTION_FRACTION(type_description->section); -	else if (type >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS && type < LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS) +	else if (type >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS && +	         type < LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS)  		splits = 1;  	else  		abort(); @@ -229,9 +237,11 @@ read_field(const void *data, size_t data_size, const size_t *field_offsets,  		if ((type & LIBSYSCALLS_TYPEBITSMASK) != LIBSYSCALLS_TYPEBITS_SCALAR)  			abort();  		type ^= LIBSYSCALLS_TYPEBITS_SCALAR; -		if (type >= LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES && type < LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES) +		if (type >= LIBSYSCALLS_TYPEOFFSET_SPLIT_PRIMITIVES && +		    type < LIBSYSCALLS_TYPEOFFSET_COMPOSITE_PRIMITIVES)  			splits = LIBSYSCALLS_GET_SECTION_FRACTION(type_description->section); -		else if (type >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS && type < LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS) +		else if (type >= LIBSYSCALLS_TYPEOFFSET_UNANNOTATED_NUMERICALS && +		         type < LIBSYSCALLS_TYPEOFFSET_FIXED_ARRAYS)  			splits = 1;  		else  			abort(); @@ -258,7 +268,8 @@ read_field(const void *data, size_t data_size, const size_t *field_offsets,  	}  	if (type_description->is_signed) { -		if (libsyscalls_parse_signed_integer(result, type_description->sign_representation, bits, &result, &is_negative)) +		if (libsyscalls_parse_signed_integer(result, type_description->sign_representation, +		                                     bits, &result, &is_negative))  			abort();  		if (is_negative) {  #if LLONG_MIN == -LLONG_MAX @@ -397,9 +408,10 @@ adjust_for_struct(enum libsyscalls_os os, enum libsyscalls_arch arch, const void  	unsigned short int field;  	enum libsyscalls_error r; -	r = get_struct_description(os, arch, description->fields[i].type, &((const char *)data)[field_offsets[i]], -				   data_size < field_offsets[i] ? 0 : data_size - field_offsets[i], -				   &struct_description, extra_sizep); +	r = get_struct_description(os, arch, description->fields[i].type, +	                           &((const char *)data)[field_offsets[i]], +	                           USAT_MINUS(data_size, field_offsets[i]), +	                           &struct_description, extra_sizep);  	if (r)  		return r; @@ -418,7 +430,7 @@ adjust_for_struct(enum libsyscalls_os os, enum libsyscalls_arch arch, const void  			if (field > i)  				abort();  		set_subsize: -			uvalue = read_field(data, data_size, field_offsets, description, i, undetermined_sizep); +			uvalue = read_field(data, data_size, field_offsets, description, field, undetermined_sizep);  			/* TODO set `*subsizep` to `uvalue` (may overflow) */  		}  		if (!struct_description->array_size) @@ -442,7 +454,7 @@ adjust_for_struct(enum libsyscalls_os os, enum libsyscalls_arch arch, const void  static enum libsyscalls_error  adjust_for_fields(enum libsyscalls_os os, enum libsyscalls_arch arch, const void *data, size_t data_size, -		  struct padding **paddingsp, size_t *npaddingsp, size_t *paddings_sizep, +                  struct padding **paddingsp, size_t *npaddingsp, size_t *paddings_sizep,                    struct libsyscalls_structure_description *description, int dont_align_fields, size_t *extra_sizep)  {  	size_t field_offsets[description->num_fields]; @@ -494,8 +506,10 @@ adjust_for_fields(enum libsyscalls_os os, enum libsyscalls_arch arch, const void  static enum libsyscalls_error -get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, const void *data, -                       size_t data_size, struct libsyscalls_structure_description **description_out, size_t *extra_sizep) +get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                       enum libsyscalls_datatype datatype, const void *data, size_t data_size, +                       struct libsyscalls_structure_description **description_out, +                       size_t *extra_sizep)  {  	unsigned char fill_is_known;  	unsigned short int array_size; @@ -508,7 +522,7 @@ get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum  	size_t npaddings = 0, paddings_size = 0;  	struct padding *paddings = NULL; -	if ((unsigned)datatype & ~(LIBSYSCALLS_TYPEBITSMASK | (LIBSYSCALLS_TYPEBITSMASK - 1U))) +	if ((unsigned)datatype & ~SET_MASK_TRAIL(LIBSYSCALLS_TYPEBITSMASK))  		return LIBSYSCALLS_E_INVAL;  	datatype ^= class = datatype & LIBSYSCALLS_TYPEBITSMASK; @@ -577,7 +591,8 @@ get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum  #define CASE(UPPERCASE, LOWERCASE)\  	case LIBSYSCALLS_OS_##UPPERCASE:\ -		r = fix_##LOWERCASE##_struct_description(arch, datatype, class, data, data_size, description);\ +		r = fix_##LOWERCASE##_struct_description(arch, datatype, class,\ +		                                         data, data_size, description);\  		break  	switch ((int)os) { @@ -613,8 +628,10 @@ fail:  enum libsyscalls_error -libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, enum libsyscalls_datatype datatype, -                                   const void *data, size_t data_size, struct libsyscalls_structure_description **description_out) +libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch arch, +                                   enum libsyscalls_datatype datatype, +                                   const void *data, size_t data_size, +                                   struct libsyscalls_structure_description **description_out)  {  	struct libsyscalls_structure_description *description, *new;  	size_t extra_size = 0, size, nalign, salign, align; @@ -637,7 +654,7 @@ libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch  	size = offsetof(struct libsyscalls_structure_description, fields);  	size += (size_t)description->num_fields * sizeof(*description->fields); -	size += (align - (size & (align - 1))) & (align - 1); +	size += ALIGNMENT_ADJUSTMENT(size, align);  	new = realloc(description, size + extra_size);  	if (!new) { @@ -647,9 +664,11 @@ libsyscalls_get_struct_description(enum libsyscalls_os os, enum libsyscalls_arch  	}  	description = new; -	move_in_subdescriptions((void *)description, &size, description, nalign == align, salign == align); +	move_in_subdescriptions((void *)description, &size, description, +	                        nalign == align, salign == align);  	if (nalign != align || salign != align) -		move_in_subdescriptions((void *)description, &size, description, nalign != align, salign != align); +		move_in_subdescriptions((void *)description, &size, description, +		                        nalign != align, salign != align);  	*description_out = description;  	return LIBSYSCALLS_E_OK; diff --git a/libsyscalls_get_syscall_display_info.c b/libsyscalls_get_syscall_display_info.c index add65e2..f18834c 100644 --- a/libsyscalls_get_syscall_display_info.c +++ b/libsyscalls_get_syscall_display_info.c @@ -43,146 +43,18 @@ trailing_zeroes(unsigned long long int x)  } -#define USE_INTERPOLATION_SEARCH /* TODO validate; should be configurable and (if good) default on systems with intrinsic divsion */ -#ifndef USE_INTERPOLATION_SEARCH - - -PURE_FUNCTION -static int -signed_named_number_cmp(const void *a_, const void *b_) -{ -	const struct libsyscalls_named_number *a = a_, *b = b_; -	return a->number.s < b->number.s ? -1 : a->number.s > b->number.s; -} - - -PURE_FUNCTION -static int -unsigned_named_number_cmp(const void *a_, const void *b_) -{ -	const struct libsyscalls_named_number *a = a_, *b = b_; -	return a->number.u < b->number.u ? -1 : a->number.u > b->number.u; -} - - -#else - - -/* convertion to unsigned is a modulo (unsigned maximum + 1) operation */ -#define DIFF(TYPE, A, B) ((unsigned TYPE)(A) - (unsigned TYPE)(B)) - -#define INTERPOL_SEARCH(KEY, BASE, N, READ)\ -	do {\ -		double guess_d;\ -		unsigned long long int guess;\ -		size_t h = (N);\ -		\ -		if (!h--)\ -			return NULL;\ -		\ -		if ((KEY) <= READ((BASE), 0))\ -			return (KEY) == READ((BASE), 0) ? (BASE) : NULL;\ -		if ((KEY) >= READ((BASE), h))\ -			return (KEY) == READ((BASE), h) ? (BASE) : NULL;\ -		if (READ((BASE), 0) == READ((BASE), h))\ -			return NULL;\ -		\ -		guess = DIFF(long long int, (KEY), READ((BASE), 0));\ -		if (h > ULLONG_MAX / guess)\ -			goto use_double;\ -		\ -		for (;;) {\ -			guess = DIFF(long long int, (KEY), READ((BASE), 0));\ -			guess *= (unsigned long long int)h;\ -			guess /= DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ -			\ -			if (READ((BASE), guess) < (KEY)) {\ -				h -= guess += 1;\ -				(BASE) = &(BASE)[guess];\ -			} else if (READ((BASE), guess) > (KEY)) {\ -				h -= guess -= 1;\ -			} else {\ -				return &(BASE)[guess];\ -			}\ -			\ -			if (READ((BASE), 0) == READ((BASE), h))\ -				return (KEY) == READ((BASE), 0) ? (BASE) : NULL;\ -			if ((KEY) < READ((BASE), 0))\ -				return NULL;\ -			if ((KEY) > READ((BASE), h))\ -				return NULL;\ -		}\ -		\ -	use_double:\ -		for (;;) {\ -			guess = DIFF(long long int, (KEY), READ((BASE), 0));\ -			guess_d = (double)guess * (double)h;\ -			guess = DIFF(long long int, READ((BASE), h), READ((BASE), 0));\ -			guess_d /= (double)guess;\ -			guess = (unsigned long long int)guess_d;\ -			\ -			if (READ((BASE), guess) < (KEY)) {\ -				h -= guess += 1;\ -				(BASE) = &(BASE)[guess];\ -			} else if (READ((BASE), guess) > (KEY)) {\ -				h -= guess -= 1;\ -			} else {\ -				return &(BASE)[guess];\ -			}\ -			\ -			if (READ((BASE), 0) == READ((BASE), h))\ -				return (KEY) == READ((BASE), 0) ? (BASE) : NULL;\ -			if ((KEY) < READ((BASE), 0))\ -				return NULL;\ -			if ((KEY) > READ((BASE), h))\ -				return NULL;\ -		}\ -	} while (0) - - -PURE_FUNCTION -static const struct libsyscalls_named_number * -interpol_search_signed_named_number(signed long long int key, const struct libsyscalls_named_number *base, size_t n) -{ -#define X(ARR, I) ((ARR)[I].number.s) -	INTERPOL_SEARCH(key, base, n, X); -#undef X -} - - -PURE_FUNCTION -static const struct libsyscalls_named_number * -interpol_search_unsigned_named_number(unsigned long long int key, const struct libsyscalls_named_number *base, size_t n) -{ -#define X(ARR, I) ((ARR)[I].number.u) -	INTERPOL_SEARCH(key, base, n, X); -#undef X -} - -#undef DIFF - - -#endif - -  static const char * -extract_signal(enum libsyscalls_os os, enum libsyscalls_arch arch, unsigned long long int *valuep, char *fallback_out) +extract_signal(enum libsyscalls_os os, enum libsyscalls_arch arch, +               unsigned long long int *valuep, char *fallback_out)  {  	const struct libsyscalls_named_number *signals, *found;  	size_t nsignals; -	struct libsyscalls_named_number key = {.number.u = *valuep};  	int is_signed;  	if (libsyscalls_get_signals(os, arch, &signals, &nsignals, &is_signed))  		return NULL; -#ifndef USE_INTERPOLATION_SEARCH -	found = bsearch(&key, signals, nsignals, sizeof(key), -	                is_signed ? &signed_named_number_cmp : &unsigned_named_number_cmp); -#else -	found = is_signed ? interpol_search_signed_named_number(key.number.s, signals, nsignals) -	                  : interpol_search_unsigned_named_number(key.number.u, signals, nsignals); -#endif +	found = libsyscalls_find_named_number(*valuep, is_signed, signals, nsignals);  	if (!found)  		return NULL; @@ -196,11 +68,11 @@ extract_signal(enum libsyscalls_os os, enum libsyscalls_arch arch, unsigned long  static struct libsyscalls_syscall_display_info *  build_syscall_display_info(void *data, size_t data_size, size_t data_align,                             libsyscalls_symbol_printer_function **funcs, -			   const struct libsyscalls_syscall_abi *syscall, int nargs, int nsyms) +			   const struct libsyscalls_syscall_abi *syscall, +                           size_t nargs, size_t nsyms)  {  	struct libsyscalls_syscall_display_info *ret; -	size_t size, dataoff, paramoff; -	int i; +	size_t i, size, dataoff, paramoff;  	size = sizeof(*ret); @@ -209,14 +81,14 @@ build_syscall_display_info(void *data, size_t data_size, size_t data_align,  		size += 1;  	}  	dataoff = size; -	size += (size_t)nsyms * data_size; +	size += nsyms * data_size;  	if (size & (alignof(struct libsyscalls_syscall_type_info) - 1)) {  		size |= alignof(struct libsyscalls_syscall_type_info) - 1;  		size += 1;  	}  	paramoff = size; -	size += (size_t)(nargs + 1) * sizeof(*ret->params); +	size += (nargs + 1U) * sizeof(*ret->params);  	ret = calloc(1, size);  	if (!ret) @@ -231,8 +103,8 @@ build_syscall_display_info(void *data, size_t data_size, size_t data_align,  		ret->params[i].type = syscall->parameters_types[i];  		if (funcs[i]) {  			ret->params[i].function = funcs[i]; -			ret->params[i].data = (void *)&((char *)ret)[dataoff + (size_t)nsyms * data_size]; -			memcpy(ret->params[i].data, &((char *)data)[(size_t)i * data_size], data_size); +			ret->params[i].data = (void *)&((char *)ret)[dataoff + nsyms * data_size]; +			memcpy(ret->params[i].data, &((char *)data)[i * data_size], data_size);  			nsyms++;  		}  	} @@ -240,8 +112,8 @@ build_syscall_display_info(void *data, size_t data_size, size_t data_align,  	ret->retvalue->expect_zero = syscall->expect_zero;  	if (funcs[i]) {  		ret->retvalue->function = funcs[i]; -		ret->retvalue->data = (void *)&((char *)ret)[dataoff + (size_t)nsyms * data_size]; -		memcpy(ret->retvalue->data, &((char *)data)[(size_t)i * data_size], data_size); +		ret->retvalue->data = (void *)&((char *)ret)[dataoff + nsyms * data_size]; +		memcpy(ret->retvalue->data, &((char *)data)[i * data_size], data_size);  	}  	return ret; diff --git a/libsyscalls_get_syscall_range.c b/libsyscalls_get_syscall_range.c index eb9b11e..0fd2554 100644 --- a/libsyscalls_get_syscall_range.c +++ b/libsyscalls_get_syscall_range.c @@ -5,7 +5,8 @@  #include "generated/get_syscall_range.c"  enum libsyscalls_error -libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch, long long int *min_out, long long int *max_out) +libsyscalls_get_syscall_range(enum libsyscalls_os os, enum libsyscalls_arch arch, +                              long long int *min_out, long long int *max_out)  {  	long long int discarded; diff --git a/libsyscalls_parse_signed_integer.c b/libsyscalls_parse_signed_integer.c index da6f078..635000d 100644 --- a/libsyscalls_parse_signed_integer.c +++ b/libsyscalls_parse_signed_integer.c @@ -3,7 +3,8 @@  enum libsyscalls_error -libsyscalls_parse_signed_integer(unsigned long long int value_in, enum libsyscalls_datatype_sign_representation representation, +libsyscalls_parse_signed_integer(unsigned long long int value_in, +                                 enum libsyscalls_datatype_sign_representation representation,                                   size_t bits, unsigned long long int *value_out, int *negative_out)  {  	unsigned long long int value = value_in, mask; diff --git a/libsyscalls_section_value.c b/libsyscalls_section_value.c index dc86cca..6cdb787 100644 --- a/libsyscalls_section_value.c +++ b/libsyscalls_section_value.c @@ -4,9 +4,11 @@  enum libsyscalls_error  libsyscalls_section_value(unsigned long long int value_in, size_t bits, -                          enum libsyscalls_datatype_section section, unsigned long long int *value_out) +                          enum libsyscalls_datatype_section section, +                          unsigned long long int *value_out)  {  	unsigned long long int value = value_in, mask, shift; +	size_t hbits;  	if (bits > sizeof(value) / sizeof(char) * CHAR_BIT ||  	    bits & (size_t)(LIBSYSCALLS_GET_SECTION_FRACTION(section) - 1U)) @@ -43,14 +45,18 @@ libsyscalls_section_value(unsigned long long int value_in, size_t bits,  		break;  	case LIBSYSCALLS_SECTION_OUTER_HALF: /* 0xFFFF00000000FFFF */ -		value = ((value & (mask << (bits + bits / 2))) >> bits) | (value & (mask >> (bits / 2))); +		hbits = bits / 2; +		value = ((value & (mask << (bits + hbits))) >> bits) +		      | (value & (mask >> hbits));  		break;  	case LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF: /* 0xFFFF0000FFFF0000 */  		value >>= bits / 2;  		/* fall through */  	case LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF: /* 0x0000FFFF0000FFFF */ -		value = ((value & (mask << (bits / 2)) & ~mask) >> (bits / 2)) | (value & (mask >> (bits / 2))); +		hbits = bits / 2; +		value = ((value & (mask << hbits) & ~mask) >> hbits) +		      | (value & (mask >> hbits));  		break;  	case LIBSYSCALLS_SECTION_ODD_BYTES_AS_HALF: /* 0xFF00FF00FF00FF00 */ diff --git a/libsyscalls_unsection_value.c b/libsyscalls_unsection_value.c index 6cd797e..fb0f1fe 100644 --- a/libsyscalls_unsection_value.c +++ b/libsyscalls_unsection_value.c @@ -4,7 +4,8 @@  enum libsyscalls_error  libsyscalls_unsection_value(unsigned long long int value_in, size_t bits, -                            enum libsyscalls_datatype_section section, unsigned long long int *value_out) +                            enum libsyscalls_datatype_section section, +                            unsigned long long int *value_out)  {  	unsigned long long int value = value_in, mask, shift; @@ -15,8 +16,6 @@ libsyscalls_unsection_value(unsigned long long int value_in, size_t bits,  	switch (section) {  	case LIBSYSCALLS_SECTION_UNDETERMINED:  	case LIBSYSCALLS_SECTION_WHOLE: /* 0xFFFFFFFFFFFFFFFF */ -		break; -  	case LIBSYSCALLS_SECTION_LOWER_HALF: /* 0x00000000FFFFFFFF */  	case LIBSYSCALLS_SECTION_LOWER_QUARTER: /* 0x000000000000FFFF */  		break; @@ -40,17 +39,20 @@ libsyscalls_unsection_value(unsigned long long int value_in, size_t bits,  	case LIBSYSCALLS_SECTION_OUTER_HALF: /* 0xFFFF00000000FFFF */  		mask = (1ULL << (bits / 2)) - 1ULL; -		value = ((value & ~mask) << bits) | (value & mask); +		value = ((value & ~mask) << bits) +		      | (value & mask);  		break;  	case LIBSYSCALLS_SECTION_EVEN_QUARTERS_AS_HALF: /* 0x0000FFFF0000FFFF */  		mask = (1ULL << (bits / 2)) - 1ULL; -		value = ((value & ~mask) << (bits / 2)) | (value & mask); +		value = ((value & ~mask) << (bits / 2)) +		      | (value & mask);  		break;  	case LIBSYSCALLS_SECTION_ODD_QUARTERS_AS_HALF: /* 0xFFFF0000FFFF0000 */  		mask = (1ULL << (bits / 2)) - 1ULL; -		value = ((value & ~mask) << (bits / 2)) | (value & mask); +		value = ((value & ~mask) << (bits / 2)) +		      | (value & mask);  		value <<= bits / 2;  		break; diff --git a/linux/symbols.c b/linux/symbols.c index cbfb661..5cc848d 100644 --- a/linux/symbols.c +++ b/linux/symbols.c @@ -275,7 +275,7 @@ get_linux_syscall_display_info(enum libsyscalls_arch arch, const struct libsysca  {  	LIBSYSCALLS_SYMBOL_PRINTER_DATA *data;  	libsyscalls_symbol_printer_function **funcs; -	int i, nargs, nsyms; +	size_t i, nargs, nsyms;  	size_t data_size = offsetof(LIBSYSCALLS_SYMBOL_PRINTER_DATA, buf);  	size_t data_align = alignof(LIBSYSCALLS_SYMBOL_PRINTER_DATA);  	size_t bufspace, bufspace1, bufspace2; @@ -42,6 +42,9 @@ p tests/os-dependent-arrays  p tests/os-dependent-integers  await +t tests/error-search +t tests/signal-search +  # TODO test libsyscalls_get_struct_description  # TODO test libsyscalls_get_struct_display_info diff --git a/tests/archinfo b/tests/archinfo index 5034766..334571e 100644 --- a/tests/archinfo +++ b/tests/archinfo @@ -1,19 +1,22 @@  # -*- sh -*-  # See LICENSE file for copyright and license details. -printf '%s\n' "$archinfo" | grep '^AMD64 8 64 64 Little TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^AMD64_X32 8 32 32 Little TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^M68K 8 32 32 Big TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^PARISC_32 8 32 32 Big TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^PARISC_64 8 64 64 Big TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^SPARC_32 8 32 32 Big TWOS_COMPLEMENT' >/dev/null -printf '%s\n' "$archinfo" | grep '^I386 8 32 32 Little TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^AMD64 8 64 64 64 Little TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^AMD64_X32 8 32 32 64 Little TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^M68K 8 32 32 16 Big TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^PARISC_32 8 32 32 64 Big TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^PARISC_64 8 64 64 64 Big TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^SPARC_32 8 32 32 64 Big TWOS_COMPLEMENT' >/dev/null +printf '%s\n' "$archinfo" | grep '^I386 8 32 32 32 Little TWOS_COMPLEMENT' >/dev/null  test $(getbytesize AMD64) = 8  test $(getbytesize I386) = 8  test $(getaddrsize I386) = 32  test $(getaddrsize AMD64) = 64  test $(getsizesize AMD64) = 64  test $(getsizesize I386) = 32 +test $(getintalign I386) = 32 +test $(getintalign AMD64) = 64 +test $(getintalign M68K) = 16  test $(getendian I386) = Little  test $(getendian AMD64) = Little  test $(getendian M68K) = Big diff --git a/tests/error-search b/tests/error-search new file mode 100644 index 0000000..dd71bd9 --- /dev/null +++ b/tests/error-search @@ -0,0 +1,13 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +for os in $(getnamelist OS); do +	osn=$(getnum OS $os) +	for arch in $(getnamelist ARCH); do +		archn=$(getnum ARCH $arch) +		if issupported $os $arch; then +			p tests/run test-search.tu errors $osn $archn $os $arch +		fi +	done +	await +done diff --git a/tests/load-archinfo b/tests/load-archinfo index e5413b4..8e6b2a6 100644 --- a/tests/load-archinfo +++ b/tests/load-archinfo @@ -33,9 +33,12 @@ getaddrsize () {  getsizesize () {      printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 4  } -getendian () { +getintalign () {      printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 5  } -getsign () { +getendian () {      printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 6  } +getsign () { +    printf '%s\n' "$archinfo" | grep "^$1 " | cut -d ' ' -f 7 +} diff --git a/tests/run b/tests/run new file mode 100644 index 0000000..c9bd4b6 --- /dev/null +++ b/tests/run @@ -0,0 +1,4 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +"$@" diff --git a/tests/signal-search b/tests/signal-search new file mode 100644 index 0000000..b4afc49 --- /dev/null +++ b/tests/signal-search @@ -0,0 +1,13 @@ +# -*- sh -*- +# See LICENSE file for copyright and license details. + +for os in $(getnamelist OS); do +	osn=$(getnum OS $os) +	for arch in $(getnamelist ARCH); do +		archn=$(getnum ARCH $arch) +		if issupported $os $arch; then +			p tests/run test-search.tu signals $osn $archn $os $arch +		fi +	done +	await +done diff --git a/testutil/get-datatype-description.c b/testutil/get-datatype-description.c index 9c26626..b3d2637 100644 --- a/testutil/get-datatype-description.c +++ b/testutil/get-datatype-description.c @@ -31,7 +31,7 @@ main(int argc, char **argv)  	err = libsyscalls_get_datatype_description((enum libsyscalls_os)os, (enum libsyscalls_arch)arch,  	                                           (enum libsyscalls_datatype)type, &desc);  	if (err) { -		fprintf(stderr, "libsyscalls_get_datatype_description %s %s %s: ", argv[4], argv[5], argv[6]); +		fprintf(stderr, "get-datatype-description %s %s %s: ", argv[4], argv[5], argv[6]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/get-integer-alignment.c b/testutil/get-integer-alignment.c index 7d0fcc3..cb67eef 100644 --- a/testutil/get-integer-alignment.c +++ b/testutil/get-integer-alignment.c @@ -30,7 +30,7 @@ main(int argc, char **argv)  	err = libsyscalls_get_integer_alignment((enum libsyscalls_os)os, (enum libsyscalls_arch)arch,  	                                        (unsigned)width, &alignment);  	if (err) { -		fprintf(stderr, "libsyscalls_get_integer_alignment %s %s %s: ", argv[4], argv[5], argv[3]); +		fprintf(stderr, "get-integer-alignment %s %s %s: ", argv[4], argv[5], argv[3]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/get-signals.c b/testutil/get-signals.c index 54fcac4..2a2ea03 100644 --- a/testutil/get-signals.c +++ b/testutil/get-signals.c @@ -34,7 +34,7 @@ main(int argc, char **argv)  	} else if (err == LIBSYSCALLS_E_NOSIGNALS) {  		return 0;  	} else if (err) { -		fprintf(stderr, "test-get-syscall-signals %s %s: ", argv[3], argv[4]); +		fprintf(stderr, "get-signals %s %s: ", argv[3], argv[4]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/get-syscall-errors.c b/testutil/get-syscall-errors.c index a5923f4..0870e07 100644 --- a/testutil/get-syscall-errors.c +++ b/testutil/get-syscall-errors.c @@ -34,7 +34,7 @@ main(int argc, char **argv)  	} else if (err == LIBSYSCALLS_E_NOERRORS) {  		return 0;  	} else if (err) { -		fprintf(stderr, "test-get-syscall-errors %s %s: ", argv[3], argv[4]); +		fprintf(stderr, "get-syscall-errors %s %s: ", argv[3], argv[4]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/get-syscall-range.c b/testutil/get-syscall-range.c index 2c40b71..a199091 100644 --- a/testutil/get-syscall-range.c +++ b/testutil/get-syscall-range.c @@ -31,7 +31,7 @@ main(int argc, char **argv)  		printf("max: x\n");  		return 0;  	} else if (err) { -		fprintf(stderr, "test-get-syscall-range %s %s: ", argv[3], argv[4]); +		fprintf(stderr, "get-syscall-range %s %s: ", argv[3], argv[4]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/is-datatype-struct.c b/testutil/is-datatype-struct.c index e9eb2ef..ffaff5f 100644 --- a/testutil/is-datatype-struct.c +++ b/testutil/is-datatype-struct.c @@ -32,7 +32,7 @@ main(int argc, char **argv)  	if (err == LIBSYSCALLS_E_ISSTRUCT) {  		return 0;  	} else if (err) { -		fprintf(stderr, "libsyscalls_get_datatype_description %s %s %s: ", argv[4], argv[5], argv[6]); +		fprintf(stderr, "is-datatype-struct %s %s %s: ", argv[4], argv[5], argv[6]);  		libsyscalls_perror(NULL, err);  		return 2;  	} diff --git a/testutil/make-signed.c b/testutil/make-signed.c index 7cd0134..5ac7338 100644 --- a/testutil/make-signed.c +++ b/testutil/make-signed.c @@ -42,6 +42,7 @@ main(int argc, char **argv)  		printf("inval\n");  		goto out;  	} else if (err) { +		fprintf(stderr, "make-signed %s %s %s: ", argv[1], argv[2], argv[3]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/parse-signed.c b/testutil/parse-signed.c index 0fea405..f5e6d35 100644 --- a/testutil/parse-signed.c +++ b/testutil/parse-signed.c @@ -40,6 +40,7 @@ main(int argc, char **argv)  		printf("inval\n");  		goto out;  	} else if (err) { +		fprintf(stderr, "parse-signed %s %s %s: ", argv[1], argv[2], argv[3]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/section-value.c b/testutil/section-value.c index b4c0304..bb86b8d 100644 --- a/testutil/section-value.c +++ b/testutil/section-value.c @@ -37,6 +37,7 @@ main(int argc, char **argv)  		printf("inval\n");  		goto out;  	} else if (err) { +		fprintf(stderr, "section-value %s %s %s: ", argv[1], argv[2], argv[3]);  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/test-search.c b/testutil/test-search.c new file mode 100644 index 0000000..93d6d03 --- /dev/null +++ b/testutil/test-search.c @@ -0,0 +1,114 @@ +/* See LICENSE file for copyright and license details. */ +#include "../libsyscalls.h" + +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(__clang__) +# pragma clang diagnostic ignored "-Wunsafe-buffer-usage" /* clang is just being silly */ +#endif + + +static struct libsyscalls_named_number not_found; +static size_t not_found_count = 0; +static char **argv; + +static void +check(unsigned long long int key, const struct libsyscalls_named_number *base, size_t n, int is_signed) +{ +	static int first = 1; + +	const struct libsyscalls_named_number *found; +	found = libsyscalls_find_named_number(key, is_signed, base, n); +	if (found) { +		if (first) +			not_found.number.u = key + 1; +		if (found->number.u != key) { +			fprintf(stderr, "test-search %s %s %s: found incorrect element: %llu instead of %llu\n", +			        argv[1], argv[4], argv[5], found->number.u, key); +			exit(1); +		} +	} else { +		if (first) { +			fprintf(stderr, "test-search %s %s %s: did not find first element\n", argv[1], argv[4], argv[5]); +			exit(1); +		} +		not_found.number.u = key; +		not_found_count += 1; +	} + +	first = 0; +} + + +int +main(int argc, char **argv_) +{ +	int os, arch, search_singals, is_signed; +	enum libsyscalls_error err; +	const struct libsyscalls_named_number *base, *min, *max; +	unsigned long long int ukey; +	signed long long int skey; +	size_t n, expected_not_found_count; + +	argv = argv_; + +	if (argc != 6) { +	usage: +		fprintf(stderr, "usage error\n"); +		return 1; +	} + +	if (!strcmp(argv[1], "signals")) +		search_singals = 1; +	else if (!strcmp(argv[1], "errors")) +		search_singals = 0; +	else +		goto usage; +	os = atoi(argv[2]); +	arch = atoi(argv[3]); + +	if (search_singals) +		err = libsyscalls_get_signals((enum libsyscalls_os)os, (enum libsyscalls_arch)arch, &base, &n, &is_signed); +	else +		err = libsyscalls_get_syscall_errors((enum libsyscalls_os)os, (enum libsyscalls_arch)arch, &base, &n, &is_signed); +	if (err) { +		fprintf(stderr, "test-search %s %s %s: ", argv[1], argv[4], argv[5]); +		libsyscalls_perror(NULL, err); +		return 1; +	} + +	if (!n) +		return 0; + +	min = &base[0]; +	max = &base[n - 1]; + +	if (is_signed) { +		skey = min->number.s; +		do { +			check(*(unsigned long long int *)&skey, base, n, is_signed); +		} while (skey++ != max->number.s); +		expected_not_found_count = (size_t)((unsigned long long int)max->number.s - +		                                    (unsigned long long int)min->number.s - +		                                    (unsigned long long int)n + 1); +	} else { +		ukey = min->number.u; +		do { +			check(ukey, base, n, is_signed); +		} while (ukey++ != max->number.u); +		expected_not_found_count = (size_t)(max->number.u - min->number.u - (unsigned long long int)n + 1); +	} + +	if (not_found.number.u == max->number.u) { +		fprintf(stderr, "test-search %s %s %s: did not find last element\n", argv[1], argv[4], argv[5]); +		return 1; +	} +	if (not_found_count != expected_not_found_count) { +		fprintf(stderr, "test-search %s %s %s: did not find all elements\n", argv[1], argv[4], argv[5]); +		return 1; +	} + +	return 0; +} diff --git a/testutil/to-tracee-endian.c b/testutil/to-tracee-endian.c index 4346883..ba97a95 100644 --- a/testutil/to-tracee-endian.c +++ b/testutil/to-tracee-endian.c @@ -78,6 +78,11 @@ main(int argc, char **argv)  		free(data);  		goto out;  	} else if (err) { +	fail: +		fprintf(stderr, "to-tracee-endian"); +		for (argv = &argv[1 - argc]; *argv; argv++) +			fprintf(stderr, " %s", *argv); +		fprintf(stderr, ": ");  		libsyscalls_perror(NULL, err);  		return 1;  	} @@ -90,8 +95,7 @@ main(int argc, char **argv)  		free(data);  		goto out;  	} else if (err) { -		libsyscalls_perror(NULL, err); -		return 1; +		goto fail;  	}  	make_hex(text1, data, datasize); diff --git a/testutil/to-tracer-endian.c b/testutil/to-tracer-endian.c index 53cb380..668499f 100644 --- a/testutil/to-tracer-endian.c +++ b/testutil/to-tracer-endian.c @@ -69,6 +69,10 @@ main(int argc, char **argv)  		printf("inval\n");  		goto out;  	} else if (err) { +		fprintf(stderr, "to-tracer-endian"); +		for (argv = &argv[1 - argc]; *argv; argv++) +			fprintf(stderr, " %s", *argv); +		fprintf(stderr, ": ");  		libsyscalls_perror(NULL, err);  		return 1;  	} diff --git a/testutil/unsection-value.c b/testutil/unsection-value.c index 9c85b3b..9c7e68a 100644 --- a/testutil/unsection-value.c +++ b/testutil/unsection-value.c @@ -37,6 +37,7 @@ main(int argc, char **argv)  		printf("inval\n");  		goto out;  	} else if (err) { +		fprintf(stderr, "unsection-value %s %s %s: ", argv[1], argv[2], argv[3]);  		libsyscalls_perror(NULL, err);  		return 1;  	} | 
