summaryrefslogtreecommitdiffstats
path: root/libsyscalls.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libsyscalls.h369
1 files changed, 328 insertions, 41 deletions
diff --git a/libsyscalls.h b/libsyscalls.h
index caf4a4b..382022b 100644
--- a/libsyscalls.h
+++ b/libsyscalls.h
@@ -31,7 +31,8 @@
X(LIBSYSCALLS_E_NOMEM, "Failed to allocate required memory") D\
X(LIBSYSCALLS_E_INVAL, "Invalid arguments passed to function") D\
X(LIBSYSCALLS_E_NOSUCHTYPE, "Type does not exist on the selected operating system or architecture") D\
- X(LIBSYSCALLS_E_ISSTRUCT, "Type is a structure or union")
+ X(LIBSYSCALLS_E_ISSTRUCT, "Type is a structure or union") D\
+ X(LIBSYSCALLS_E_ISNOTSTRUCT, "Type is not a structure or union")
/**
* libsyscall error numbers
@@ -51,30 +52,49 @@ enum libsyscalls_os {
* Architectures
*/
enum libsyscalls_arch {
- LIBSYSCALLS_ARCH_ALPHA,
+ LIBSYSCALLS_ARCH_ALPHA_LE,
+ LIBSYSCALLS_ARCH_ALPHA_BE,
LIBSYSCALLS_ARCH_AMD64,
- LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI, not traditional 32-bit x86 ISA */
- LIBSYSCALLS_ARCH_ARM_OABI,
- LIBSYSCALLS_ARCH_ARM_EABI,
- LIBSYSCALLS_ARCH_IA64,
+ LIBSYSCALLS_ARCH_AMD64_X32, /* 32-bit ABI on 64-bit ISA */
+ LIBSYSCALLS_ARCH_ARM_OABI_LE,
+ LIBSYSCALLS_ARCH_ARM_OABI_BE,
+ LIBSYSCALLS_ARCH_ARM_EABI_LE,
+ LIBSYSCALLS_ARCH_ARM_EABI_BE,
+ LIBSYSCALLS_ARCH_IA64_LE, /* 64-bit pointers */
+ LIBSYSCALLS_ARCH_IA64_BE, /* 64-bit pointers */
+ LIBSYSCALLS_ARCH_IA64_P32_LE, /* 32-bit pointers */
+ LIBSYSCALLS_ARCH_IA64_P32_BE, /* 32-bit pointers */
LIBSYSCALLS_ARCH_M68K,
- LIBSYSCALLS_ARCH_MICROBLAZE,
- LIBSYSCALLS_ARCH_MIPS_O32,
- LIBSYSCALLS_ARCH_MIPS_N32,
- LIBSYSCALLS_ARCH_MIPS_N64,
+ LIBSYSCALLS_ARCH_MICROBLAZE_32_LE,
+ LIBSYSCALLS_ARCH_MICROBLAZE_32_BE,
+ LIBSYSCALLS_ARCH_MICROBLAZE_64_LE,
+ LIBSYSCALLS_ARCH_MICROBLAZE_64_BE,
+ LIBSYSCALLS_ARCH_MIPS_O32_LE,
+ LIBSYSCALLS_ARCH_MIPS_O32_BE,
+ LIBSYSCALLS_ARCH_MIPS_N32_LE, /* 32-bit ABI on 64-bit ISA */
+ LIBSYSCALLS_ARCH_MIPS_N32_BE, /* 32-bit ABI on 64-bit ISA */
+ LIBSYSCALLS_ARCH_MIPS_N64_LE,
+ LIBSYSCALLS_ARCH_MIPS_N64_BE,
LIBSYSCALLS_ARCH_PARISC_32,
LIBSYSCALLS_ARCH_PARISC_64,
- LIBSYSCALLS_ARCH_POWERPC_32,
- LIBSYSCALLS_ARCH_POWERPC_64,
- LIBSYSCALLS_ARCH_POWERPC_NOSPU,
- LIBSYSCALLS_ARCH_POWERPC_SPU,
+ LIBSYSCALLS_ARCH_POWERPC_32_LE,
+ LIBSYSCALLS_ARCH_POWERPC_32_BE,
+ LIBSYSCALLS_ARCH_POWERPC_64_LE,
+ LIBSYSCALLS_ARCH_POWERPC_64_BE,
+ LIBSYSCALLS_ARCH_POWERPC_NOSPU_LE,
+ LIBSYSCALLS_ARCH_POWERPC_NOSPU_BE,
+ LIBSYSCALLS_ARCH_POWERPC_SPU_LE,
+ LIBSYSCALLS_ARCH_POWERPC_SPU_BE,
LIBSYSCALLS_ARCH_S390_32,
LIBSYSCALLS_ARCH_S390_64,
- LIBSYSCALLS_ARCH_SH,
+ LIBSYSCALLS_ARCH_SH_LE, /* does not cover SH-5 */
+ LIBSYSCALLS_ARCH_SH_BE, /* does not cover SH-5 */
LIBSYSCALLS_ARCH_SPARC_32,
- LIBSYSCALLS_ARCH_SPARC_64,
+ LIBSYSCALLS_ARCH_SPARC_64_LE,
+ LIBSYSCALLS_ARCH_SPARC_64_BE,
LIBSYSCALLS_ARCH_I386,
- LIBSYSCALLS_ARCH_XTENSA
+ LIBSYSCALLS_ARCH_XTENSA_LE,
+ LIBSYSCALLS_ARCH_XTENSA_BE
};
/**
@@ -174,18 +194,23 @@ enum libsyscalls_datatype {
#define LIBSYSCALLS_LIST_STRUCTS_AND_UNIONS(X, SUFFIX, D, FIRST)\
X(LIBSYSCALLS_TYPE_STRUCT_AIO_SIGSET ## SUFFIX, FIRST, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_AIO_SIGSET ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CACHESTAT_RANGE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_CLONE_ARGS ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_EPOLL_EVENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_OABI_EPOLL_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FILE_HANDLE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_FUTEX_WAITV ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOB ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IOVEC ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_EVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_IO_URING_PARAMS ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_ITIMERVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_ITIMERSPEC64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_KEXEC_SEGMENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LANDLOCK_RULESET_ATTR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_LINUX_DIRENT64 ## SUFFIX,, "struct") D\
@@ -214,6 +239,7 @@ enum libsyscalls_datatype {
X(LIBSYSCALLS_TYPE_STRUCT_POLLFD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RLIMIT64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_COMPAT_RLIMIT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_ROBUST_LIST_HEAD ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RSEQ ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_RUSAGE ## SUFFIX,, "struct") D\
@@ -227,7 +253,7 @@ enum libsyscalls_datatype {
X(LIBSYSCALLS_TYPE_STRUCT_SIGALTSTACK ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGEVENT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SIGINFO ## SUFFIX,, "struct") D\
- X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D /* size is always in the next argument */\
+ X(LIBSYSCALLS_TYPE_STRUCT_SOCKADDR ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STAT ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STAT64 ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_STATFS ## SUFFIX,, "struct") D\
@@ -235,6 +261,8 @@ enum libsyscalls_datatype {
X(LIBSYSCALLS_TYPE_STRUCT_STATX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_SYSINFO ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TIMESPEC64 ## SUFFIX,, "struct") D\
+ X(LIBSYSCALLS_TYPE_STRUCT_TIMEVAL ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEX ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TIMEZONE ## SUFFIX,, "struct") D\
X(LIBSYSCALLS_TYPE_STRUCT_TMS ## SUFFIX,, "struct") D\
@@ -246,7 +274,9 @@ enum libsyscalls_datatype {
X(LIBSYSCALLS_TYPE_2_INTS ## SUFFIX, FIRST, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_INTS_FD ## SUFFIX,, "int[2]") D\
X(LIBSYSCALLS_TYPE_2_UINT32S ## SUFFIX,, "uint32[2]") D\
- X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024 / CHAR_BIT / sizeof(long)) in Linux */
+ X(LIBSYSCALLS_TYPE_FD_SET ## SUFFIX,, "unsigned long[]") /* size depends on OS, (1024/CHAR_BIT/sizeof(long)) in Linux */ D\
+ X(LIBSYSCALLS_TYPE_BUFFER_9 ## SUFFIX,, "char[9]") D\
+ X(LIBSYSCALLS_TYPE_BUFFER_65 ## SUFFIX,, "char[65]")
/* these don't have any suffix */
LIBSYSCALLS_MAKE_SPECIAL_TYPES_(),
@@ -256,7 +286,7 @@ enum libsyscalls_datatype {
LIBSYSCALLS_MAKE_ANNOTATED_NUMERICALS_(),
LIBSYSCALLS_MAKE_STRUCTS_AND_UNIONS_(),
- /* the following are always pointers unless returned */
+ /* the following are always pointers if used as a parameter */
/* size in next parameter (or the previous parameter if there is no next parameter),
* updated with fill if possible, otherwise returned (these use the suffix _ARRAY) */
@@ -2074,7 +2104,7 @@ struct libsyscalls_datatype_description {
* guaranteed to be split otherwise) and this value is just
* the number of bits stored in the register or struct field
*
- * It is possible for the datatype to contain unused dummy
+ * It is possible for the data type to contain unused dummy
* bits in order to make it a power of 2 or a multiple of
* a smaller data type. For example, on x86, `long double`
* uses 128 bits, even though the value only uses 80 bits.
@@ -2194,7 +2224,9 @@ struct libsyscalls_datatype_description {
* `sizeof(x.byteorder) / sizeof(*x.byteorder)`
* elements are read (where x is the instance of the
* structure) (you should definitely have your own
- * macro for that one)
+ * macro for that one). As an alternative to
+ * `LIBSYSCALLS_IS_BYTEORDER_END`, you may use the
+ * LIBSYSCALLS_IS_BYTEORDER_END_AT macro
*/
unsigned char byteorder[32];
@@ -2214,6 +2246,14 @@ struct libsyscalls_datatype_description {
# define LIBSYSCALLS_IS_BYTEORDER_END(SHIFT)\
(!~((SHIFT) | ~LIBSYSCALLS_FIELD_MASK_(1ULL, struct libsyscalls_datatype_description, byteorder[0])))
#endif
+
+ /**
+ * Test whether `DESC->byteorder[INDEX]` is
+ * 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]))
};
/**
@@ -2262,6 +2302,51 @@ struct libsyscalls_structure_field {
unsigned short int symbolic_field : 1;
/**
+ * Only used with .input_field set to 1
+ *
+ * If 1, it is probably not an error if the
+ * field is partially initialised as long as all
+ * its memory is allocated
+ *
+ * In the case that a field is split using for
+ * example one field with the type
+ * LIBSYSCALLS_TYPE_UINT64_FRONT_32 and another
+ * field with the type
+ * LIBSYSCALLS_TYPE_UINT64_BACK_32 (these two
+ * (for some split types, their may be more than
+ * two fields) fields will have the same name),
+ * it is one is partially initialised and the
+ * other completely uninitialised. Generally,
+ * as long as at least one of the parts are
+ * partially initialised, the application should
+ * not, unless it has more detailed knowledge
+ * about the system call, assume that there is
+ * an error. This happens because kernel's version
+ * of the library uses a scalar field, where as
+ * the userspace version (usually libc's version)
+ * uses a union of differently sized field. It
+ * is not necessarily the case that it can be
+ * known which field in the union is used: for
+ * example in epoll_ctl(2), it is completely up
+ * to the application, and the application has
+ * no way of telling the kernel which is used,
+ * and the kernel will in epoll_wait(2) simply
+ * return the union's value as it was set, meaning
+ * that some bits may be effectively uninitialised.
+ * Even if the field is complete uninitialised,
+ * it may still be the case that this is not an
+ * error, however, it probably is an error; for
+ * example in the case of epoll(7), it is completely
+ * possible, albeit unlikely (because it's silly),
+ * that the user calls epoll_ctl(2) without the
+ * `.data` field set, because it doesn't look at
+ * in when epoll_wait(2) returns, but insteads
+ * just does unblocking I/O one each file
+ * descriptor it has added to the epoll(7).
+ */
+ unsigned short int partial_init_ok : 1;
+
+ /**
* If 1, the field is a pointer that the reads from
*
* Note that there are types that fundamentally are
@@ -2281,7 +2366,16 @@ struct libsyscalls_structure_field {
*/
unsigned short int output_pointer : 1;
- unsigned short int padding1__ : 16 - (6*1);
+ /**
+ * If 1, it has been determined that the field is
+ * not being used (usually because that it's not
+ * the active field in a `union` or because a
+ * flag somewhere in the `struct` is either set or
+ * cleared)
+ */
+ unsigned short int unused : 1;
+
+ unsigned short int padding1__ : 16 - (8*1);
#if LIBSYSCALLS_IS_PADDING_REQUIRED_(3, 16, LIBSYSCALLS_POINTER_BIT_)
# if !LIBSYSCALLS_CAN_ALIGN_(3, 16, CHAR_BIT)
@@ -2289,6 +2383,30 @@ struct libsyscalls_structure_field {
# endif
char padding2__[LIBSYSCALLS_PAD_(sizeof(void *)/sizeof(char), (3*16)/CHAR_BIT)];
#endif
+
+ /**
+ * Data type description
+ *
+ * The application is free to make changes, however,
+ * however the pointers themselves must not be touched
+ */
+ union {
+ /**
+ * Description to use if `.type` refers to a
+ * `struct` or `union`; that is, if
+ * `(.type & ~LIBSYSCALLS_TYPEBITSMASK) >=
+ * LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
+ */
+ struct libsyscalls_structure_description *structure;
+
+ /**
+ * Description to use if `.type` does not refer
+ * to a `struct` or `union`; that is, if
+ * `(.type & ~LIBSYSCALLS_TYPEBITSMASK) <
+ * LIBSYSCALLS_TYPEOFFSET_STRUCTS_AND_UNIONS`
+ */
+ struct libsyscalls_datatype_description *nonstructure;
+ } type_description;
};
/**
@@ -2320,6 +2438,12 @@ struct libsyscalls_structure_description {
unsigned short int num_fields : 14;
/**
+ * If 1, the data type is a `union`,
+ * if 0, the data type is a `struct`
+ */
+ unsigned short int is_union : 1;
+
+ /**
* Only used if .array_size is 0
*
* Assuming the kernel writes into the array, if 1, the number
@@ -2333,18 +2457,12 @@ struct libsyscalls_structure_description {
unsigned short int fill_is_known : 1;
/**
- * If 1, the data type is a `union`,
- * if 0, the data type is a `struct`
- */
- unsigned short int is_union : 1;
-
- /**
* The size (in number of elements) of the array the data type
* is used in, or 1 if the data type was not an array or
* 0 if the array size is determined by another parameter/field
*
* If 1, .relative_position_of_size will be set to 0,
- * and .absolute_position_of_size -1, hoever if that is not
+ * and .absolute_position_of_size -1, however if that is not
* the case and this field is set to 1, then .size (which may
* or may not be 0 at this point) is determined by the indicated
* parameter
@@ -2441,7 +2559,7 @@ 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__)
+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 *);
@@ -2468,7 +2586,7 @@ libsyscalls_get_syscall_range(enum libsyscalls_os, enum libsyscalls_arch, long l
* of operating system (`os`) and architecture (`arch`) is
* unsupported
*/
-LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+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 **);
@@ -2498,6 +2616,7 @@ libsyscalls_get_syscall(enum libsyscalls_os, enum libsyscalls_arch, long long in
* 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))
enum libsyscalls_error
libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
@@ -2527,6 +2646,7 @@ libsyscalls_get_syscall_errors(enum libsyscalls_os, enum libsyscalls_arch, const
* 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))
enum libsyscalls_error
libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct libsyscalls_named_number **, size_t *);
@@ -2542,7 +2662,11 @@ libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct
* @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
+ * @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`)
@@ -2552,17 +2676,23 @@ libsyscalls_get_signals(enum libsyscalls_os, enum libsyscalls_arch, const struct
* 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__)
+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, unsigned long long int *, struct libsyscalls_syscall_display_info **);
+ long long int, const unsigned long long int *, struct libsyscalls_syscall_display_info **);
/**
- * Get information on how an instance of data type is to be parsed
+ * Get information on how an instance of non-struct, non-union
+ * data type is to be parsed
+ *
+ * Do not use for data types inside structures,
+ * instead, use `.type_description.nonstructure`
+ * 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 datatype, `LIBSYSCALLS_TYPE_DYNAMIC` can
+ * @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
@@ -2575,13 +2705,14 @@ libsyscalls_get_syscall_display_info(enum libsyscalls_os, enum libsyscalls_arch,
* 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
+ * 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__)
+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 *);
@@ -2625,11 +2756,167 @@ libsyscalls_get_datatype_description(enum libsyscalls_os, enum libsyscalls_arch,
* return LIBSYSCALLS_E_ARCHNOSUP, in such cases, the result
* is indeed reliable
*/
-LIBSYSCALLS_GCC_ATTRIBUTES_(__warn_unused_result__)
+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 *);
-/* TODO add libsyscalls_get_struct_description */
+/**
+ * Parse a string of bits as a signed integer
+ *
+ * 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`
+ */
+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 *);
+
+/**
+ * Create a string of bits representing a signed integer
+ *
+ * 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`
+ */
+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 *);
+
+/**
+ * Take bits from a section of a split value
+ * and shift its bit into place, so that the OR
+ * of the result for each section creates the
+ * original unsplit value
+ *
+ * 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`
+ */
+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 *);
+
+/**
+ * Create a split section from a value
+ *
+ * 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`
+ */
+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 *);
+
+/**
+ * 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
+ */
+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 *);
+
+/**
+ * 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
+ */
+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);
+
+/**
+ * Get information on how an instance of struct or union is to be parsed
+ *
+ * Do not use for structures inside other structures,
+ * instead, use `.type_description.structure` 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
+ * @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))
+enum libsyscalls_error
+libsyscalls_get_struct_description(enum libsyscalls_os, enum libsyscalls_arch, enum libsyscalls_datatype,
+ const void *, size_t, struct libsyscalls_structure_description **);
+#endif
+
/* TODO add libsyscalls_get_struct_display_info */