summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--LICENSE2
-rw-r--r--Makefile2
-rw-r--r--common.h102
-rw-r--r--config.mk13
-rw-r--r--libsyscalls.h826
-rw-r--r--libsyscalls_find_named_number.c141
-rw-r--r--libsyscalls_get_datatype_description.c36
-rw-r--r--libsyscalls_get_integer_alignment.c69
-rw-r--r--libsyscalls_get_struct_description.c69
-rw-r--r--libsyscalls_get_syscall_display_info.c152
-rw-r--r--libsyscalls_get_syscall_range.c3
-rw-r--r--libsyscalls_parse_signed_integer.c3
-rw-r--r--libsyscalls_section_value.c12
-rw-r--r--libsyscalls_unsection_value.c14
-rw-r--r--linux/symbols.c2
-rwxr-xr-xtest3
-rw-r--r--tests/archinfo17
-rw-r--r--tests/error-search13
-rw-r--r--tests/load-archinfo7
-rw-r--r--tests/run4
-rw-r--r--tests/signal-search13
-rw-r--r--testutil/get-datatype-description.c2
-rw-r--r--testutil/get-integer-alignment.c2
-rw-r--r--testutil/get-signals.c2
-rw-r--r--testutil/get-syscall-errors.c2
-rw-r--r--testutil/get-syscall-range.c2
-rw-r--r--testutil/is-datatype-struct.c2
-rw-r--r--testutil/make-signed.c1
-rw-r--r--testutil/parse-signed.c1
-rw-r--r--testutil/section-value.c1
-rw-r--r--testutil/test-search.c114
-rw-r--r--testutil/to-tracee-endian.c8
-rw-r--r--testutil/to-tracer-endian.c4
-rw-r--r--testutil/unsection-value.c1
34 files changed, 1028 insertions, 617 deletions
diff --git a/LICENSE b/LICENSE
index 0be2ccf..6ddac9a 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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
diff --git a/Makefile b/Makefile
index dbe8bcc..7916431 100644
--- a/Makefile
+++ b/Makefile
@@ -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
diff --git a/common.h b/common.h
index e2a5422..8b2ff2b 100644
--- a/common.h
+++ b/common.h
@@ -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"
diff --git a/config.mk b/config.mk
index 1cc7dcb..e0b7aa7 100644
--- a/config.mk
+++ b/config.mk
@@ -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;
diff --git a/test b/test
index 4af52c8..28ce256 100755
--- a/test
+++ b/test
@@ -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;
}