Move dead submodules in-tree

Signed-off-by: swurl <swurl@swurl.xyz>
This commit is contained in:
swurl 2025-05-31 02:33:02 -04:00
parent c0cceff365
commit 6c655321e6
No known key found for this signature in database
GPG key ID: A5A7629F109C8FD1
4081 changed files with 1185566 additions and 45 deletions

View file

@ -0,0 +1,22 @@
COPYRIGHT AND PERMISSION NOTICE
Copyright (c) 1996 - 2011, Daniel Stenberg, <daniel@haxx.se>.
All rights reserved.
Permission to use, copy, modify, and distribute this software for any purpose
with or without fee is hereby granted, provided that the above copyright
notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY RIGHTS. IN
NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
Except as contained in this notice, the name of a copyright holder shall not
be used in advertising or otherwise to promote the sale, use or other dealings
in this Software without prior written authorization of the copyright holder.

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,204 @@
/* include/curl/curlbuild.h. Generated from curlbuild.h.in by configure. */
#ifndef __CURL_CURLBUILD_H
#define __CURL_CURLBUILD_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: curlbuild.h.in,v 1.8 2009-04-29 15:15:38 yangtse Exp $
***************************************************************************/
/* ================================================================ */
/* NOTES FOR CONFIGURE CAPABLE SYSTEMS */
/* ================================================================ */
/*
* NOTE 1:
* -------
*
* Nothing in this file is intended to be modified or adjusted by the
* curl library user nor by the curl library builder.
*
* If you think that something actually needs to be changed, adjusted
* or fixed in this file, then, report it on the libcurl development
* mailing list: http://cool.haxx.se/mailman/listinfo/curl-library/
*
* This header file shall only export symbols which are 'curl' or 'CURL'
* prefixed, otherwise public name space would be polluted.
*
* NOTE 2:
* -------
*
* Right now you might be staring at file include/curl/curlbuild.h.in or
* at file include/curl/curlbuild.h, this is due to the following reason:
*
* On systems capable of running the configure script, the configure process
* will overwrite the distributed include/curl/curlbuild.h file with one that
* is suitable and specific to the library being configured and built, which
* is generated from the include/curl/curlbuild.h.in template file.
*
*/
/* ================================================================ */
/* DEFINITION OF THESE SYMBOLS SHALL NOT TAKE PLACE ANYWHERE ELSE */
/* ================================================================ */
#ifdef CURL_SIZEOF_LONG
# error "CURL_SIZEOF_LONG shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_LONG_already_defined
#endif
#ifdef CURL_TYPEOF_CURL_SOCKLEN_T
# error "CURL_TYPEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_already_defined
#endif
#ifdef CURL_SIZEOF_CURL_SOCKLEN_T
# error "CURL_SIZEOF_CURL_SOCKLEN_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_already_defined
#endif
#ifdef CURL_TYPEOF_CURL_OFF_T
# error "CURL_TYPEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_already_defined
#endif
#ifdef CURL_FORMAT_CURL_OFF_T
# error "CURL_FORMAT_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_already_defined
#endif
#ifdef CURL_FORMAT_CURL_OFF_TU
# error "CURL_FORMAT_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_already_defined
#endif
#ifdef CURL_FORMAT_OFF_T
# error "CURL_FORMAT_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_FORMAT_OFF_T_already_defined
#endif
#ifdef CURL_SIZEOF_CURL_OFF_T
# error "CURL_SIZEOF_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_already_defined
#endif
#ifdef CURL_SUFFIX_CURL_OFF_T
# error "CURL_SUFFIX_CURL_OFF_T shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_already_defined
#endif
#ifdef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU shall not be defined except in curlbuild.h"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_already_defined
#endif
/* ================================================================ */
/* EXTERNAL INTERFACE SETTINGS FOR CONFIGURE CAPABLE SYSTEMS ONLY */
/* ================================================================ */
/* Configure process defines this to 1 when it finds out that system */
/* header file ws2tcpip.h must be included by the external interface. */
/* #undef CURL_PULL_WS2TCPIP_H */
#ifdef CURL_PULL_WS2TCPIP_H
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# include <winsock2.h>
# include <ws2tcpip.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/types.h must be included by the external interface. */
#define CURL_PULL_SYS_TYPES_H 1
#ifdef CURL_PULL_SYS_TYPES_H
# include <sys/types.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file stdint.h must be included by the external interface. */
/* #undef CURL_PULL_STDINT_H */
#ifdef CURL_PULL_STDINT_H
# include <stdint.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file inttypes.h must be included by the external interface. */
/* #undef CURL_PULL_INTTYPES_H */
#ifdef CURL_PULL_INTTYPES_H
# include <inttypes.h>
#endif
/* Configure process defines this to 1 when it finds out that system */
/* header file sys/socket.h must be included by the external interface. */
#define CURL_PULL_SYS_SOCKET_H 1
#ifdef CURL_PULL_SYS_SOCKET_H
# include <sys/socket.h>
#endif
/* The size of `long', as computed by sizeof. */
#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
defined(__aarch64__) || (defined(__mips__) && _MIPS_SIM == _ABI64) || \
defined(__powerpc64__) || defined(__s390x__) || defined(__LP64__) || \
(defined(__riscv) && __riscv_xlen == 64)
#define CURL_SIZEOF_LONG 8
#else
#define CURL_SIZEOF_LONG 4
#endif
/* Integral data type used for curl_socklen_t. */
#define CURL_TYPEOF_CURL_SOCKLEN_T socklen_t
/* The size of `curl_socklen_t', as computed by sizeof. */
#define CURL_SIZEOF_CURL_SOCKLEN_T 4
/* Data type definition of curl_socklen_t. */
typedef CURL_TYPEOF_CURL_SOCKLEN_T curl_socklen_t;
/* Signed integral data type used for curl_off_t. */
#if defined(_M_X64) || (defined(__x86_64__) && !defined(__ILP32__)) || \
defined(__aarch64__)
#define CURL_TYPEOF_CURL_OFF_T long
#else
#define CURL_TYPEOF_CURL_OFF_T int64_t
#endif
/* Data type definition of curl_off_t. */
typedef CURL_TYPEOF_CURL_OFF_T curl_off_t;
/* curl_off_t formatting string directive without "%" conversion specifier. */
#define CURL_FORMAT_CURL_OFF_T "ld"
/* unsigned curl_off_t formatting string without "%" conversion specifier. */
#define CURL_FORMAT_CURL_OFF_TU "lu"
/* curl_off_t formatting string directive with "%" conversion specifier. */
#define CURL_FORMAT_OFF_T "%ld"
/* The size of `curl_off_t', as computed by sizeof. */
#define CURL_SIZEOF_CURL_OFF_T 8
/* curl_off_t constant suffix. */
#define CURL_SUFFIX_CURL_OFF_T L
/* unsigned curl_off_t constant suffix. */
#define CURL_SUFFIX_CURL_OFF_TU UL
#endif /* __CURL_CURLBUILD_H */

View file

@ -0,0 +1,249 @@
#ifndef __CURL_CURLRULES_H
#define __CURL_CURLRULES_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: curlrules.h,v 1.7 2009-10-27 16:56:20 yangtse Exp $
***************************************************************************/
/* ================================================================ */
/* COMPILE TIME SANITY CHECKS */
/* ================================================================ */
/*
* NOTE 1:
* -------
*
* All checks done in this file are intentionally placed in a public
* header file which is pulled by curl/curl.h when an application is
* being built using an already built libcurl library. Additionally
* this file is also included and used when building the library.
*
* If compilation fails on this file it is certainly sure that the
* problem is elsewhere. It could be a problem in the curlbuild.h
* header file, or simply that you are using different compilation
* settings than those used to build the library.
*
* Nothing in this file is intended to be modified or adjusted by the
* curl library user nor by the curl library builder.
*
* Do not deactivate any check, these are done to make sure that the
* library is properly built and used.
*
* You can find further help on the libcurl development mailing list:
* http://cool.haxx.se/mailman/listinfo/curl-library/
*
* NOTE 2
* ------
*
* Some of the following compile time checks are based on the fact
* that the dimension of a constant array can not be a negative one.
* In this way if the compile time verification fails, the compilation
* will fail issuing an error. The error description wording is compiler
* dependent but it will be quite similar to one of the following:
*
* "negative subscript or subscript is too large"
* "array must have at least one element"
* "-1 is an illegal array size"
* "size of array is negative"
*
* If you are building an application which tries to use an already
* built libcurl library and you are getting this kind of errors on
* this file, it is a clear indication that there is a mismatch between
* how the library was built and how you are trying to use it for your
* application. Your already compiled or binary library provider is the
* only one who can give you the details you need to properly use it.
*/
/*
* Verify that some macros are actually defined.
*/
#ifndef CURL_SIZEOF_LONG
# error "CURL_SIZEOF_LONG definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_LONG_is_missing
#endif
#ifndef CURL_TYPEOF_CURL_SOCKLEN_T
# error "CURL_TYPEOF_CURL_SOCKLEN_T definition is missing!"
Error Compilation_aborted_CURL_TYPEOF_CURL_SOCKLEN_T_is_missing
#endif
#ifndef CURL_SIZEOF_CURL_SOCKLEN_T
# error "CURL_SIZEOF_CURL_SOCKLEN_T definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_CURL_SOCKLEN_T_is_missing
#endif
#ifndef CURL_TYPEOF_CURL_OFF_T
# error "CURL_TYPEOF_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_TYPEOF_CURL_OFF_T_is_missing
#endif
#ifndef CURL_FORMAT_CURL_OFF_T
# error "CURL_FORMAT_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_T_is_missing
#endif
#ifndef CURL_FORMAT_CURL_OFF_TU
# error "CURL_FORMAT_CURL_OFF_TU definition is missing!"
Error Compilation_aborted_CURL_FORMAT_CURL_OFF_TU_is_missing
#endif
#ifndef CURL_FORMAT_OFF_T
# error "CURL_FORMAT_OFF_T definition is missing!"
Error Compilation_aborted_CURL_FORMAT_OFF_T_is_missing
#endif
#ifndef CURL_SIZEOF_CURL_OFF_T
# error "CURL_SIZEOF_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_SIZEOF_CURL_OFF_T_is_missing
#endif
#ifndef CURL_SUFFIX_CURL_OFF_T
# error "CURL_SUFFIX_CURL_OFF_T definition is missing!"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_T_is_missing
#endif
#ifndef CURL_SUFFIX_CURL_OFF_TU
# error "CURL_SUFFIX_CURL_OFF_TU definition is missing!"
Error Compilation_aborted_CURL_SUFFIX_CURL_OFF_TU_is_missing
#endif
/*
* Macros private to this header file.
*/
#define CurlchkszEQ(t, s) sizeof(t) == s ? 1 : -1
#define CurlchkszGE(t1, t2) sizeof(t1) >= sizeof(t2) ? 1 : -1
/*
* Verify that the size previously defined and expected for long
* is the same as the one reported by sizeof() at compile time.
*/
typedef char
__curl_rule_01__
[CurlchkszEQ(long, CURL_SIZEOF_LONG)];
/*
* Verify that the size previously defined and expected for
* curl_off_t is actually the the same as the one reported
* by sizeof() at compile time.
*/
typedef char
__curl_rule_02__
[CurlchkszEQ(curl_off_t, CURL_SIZEOF_CURL_OFF_T)];
/*
* Verify at compile time that the size of curl_off_t as reported
* by sizeof() is greater or equal than the one reported for long
* for the current compilation.
*/
typedef char
__curl_rule_03__
[CurlchkszGE(curl_off_t, long)];
/*
* Verify that the size previously defined and expected for
* curl_socklen_t is actually the the same as the one reported
* by sizeof() at compile time.
*/
typedef char
__curl_rule_04__
[CurlchkszEQ(curl_socklen_t, CURL_SIZEOF_CURL_SOCKLEN_T)];
/*
* Verify at compile time that the size of curl_socklen_t as reported
* by sizeof() is greater or equal than the one reported for int for
* the current compilation.
*/
typedef char
__curl_rule_05__
[CurlchkszGE(curl_socklen_t, int)];
/* ================================================================ */
/* EXTERNALLY AND INTERNALLY VISIBLE DEFINITIONS */
/* ================================================================ */
/*
* CURL_ISOCPP and CURL_OFF_T_C definitions are done here in order to allow
* these to be visible and exported by the external libcurl interface API,
* while also making them visible to the library internals, simply including
* setup.h, without actually needing to include curl.h internally.
* If some day this section would grow big enough, all this should be moved
* to its own header file.
*/
/*
* Figure out if we can use the ## preprocessor operator, which is supported
* by ISO/ANSI C and C++. Some compilers support it without setting __STDC__
* or __cplusplus so we need to carefully check for them too.
*/
#if defined(__STDC__) || defined(_MSC_VER) || defined(__cplusplus) || \
defined(__HP_aCC) || defined(__BORLANDC__) || defined(__LCC__) || \
defined(__POCC__) || defined(__SALFORDC__) || defined(__HIGHC__) || \
defined(__ILEC400__)
/* This compiler is believed to have an ISO compatible preprocessor */
#define CURL_ISOCPP
#else
/* This compiler is believed NOT to have an ISO compatible preprocessor */
#undef CURL_ISOCPP
#endif
/*
* Macros for minimum-width signed and unsigned curl_off_t integer constants.
*/
#ifdef CURL_ISOCPP
# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val ## Suffix
#else
# define __CURL_OFF_T_C_HELPER2(Val,Suffix) Val/**/Suffix
#endif
#define __CURL_OFF_T_C_HELPER1(Val,Suffix) __CURL_OFF_T_C_HELPER2(Val,Suffix)
#define CURL_OFF_T_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_T)
#define CURL_OFF_TU_C(Val) __CURL_OFF_T_C_HELPER1(Val,CURL_SUFFIX_CURL_OFF_TU)
/*
* Get rid of macros private to this header file.
*/
#undef CurlchkszEQ
#undef CurlchkszGE
/*
* Get rid of macros not intended to exist beyond this point.
*/
#undef CURL_PULL_WS2TCPIP_H
#undef CURL_PULL_SYS_TYPES_H
#undef CURL_PULL_SYS_SOCKET_H
#undef CURL_PULL_STDINT_H
#undef CURL_PULL_INTTYPES_H
#undef CURL_TYPEOF_CURL_SOCKLEN_T
#undef CURL_TYPEOF_CURL_OFF_T
#endif /* __CURL_CURLRULES_H */

View file

@ -0,0 +1,70 @@
#ifndef __CURL_CURLVER_H
#define __CURL_CURLVER_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: curlver.h,v 1.48 2009-08-12 11:24:52 bagder Exp $
***************************************************************************/
/* This header file contains nothing but libcurl version info, generated by
a script at release-time. This was made its own header file in 7.11.2 */
/* This is the global package copyright */
#define LIBCURL_COPYRIGHT "1996 - 2009 Daniel Stenberg, <daniel@haxx.se>."
/* This is the version number of the libcurl package from which this header
file origins: */
#define LIBCURL_VERSION "7.19.7"
/* The numeric version number is also available "in parts" by using these
defines: */
#define LIBCURL_VERSION_MAJOR 7
#define LIBCURL_VERSION_MINOR 19
#define LIBCURL_VERSION_PATCH 7
/* This is the numeric version of the libcurl version number, meant for easier
parsing and comparions by programs. The LIBCURL_VERSION_NUM define will
always follow this syntax:
0xXXYYZZ
Where XX, YY and ZZ are the main version, release and patch numbers in
hexadecimal (using 8 bits each). All three numbers are always represented
using two digits. 1.2 would appear as "0x010200" while version 9.11.7
appears as "0x090b07".
This 6-digit (24 bits) hexadecimal number does not show pre-release number,
and it is always a greater number in a more recent release. It makes
comparisons with greater than and less than work.
*/
#define LIBCURL_VERSION_NUM 0x071307
/*
* This is the date and time when the full source package was created. The
* timestamp is not stored in CVS, as the timestamp is properly set in the
* tarballs by the maketgz script.
*
* The format of the date should follow this template:
*
* "Mon Feb 12 11:35:33 UTC 2007"
*/
#define LIBCURL_TIMESTAMP "Wed Nov 4 12:34:59 UTC 2009"
#endif /* __CURL_CURLVER_H */

View file

@ -0,0 +1,103 @@
#ifndef __CURL_EASY_H
#define __CURL_EASY_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2008, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: easy.h,v 1.14 2008-05-12 21:43:28 bagder Exp $
***************************************************************************/
#ifdef __cplusplus
extern "C" {
#endif
CURL_EXTERN CURL *curl_easy_init(void);
CURL_EXTERN CURLcode curl_easy_setopt(CURL *curl, CURLoption option, ...);
CURL_EXTERN CURLcode curl_easy_perform(CURL *curl);
CURL_EXTERN void curl_easy_cleanup(CURL *curl);
/*
* NAME curl_easy_getinfo()
*
* DESCRIPTION
*
* Request internal information from the curl session with this function. The
* third argument MUST be a pointer to a long, a pointer to a char * or a
* pointer to a double (as the documentation describes elsewhere). The data
* pointed to will be filled in accordingly and can be relied upon only if the
* function returns CURLE_OK. This function is intended to get used *AFTER* a
* performed transfer, all results from this function are undefined until the
* transfer is completed.
*/
CURL_EXTERN CURLcode curl_easy_getinfo(CURL *curl, CURLINFO info, ...);
/*
* NAME curl_easy_duphandle()
*
* DESCRIPTION
*
* Creates a new curl session handle with the same options set for the handle
* passed in. Duplicating a handle could only be a matter of cloning data and
* options, internal state info and things like persistant connections cannot
* be transfered. It is useful in multithreaded applications when you can run
* curl_easy_duphandle() for each new thread to avoid a series of identical
* curl_easy_setopt() invokes in every thread.
*/
CURL_EXTERN CURL* curl_easy_duphandle(CURL *curl);
/*
* NAME curl_easy_reset()
*
* DESCRIPTION
*
* Re-initializes a CURL handle to the default values. This puts back the
* handle to the same state as it was in when it was just created.
*
* It does keep: live connections, the Session ID cache, the DNS cache and the
* cookies.
*/
CURL_EXTERN void curl_easy_reset(CURL *curl);
/*
* NAME curl_easy_recv()
*
* DESCRIPTION
*
* Receives data from the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_recv(CURL *curl, void *buffer, size_t buflen,
size_t *n);
/*
* NAME curl_easy_send()
*
* DESCRIPTION
*
* Sends data over the connected socket. Use after successful
* curl_easy_perform() with CURLOPT_CONNECT_ONLY option.
*/
CURL_EXTERN CURLcode curl_easy_send(CURL *curl, const void *buffer,
size_t buflen, size_t *n);
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,82 @@
#ifndef __CURL_MPRINTF_H
#define __CURL_MPRINTF_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2006, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: mprintf.h,v 1.16 2008-05-20 10:21:50 patrickm Exp $
***************************************************************************/
#include <stdarg.h>
#include <stdio.h> /* needed for FILE */
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
CURL_EXTERN int curl_mprintf(const char *format, ...);
CURL_EXTERN int curl_mfprintf(FILE *fd, const char *format, ...);
CURL_EXTERN int curl_msprintf(char *buffer, const char *format, ...);
CURL_EXTERN int curl_msnprintf(char *buffer, size_t maxlength,
const char *format, ...);
CURL_EXTERN int curl_mvprintf(const char *format, va_list args);
CURL_EXTERN int curl_mvfprintf(FILE *fd, const char *format, va_list args);
CURL_EXTERN int curl_mvsprintf(char *buffer, const char *format, va_list args);
CURL_EXTERN int curl_mvsnprintf(char *buffer, size_t maxlength,
const char *format, va_list args);
CURL_EXTERN char *curl_maprintf(const char *format, ...);
CURL_EXTERN char *curl_mvaprintf(const char *format, va_list args);
#ifdef _MPRINTF_REPLACE
# undef printf
# undef fprintf
# undef sprintf
# undef vsprintf
# undef snprintf
# undef vprintf
# undef vfprintf
# undef vsnprintf
# undef aprintf
# undef vaprintf
# define printf curl_mprintf
# define fprintf curl_mfprintf
#ifdef CURLDEBUG
/* When built with CURLDEBUG we define away the sprintf() functions since we
don't want internal code to be using them */
# define sprintf sprintf_was_used
# define vsprintf vsprintf_was_used
#else
# define sprintf curl_msprintf
# define vsprintf curl_mvsprintf
#endif
# define snprintf curl_msnprintf
# define vprintf curl_mvprintf
# define vfprintf curl_mvfprintf
# define vsnprintf curl_mvsnprintf
# define aprintf curl_maprintf
# define vaprintf curl_mvaprintf
#endif
#ifdef __cplusplus
}
#endif
#endif /* __CURL_MPRINTF_H */

View file

@ -0,0 +1,346 @@
#ifndef __CURL_MULTI_H
#define __CURL_MULTI_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2007, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: multi.h,v 1.45 2008-05-20 10:21:50 patrickm Exp $
***************************************************************************/
/*
This is an "external" header file. Don't give away any internals here!
GOALS
o Enable a "pull" interface. The application that uses libcurl decides where
and when to ask libcurl to get/send data.
o Enable multiple simultaneous transfers in the same thread without making it
complicated for the application.
o Enable the application to select() on its own file descriptors and curl's
file descriptors simultaneous easily.
*/
/*
* This header file should not really need to include "curl.h" since curl.h
* itself includes this file and we expect user applications to do #include
* <curl/curl.h> without the need for especially including multi.h.
*
* For some reason we added this include here at one point, and rather than to
* break existing (wrongly written) libcurl applications, we leave it as-is
* but with this warning attached.
*/
#include "curl.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef void CURLM;
typedef enum {
CURLM_CALL_MULTI_PERFORM = -1, /* please call curl_multi_perform() or
curl_multi_socket*() soon */
CURLM_OK,
CURLM_BAD_HANDLE, /* the passed-in handle is not a valid CURLM handle */
CURLM_BAD_EASY_HANDLE, /* an easy handle was not good/valid */
CURLM_OUT_OF_MEMORY, /* if you ever get this, you're in deep sh*t */
CURLM_INTERNAL_ERROR, /* this is a libcurl bug */
CURLM_BAD_SOCKET, /* the passed in socket argument did not match */
CURLM_UNKNOWN_OPTION, /* curl_multi_setopt() with unsupported option */
CURLM_LAST
} CURLMcode;
/* just to make code nicer when using curl_multi_socket() you can now check
for CURLM_CALL_MULTI_SOCKET too in the same style it works for
curl_multi_perform() and CURLM_CALL_MULTI_PERFORM */
#define CURLM_CALL_MULTI_SOCKET CURLM_CALL_MULTI_PERFORM
typedef enum {
CURLMSG_NONE, /* first, not used */
CURLMSG_DONE, /* This easy handle has completed. 'result' contains
the CURLcode of the transfer */
CURLMSG_LAST /* last, not used */
} CURLMSG;
struct CURLMsg {
CURLMSG msg; /* what this message means */
CURL *easy_handle; /* the handle it concerns */
union {
void *whatever; /* message-specific data */
CURLcode result; /* return code for transfer */
} data;
};
typedef struct CURLMsg CURLMsg;
/*
* Name: curl_multi_init()
*
* Desc: inititalize multi-style curl usage
*
* Returns: a new CURLM handle to use in all 'curl_multi' functions.
*/
CURL_EXTERN CURLM *curl_multi_init(void);
/*
* Name: curl_multi_add_handle()
*
* Desc: add a standard curl handle to the multi stack
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_add_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_remove_handle()
*
* Desc: removes a curl handle from the multi stack again
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_remove_handle(CURLM *multi_handle,
CURL *curl_handle);
/*
* Name: curl_multi_fdset()
*
* Desc: Ask curl for its fd_set sets. The app can use these to select() or
* poll() on. We want curl_multi_perform() called as soon as one of
* them are ready.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_fdset(CURLM *multi_handle,
fd_set *read_fd_set,
fd_set *write_fd_set,
fd_set *exc_fd_set,
int *max_fd);
/*
* Name: curl_multi_perform()
*
* Desc: When the app thinks there's data available for curl it calls this
* function to read/write whatever there is right now. This returns
* as soon as the reads and writes are done. This function does not
* require that there actually is data available for reading or that
* data can be written, it can be called just in case. It returns
* the number of handles that still transfer data in the second
* argument's integer-pointer.
*
* Returns: CURLMcode type, general multi error code. *NOTE* that this only
* returns errors etc regarding the whole multi stack. There might
* still have occurred problems on invidual transfers even when this
* returns OK.
*/
CURL_EXTERN CURLMcode curl_multi_perform(CURLM *multi_handle,
int *running_handles);
/*
* Name: curl_multi_cleanup()
*
* Desc: Cleans up and removes a whole multi stack. It does not free or
* touch any individual easy handles in any way. We need to define
* in what state those handles will be if this function is called
* in the middle of a transfer.
*
* Returns: CURLMcode type, general multi error code.
*/
CURL_EXTERN CURLMcode curl_multi_cleanup(CURLM *multi_handle);
/*
* Name: curl_multi_info_read()
*
* Desc: Ask the multi handle if there's any messages/informationals from
* the individual transfers. Messages include informationals such as
* error code from the transfer or just the fact that a transfer is
* completed. More details on these should be written down as well.
*
* Repeated calls to this function will return a new struct each
* time, until a special "end of msgs" struct is returned as a signal
* that there is no more to get at this point.
*
* The data the returned pointer points to will not survive calling
* curl_multi_cleanup().
*
* The 'CURLMsg' struct is meant to be very simple and only contain
* very basic informations. If more involved information is wanted,
* we will provide the particular "transfer handle" in that struct
* and that should/could/would be used in subsequent
* curl_easy_getinfo() calls (or similar). The point being that we
* must never expose complex structs to applications, as then we'll
* undoubtably get backwards compatibility problems in the future.
*
* Returns: A pointer to a filled-in struct, or NULL if it failed or ran out
* of structs. It also writes the number of messages left in the
* queue (after this read) in the integer the second argument points
* to.
*/
CURL_EXTERN CURLMsg *curl_multi_info_read(CURLM *multi_handle,
int *msgs_in_queue);
/*
* Name: curl_multi_strerror()
*
* Desc: The curl_multi_strerror function may be used to turn a CURLMcode
* value into the equivalent human readable error string. This is
* useful for printing meaningful error messages.
*
* Returns: A pointer to a zero-terminated error message.
*/
CURL_EXTERN const char *curl_multi_strerror(CURLMcode);
/*
* Name: curl_multi_socket() and
* curl_multi_socket_all()
*
* Desc: An alternative version of curl_multi_perform() that allows the
* application to pass in one of the file descriptors that have been
* detected to have "action" on them and let libcurl perform.
* See man page for details.
*/
#define CURL_POLL_NONE 0
#define CURL_POLL_IN 1
#define CURL_POLL_OUT 2
#define CURL_POLL_INOUT 3
#define CURL_POLL_REMOVE 4
#define CURL_SOCKET_TIMEOUT CURL_SOCKET_BAD
#define CURL_CSELECT_IN 0x01
#define CURL_CSELECT_OUT 0x02
#define CURL_CSELECT_ERR 0x04
typedef int (*curl_socket_callback)(CURL *easy, /* easy handle */
curl_socket_t s, /* socket */
int what, /* see above */
void *userp, /* private callback
pointer */
void *socketp); /* private socket
pointer */
/*
* Name: curl_multi_timer_callback
*
* Desc: Called by libcurl whenever the library detects a change in the
* maximum number of milliseconds the app is allowed to wait before
* curl_multi_socket() or curl_multi_perform() must be called
* (to allow libcurl's timed events to take place).
*
* Returns: The callback should return zero.
*/
typedef int (*curl_multi_timer_callback)(CURLM *multi, /* multi handle */
long timeout_ms, /* see above */
void *userp); /* private callback
pointer */
CURL_EXTERN CURLMcode curl_multi_socket(CURLM *multi_handle, curl_socket_t s,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_action(CURLM *multi_handle,
curl_socket_t s,
int ev_bitmask,
int *running_handles);
CURL_EXTERN CURLMcode curl_multi_socket_all(CURLM *multi_handle,
int *running_handles);
#ifndef CURL_ALLOW_OLD_MULTI_SOCKET
/* This macro below was added in 7.16.3 to push users who recompile to use
the new curl_multi_socket_action() instead of the old curl_multi_socket()
*/
#define curl_multi_socket(x,y,z) curl_multi_socket_action(x,y,0,z)
#endif
/*
* Name: curl_multi_timeout()
*
* Desc: Returns the maximum number of milliseconds the app is allowed to
* wait before curl_multi_socket() or curl_multi_perform() must be
* called (to allow libcurl's timed events to take place).
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_timeout(CURLM *multi_handle,
long *milliseconds);
#undef CINIT /* re-using the same name as in curl.h */
#ifdef CURL_ISOCPP
#define CINIT(name,type,num) CURLMOPT_ ## name = CURLOPTTYPE_ ## type + num
#else
/* The macro "##" is ISO C, we assume pre-ISO C doesn't support it. */
#define LONG CURLOPTTYPE_LONG
#define OBJECTPOINT CURLOPTTYPE_OBJECTPOINT
#define FUNCTIONPOINT CURLOPTTYPE_FUNCTIONPOINT
#define OFF_T CURLOPTTYPE_OFF_T
#define CINIT(name,type,number) CURLMOPT_/**/name = type + number
#endif
typedef enum {
/* This is the socket callback function pointer */
CINIT(SOCKETFUNCTION, FUNCTIONPOINT, 1),
/* This is the argument passed to the socket callback */
CINIT(SOCKETDATA, OBJECTPOINT, 2),
/* set to 1 to enable pipelining for this multi handle */
CINIT(PIPELINING, LONG, 3),
/* This is the timer callback function pointer */
CINIT(TIMERFUNCTION, FUNCTIONPOINT, 4),
/* This is the argument passed to the timer callback */
CINIT(TIMERDATA, OBJECTPOINT, 5),
/* maximum number of entries in the connection cache */
CINIT(MAXCONNECTS, LONG, 6),
CURLMOPT_LASTENTRY /* the last unused */
} CURLMoption;
/*
* Name: curl_multi_setopt()
*
* Desc: Sets options for the multi handle.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_setopt(CURLM *multi_handle,
CURLMoption option, ...);
/*
* Name: curl_multi_assign()
*
* Desc: This function sets an association in the multi handle between the
* given socket and a private pointer of the application. This is
* (only) useful for curl_multi_socket uses.
*
* Returns: CURLM error code.
*/
CURL_EXTERN CURLMcode curl_multi_assign(CURLM *multi_handle,
curl_socket_t sockfd, void *sockp);
#ifdef __cplusplus
} /* end of extern "C" */
#endif
#endif

View file

@ -0,0 +1,34 @@
#ifndef __STDC_HEADERS_H
#define __STDC_HEADERS_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: stdcheaders.h,v 1.9 2009-05-18 12:25:45 yangtse Exp $
***************************************************************************/
#include <sys/types.h>
size_t fread (void *, size_t, size_t, FILE *);
size_t fwrite (const void *, size_t, size_t, FILE *);
int strcasecmp(const char *, const char *);
int strncasecmp(const char *, const char *, size_t);
#endif

View file

@ -0,0 +1,551 @@
#ifndef __CURL_TYPECHECK_GCC_H
#define __CURL_TYPECHECK_GCC_H
/***************************************************************************
* _ _ ____ _
* Project ___| | | | _ \| |
* / __| | | | |_) | |
* | (__| |_| | _ <| |___
* \___|\___/|_| \_\_____|
*
* Copyright (C) 1998 - 2009, Daniel Stenberg, <daniel@haxx.se>, et al.
*
* This software is licensed as described in the file COPYING, which
* you should have received as part of this distribution. The terms
* are also available at http://curl.haxx.se/docs/copyright.html.
*
* You may opt to use, copy, modify, merge, publish, distribute and/or sell
* copies of the Software, and permit persons to whom the Software is
* furnished to do so, under the terms of the COPYING file.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
* $Id: typecheck-gcc.h,v 1.9 2009-01-25 23:26:31 bagder Exp $
***************************************************************************/
/* wraps curl_easy_setopt() with typechecking */
/* To add a new kind of warning, add an
* if(_curl_is_sometype_option(_curl_opt) && ! _curl_is_sometype(value))
* _curl_easy_setopt_err_sometype();
* block and define _curl_is_sometype_option, _curl_is_sometype and
* _curl_easy_setopt_err_sometype below
*
* To add an option that uses the same type as an existing option, you'll just
* need to extend the appropriate _curl_*_option macro
*/
#define curl_easy_setopt(handle, option, value) \
__extension__ ({ \
__typeof__ (option) _curl_opt = option; \
if (__builtin_constant_p(_curl_opt)) { \
if (_curl_is_long_option(_curl_opt) && !_curl_is_long(value)) \
_curl_easy_setopt_err_long(); \
if (_curl_is_off_t_option(_curl_opt) && !_curl_is_off_t(value)) \
_curl_easy_setopt_err_curl_off_t(); \
if (_curl_is_string_option(_curl_opt) && !_curl_is_string(value)) \
_curl_easy_setopt_err_string(); \
if (_curl_is_write_cb_option(_curl_opt) && !_curl_is_write_cb(value)) \
_curl_easy_setopt_err_write_callback(); \
if ((_curl_opt) == CURLOPT_READFUNCTION && !_curl_is_read_cb(value)) \
_curl_easy_setopt_err_read_cb(); \
if ((_curl_opt) == CURLOPT_IOCTLFUNCTION && !_curl_is_ioctl_cb(value)) \
_curl_easy_setopt_err_ioctl_cb(); \
if ((_curl_opt) == CURLOPT_SOCKOPTFUNCTION && !_curl_is_sockopt_cb(value))\
_curl_easy_setopt_err_sockopt_cb(); \
if ((_curl_opt) == CURLOPT_OPENSOCKETFUNCTION && \
!_curl_is_opensocket_cb(value)) \
_curl_easy_setopt_err_opensocket_cb(); \
if ((_curl_opt) == CURLOPT_PROGRESSFUNCTION && \
!_curl_is_progress_cb(value)) \
_curl_easy_setopt_err_progress_cb(); \
if ((_curl_opt) == CURLOPT_DEBUGFUNCTION && !_curl_is_debug_cb(value)) \
_curl_easy_setopt_err_debug_cb(); \
if ((_curl_opt) == CURLOPT_SSL_CTX_FUNCTION && \
!_curl_is_ssl_ctx_cb(value)) \
_curl_easy_setopt_err_ssl_ctx_cb(); \
if (_curl_is_conv_cb_option(_curl_opt) && !_curl_is_conv_cb(value)) \
_curl_easy_setopt_err_conv_cb(); \
if ((_curl_opt) == CURLOPT_SEEKFUNCTION && !_curl_is_seek_cb(value)) \
_curl_easy_setopt_err_seek_cb(); \
if (_curl_is_cb_data_option(_curl_opt) && !_curl_is_cb_data(value)) \
_curl_easy_setopt_err_cb_data(); \
if ((_curl_opt) == CURLOPT_ERRORBUFFER && !_curl_is_error_buffer(value)) \
_curl_easy_setopt_err_error_buffer(); \
if ((_curl_opt) == CURLOPT_STDERR && !_curl_is_FILE(value)) \
_curl_easy_setopt_err_FILE(); \
if (_curl_is_postfields_option(_curl_opt) && !_curl_is_postfields(value)) \
_curl_easy_setopt_err_postfields(); \
if ((_curl_opt) == CURLOPT_HTTPPOST && \
!_curl_is_arr((value), struct curl_httppost)) \
_curl_easy_setopt_err_curl_httpost(); \
if (_curl_is_slist_option(_curl_opt) && \
!_curl_is_arr((value), struct curl_slist)) \
_curl_easy_setopt_err_curl_slist(); \
if ((_curl_opt) == CURLOPT_SHARE && !_curl_is_ptr((value), CURLSH)) \
_curl_easy_setopt_err_CURLSH(); \
} \
curl_easy_setopt(handle, _curl_opt, value); \
})
/* wraps curl_easy_getinfo() with typechecking */
/* FIXME: don't allow const pointers */
#define curl_easy_getinfo(handle, info, arg) \
__extension__ ({ \
__typeof__ (info) _curl_info = info; \
if (__builtin_constant_p(_curl_info)) { \
if (_curl_is_string_info(_curl_info) && !_curl_is_arr((arg), char *)) \
_curl_easy_getinfo_err_string(); \
if (_curl_is_long_info(_curl_info) && !_curl_is_arr((arg), long)) \
_curl_easy_getinfo_err_long(); \
if (_curl_is_double_info(_curl_info) && !_curl_is_arr((arg), double)) \
_curl_easy_getinfo_err_double(); \
if (_curl_is_slist_info(_curl_info) && \
!_curl_is_arr((arg), struct curl_slist *)) \
_curl_easy_getinfo_err_curl_slist(); \
} \
curl_easy_getinfo(handle, _curl_info, arg); \
})
/* TODO: typechecking for curl_share_setopt() and curl_multi_setopt(),
* for now just make sure that the functions are called with three
* arguments
*/
#define curl_share_setopt(share,opt,param) curl_share_setopt(share,opt,param)
#define curl_multi_setopt(handle,opt,param) curl_multi_setopt(handle,opt,param)
/* the actual warnings, triggered by calling the _curl_easy_setopt_err*
* functions */
/* To define a new warning, use _CURL_WARNING(identifier, "message") */
#define _CURL_WARNING(id, message) \
static void __attribute__((warning(message))) __attribute__((unused)) \
__attribute__((noinline)) id(void) { __asm__(""); }
_CURL_WARNING(_curl_easy_setopt_err_long,
"curl_easy_setopt expects a long argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_off_t,
"curl_easy_setopt expects a curl_off_t argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_string,
"curl_easy_setopt expects a string (char* or char[]) argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_write_callback,
"curl_easy_setopt expects a curl_write_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_read_cb,
"curl_easy_setopt expects a curl_read_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ioctl_cb,
"curl_easy_setopt expects a curl_ioctl_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_sockopt_cb,
"curl_easy_setopt expects a curl_sockopt_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_opensocket_cb,
"curl_easy_setopt expects a curl_opensocket_callback argument for this option"
)
_CURL_WARNING(_curl_easy_setopt_err_progress_cb,
"curl_easy_setopt expects a curl_progress_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_debug_cb,
"curl_easy_setopt expects a curl_debug_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_ssl_ctx_cb,
"curl_easy_setopt expects a curl_ssl_ctx_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_conv_cb,
"curl_easy_setopt expects a curl_conv_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_seek_cb,
"curl_easy_setopt expects a curl_seek_callback argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_cb_data,
"curl_easy_setopt expects a private data pointer as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_error_buffer,
"curl_easy_setopt expects a char buffer of CURL_ERROR_SIZE as argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_FILE,
"curl_easy_setopt expects a FILE* argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_postfields,
"curl_easy_setopt expects a void* or char* argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_httpost,
"curl_easy_setopt expects a struct curl_httppost* argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_curl_slist,
"curl_easy_setopt expects a struct curl_slist* argument for this option")
_CURL_WARNING(_curl_easy_setopt_err_CURLSH,
"curl_easy_setopt expects a CURLSH* argument for this option")
_CURL_WARNING(_curl_easy_getinfo_err_string,
"curl_easy_getinfo expects a pointer to char * for this info")
_CURL_WARNING(_curl_easy_getinfo_err_long,
"curl_easy_getinfo expects a pointer to long for this info")
_CURL_WARNING(_curl_easy_getinfo_err_double,
"curl_easy_getinfo expects a pointer to double for this info")
_CURL_WARNING(_curl_easy_getinfo_err_curl_slist,
"curl_easy_getinfo expects a pointer to struct curl_slist * for this info")
/* groups of curl_easy_setops options that take the same type of argument */
/* To add a new option to one of the groups, just add
* (option) == CURLOPT_SOMETHING
* to the or-expression. If the option takes a long or curl_off_t, you don't
* have to do anything
*/
/* evaluates to true if option takes a long argument */
#define _curl_is_long_option(option) \
(0 < (option) && (option) < CURLOPTTYPE_OBJECTPOINT)
#define _curl_is_off_t_option(option) \
((option) > CURLOPTTYPE_OFF_T)
/* evaluates to true if option takes a char* argument */
#define _curl_is_string_option(option) \
((option) == CURLOPT_URL || \
(option) == CURLOPT_PROXY || \
(option) == CURLOPT_INTERFACE || \
(option) == CURLOPT_NETRC_FILE || \
(option) == CURLOPT_USERPWD || \
(option) == CURLOPT_USERNAME || \
(option) == CURLOPT_PASSWORD || \
(option) == CURLOPT_PROXYUSERPWD || \
(option) == CURLOPT_PROXYUSERNAME || \
(option) == CURLOPT_PROXYPASSWORD || \
(option) == CURLOPT_NOPROXY || \
(option) == CURLOPT_ENCODING || \
(option) == CURLOPT_REFERER || \
(option) == CURLOPT_USERAGENT || \
(option) == CURLOPT_COOKIE || \
(option) == CURLOPT_COOKIEFILE || \
(option) == CURLOPT_COOKIEJAR || \
(option) == CURLOPT_COOKIELIST || \
(option) == CURLOPT_FTPPORT || \
(option) == CURLOPT_FTP_ALTERNATIVE_TO_USER || \
(option) == CURLOPT_FTP_ACCOUNT || \
(option) == CURLOPT_RANGE || \
(option) == CURLOPT_CUSTOMREQUEST || \
(option) == CURLOPT_SSLCERT || \
(option) == CURLOPT_SSLCERTTYPE || \
(option) == CURLOPT_SSLKEY || \
(option) == CURLOPT_SSLKEYTYPE || \
(option) == CURLOPT_KEYPASSWD || \
(option) == CURLOPT_SSLENGINE || \
(option) == CURLOPT_CAINFO || \
(option) == CURLOPT_CAPATH || \
(option) == CURLOPT_RANDOM_FILE || \
(option) == CURLOPT_EGDSOCKET || \
(option) == CURLOPT_SSL_CIPHER_LIST || \
(option) == CURLOPT_KRBLEVEL || \
(option) == CURLOPT_SSH_HOST_PUBLIC_KEY_MD5 || \
(option) == CURLOPT_SSH_PUBLIC_KEYFILE || \
(option) == CURLOPT_SSH_PRIVATE_KEYFILE || \
(option) == CURLOPT_CRLFILE || \
(option) == CURLOPT_ISSUERCERT || \
0)
/* evaluates to true if option takes a curl_write_callback argument */
#define _curl_is_write_cb_option(option) \
((option) == CURLOPT_HEADERFUNCTION || \
(option) == CURLOPT_WRITEFUNCTION)
/* evaluates to true if option takes a curl_conv_callback argument */
#define _curl_is_conv_cb_option(option) \
((option) == CURLOPT_CONV_TO_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_NETWORK_FUNCTION || \
(option) == CURLOPT_CONV_FROM_UTF8_FUNCTION)
/* evaluates to true if option takes a data argument to pass to a callback */
#define _curl_is_cb_data_option(option) \
((option) == CURLOPT_WRITEDATA || \
(option) == CURLOPT_READDATA || \
(option) == CURLOPT_IOCTLDATA || \
(option) == CURLOPT_SOCKOPTDATA || \
(option) == CURLOPT_OPENSOCKETDATA || \
(option) == CURLOPT_PROGRESSDATA || \
(option) == CURLOPT_WRITEHEADER || \
(option) == CURLOPT_DEBUGDATA || \
(option) == CURLOPT_SSL_CTX_DATA || \
(option) == CURLOPT_SEEKDATA || \
(option) == CURLOPT_PRIVATE || \
0)
/* evaluates to true if option takes a POST data argument (void* or char*) */
#define _curl_is_postfields_option(option) \
((option) == CURLOPT_POSTFIELDS || \
(option) == CURLOPT_COPYPOSTFIELDS || \
0)
/* evaluates to true if option takes a struct curl_slist * argument */
#define _curl_is_slist_option(option) \
((option) == CURLOPT_HTTPHEADER || \
(option) == CURLOPT_HTTP200ALIASES || \
(option) == CURLOPT_QUOTE || \
(option) == CURLOPT_POSTQUOTE || \
(option) == CURLOPT_PREQUOTE || \
(option) == CURLOPT_TELNETOPTIONS || \
0)
/* groups of curl_easy_getinfo infos that take the same type of argument */
/* evaluates to true if info expects a pointer to char * argument */
#define _curl_is_string_info(info) \
(CURLINFO_STRING < (info) && (info) < CURLINFO_LONG)
/* evaluates to true if info expects a pointer to long argument */
#define _curl_is_long_info(info) \
(CURLINFO_LONG < (info) && (info) < CURLINFO_DOUBLE)
/* evaluates to true if info expects a pointer to double argument */
#define _curl_is_double_info(info) \
(CURLINFO_DOUBLE < (info) && (info) < CURLINFO_SLIST)
/* true if info expects a pointer to struct curl_slist * argument */
#define _curl_is_slist_info(info) \
(CURLINFO_SLIST < (info))
/* typecheck helpers -- check whether given expression has requested type*/
/* For pointers, you can use the _curl_is_ptr/_curl_is_arr macros,
* otherwise define a new macro. Search for __builtin_types_compatible_p
* in the GCC manual.
* NOTE: these macros MUST NOT EVALUATE their arguments! The argument is
* the actual expression passed to the curl_easy_setopt macro. This
* means that you can only apply the sizeof and __typeof__ operators, no
* == or whatsoever.
*/
/* XXX: should evaluate to true iff expr is a pointer */
#define _curl_is_any_ptr(expr) \
(sizeof(expr) == sizeof(void*))
/* evaluates to true if expr is NULL */
/* XXX: must not evaluate expr, so this check is not accurate */
#define _curl_is_NULL(expr) \
(__builtin_types_compatible_p(__typeof__(expr), __typeof__(NULL)))
/* evaluates to true if expr is type*, const type* or NULL */
#define _curl_is_ptr(expr, type) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), type *) || \
__builtin_types_compatible_p(__typeof__(expr), const type *))
/* evaluates to true if expr is one of type[], type*, NULL or const type* */
#define _curl_is_arr(expr, type) \
(_curl_is_ptr((expr), type) || \
__builtin_types_compatible_p(__typeof__(expr), type []))
/* evaluates to true if expr is a string */
#define _curl_is_string(expr) \
(_curl_is_arr((expr), char) || \
_curl_is_arr((expr), signed char) || \
_curl_is_arr((expr), unsigned char))
/* evaluates to true if expr is a long (no matter the signedness)
* XXX: for now, int is also accepted (and therefore short and char, which
* are promoted to int when passed to a variadic function) */
#define _curl_is_long(expr) \
(__builtin_types_compatible_p(__typeof__(expr), long) || \
__builtin_types_compatible_p(__typeof__(expr), signed long) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned long) || \
__builtin_types_compatible_p(__typeof__(expr), int) || \
__builtin_types_compatible_p(__typeof__(expr), signed int) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned int) || \
__builtin_types_compatible_p(__typeof__(expr), short) || \
__builtin_types_compatible_p(__typeof__(expr), signed short) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned short) || \
__builtin_types_compatible_p(__typeof__(expr), char) || \
__builtin_types_compatible_p(__typeof__(expr), signed char) || \
__builtin_types_compatible_p(__typeof__(expr), unsigned char))
/* evaluates to true if expr is of type curl_off_t */
#define _curl_is_off_t(expr) \
(__builtin_types_compatible_p(__typeof__(expr), curl_off_t))
/* evaluates to true if expr is abuffer suitable for CURLOPT_ERRORBUFFER */
/* XXX: also check size of an char[] array? */
#define _curl_is_error_buffer(expr) \
(__builtin_types_compatible_p(__typeof__(expr), char *) || \
__builtin_types_compatible_p(__typeof__(expr), char[]))
/* evaluates to true if expr is of type (const) void* or (const) FILE* */
#if 0
#define _curl_is_cb_data(expr) \
(_curl_is_ptr((expr), void) || \
_curl_is_ptr((expr), FILE))
#else /* be less strict */
#define _curl_is_cb_data(expr) \
_curl_is_any_ptr(expr)
#endif
/* evaluates to true if expr is of type FILE* */
#define _curl_is_FILE(expr) \
(__builtin_types_compatible_p(__typeof__(expr), FILE *))
/* evaluates to true if expr can be passed as POST data (void* or char*) */
#define _curl_is_postfields(expr) \
(_curl_is_ptr((expr), void) || \
_curl_is_arr((expr), char))
/* FIXME: the whole callback checking is messy...
* The idea is to tolerate char vs. void and const vs. not const
* pointers in arguments at least
*/
/* helper: __builtin_types_compatible_p distinguishes between functions and
* function pointers, hide it */
#define _curl_callback_compatible(func, type) \
(__builtin_types_compatible_p(__typeof__(func), type) || \
__builtin_types_compatible_p(__typeof__(func), type*))
/* evaluates to true if expr is of type curl_read_callback or "similar" */
#define _curl_is_read_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), __typeof__(fread)) || \
__builtin_types_compatible_p(__typeof__(expr), curl_read_callback) || \
_curl_callback_compatible((expr), _curl_read_callback1) || \
_curl_callback_compatible((expr), _curl_read_callback2) || \
_curl_callback_compatible((expr), _curl_read_callback3) || \
_curl_callback_compatible((expr), _curl_read_callback4) || \
_curl_callback_compatible((expr), _curl_read_callback5) || \
_curl_callback_compatible((expr), _curl_read_callback6))
typedef size_t (_curl_read_callback1)(char *, size_t, size_t, void*);
typedef size_t (_curl_read_callback2)(char *, size_t, size_t, const void*);
typedef size_t (_curl_read_callback3)(char *, size_t, size_t, FILE*);
typedef size_t (_curl_read_callback4)(void *, size_t, size_t, void*);
typedef size_t (_curl_read_callback5)(void *, size_t, size_t, const void*);
typedef size_t (_curl_read_callback6)(void *, size_t, size_t, FILE*);
/* evaluates to true if expr is of type curl_write_callback or "similar" */
#define _curl_is_write_cb(expr) \
(_curl_is_read_cb(expr) || \
__builtin_types_compatible_p(__typeof__(expr), __typeof__(fwrite)) || \
__builtin_types_compatible_p(__typeof__(expr), curl_write_callback) || \
_curl_callback_compatible((expr), _curl_write_callback1) || \
_curl_callback_compatible((expr), _curl_write_callback2) || \
_curl_callback_compatible((expr), _curl_write_callback3) || \
_curl_callback_compatible((expr), _curl_write_callback4) || \
_curl_callback_compatible((expr), _curl_write_callback5) || \
_curl_callback_compatible((expr), _curl_write_callback6))
typedef size_t (_curl_write_callback1)(const char *, size_t, size_t, void*);
typedef size_t (_curl_write_callback2)(const char *, size_t, size_t,
const void*);
typedef size_t (_curl_write_callback3)(const char *, size_t, size_t, FILE*);
typedef size_t (_curl_write_callback4)(const void *, size_t, size_t, void*);
typedef size_t (_curl_write_callback5)(const void *, size_t, size_t,
const void*);
typedef size_t (_curl_write_callback6)(const void *, size_t, size_t, FILE*);
/* evaluates to true if expr is of type curl_ioctl_callback or "similar" */
#define _curl_is_ioctl_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_ioctl_callback) || \
_curl_callback_compatible((expr), _curl_ioctl_callback1) || \
_curl_callback_compatible((expr), _curl_ioctl_callback2) || \
_curl_callback_compatible((expr), _curl_ioctl_callback3) || \
_curl_callback_compatible((expr), _curl_ioctl_callback4))
typedef curlioerr (_curl_ioctl_callback1)(CURL *, int, void*);
typedef curlioerr (_curl_ioctl_callback2)(CURL *, int, const void*);
typedef curlioerr (_curl_ioctl_callback3)(CURL *, curliocmd, void*);
typedef curlioerr (_curl_ioctl_callback4)(CURL *, curliocmd, const void*);
/* evaluates to true if expr is of type curl_sockopt_callback or "similar" */
#define _curl_is_sockopt_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_sockopt_callback) || \
_curl_callback_compatible((expr), _curl_sockopt_callback1) || \
_curl_callback_compatible((expr), _curl_sockopt_callback2))
typedef int (_curl_sockopt_callback1)(void *, curl_socket_t, curlsocktype);
typedef int (_curl_sockopt_callback2)(const void *, curl_socket_t,
curlsocktype);
/* evaluates to true if expr is of type curl_opensocket_callback or "similar" */
#define _curl_is_opensocket_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_opensocket_callback) ||\
_curl_callback_compatible((expr), _curl_opensocket_callback1) || \
_curl_callback_compatible((expr), _curl_opensocket_callback2) || \
_curl_callback_compatible((expr), _curl_opensocket_callback3) || \
_curl_callback_compatible((expr), _curl_opensocket_callback4))
typedef curl_socket_t (_curl_opensocket_callback1)
(void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (_curl_opensocket_callback2)
(void *, curlsocktype, const struct curl_sockaddr *);
typedef curl_socket_t (_curl_opensocket_callback3)
(const void *, curlsocktype, struct curl_sockaddr *);
typedef curl_socket_t (_curl_opensocket_callback4)
(const void *, curlsocktype, const struct curl_sockaddr *);
/* evaluates to true if expr is of type curl_progress_callback or "similar" */
#define _curl_is_progress_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_progress_callback) || \
_curl_callback_compatible((expr), _curl_progress_callback1) || \
_curl_callback_compatible((expr), _curl_progress_callback2))
typedef int (_curl_progress_callback1)(void *,
double, double, double, double);
typedef int (_curl_progress_callback2)(const void *,
double, double, double, double);
/* evaluates to true if expr is of type curl_debug_callback or "similar" */
#define _curl_is_debug_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_debug_callback) || \
_curl_callback_compatible((expr), _curl_debug_callback1) || \
_curl_callback_compatible((expr), _curl_debug_callback2) || \
_curl_callback_compatible((expr), _curl_debug_callback3) || \
_curl_callback_compatible((expr), _curl_debug_callback4))
typedef int (_curl_debug_callback1) (CURL *,
curl_infotype, char *, size_t, void *);
typedef int (_curl_debug_callback2) (CURL *,
curl_infotype, char *, size_t, const void *);
typedef int (_curl_debug_callback3) (CURL *,
curl_infotype, const char *, size_t, void *);
typedef int (_curl_debug_callback4) (CURL *,
curl_infotype, const char *, size_t, const void *);
/* evaluates to true if expr is of type curl_ssl_ctx_callback or "similar" */
/* this is getting even messier... */
#define _curl_is_ssl_ctx_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_ssl_ctx_callback) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback1) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback2) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback3) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback4) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback5) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback6) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback7) || \
_curl_callback_compatible((expr), _curl_ssl_ctx_callback8))
typedef CURLcode (_curl_ssl_ctx_callback1)(CURL *, void *, void *);
typedef CURLcode (_curl_ssl_ctx_callback2)(CURL *, void *, const void *);
typedef CURLcode (_curl_ssl_ctx_callback3)(CURL *, const void *, void *);
typedef CURLcode (_curl_ssl_ctx_callback4)(CURL *, const void *, const void *);
#ifdef HEADER_SSL_H
/* hack: if we included OpenSSL's ssl.h, we know about SSL_CTX
* this will of course break if we're included before OpenSSL headers...
*/
typedef CURLcode (_curl_ssl_ctx_callback5)(CURL *, SSL_CTX, void *);
typedef CURLcode (_curl_ssl_ctx_callback6)(CURL *, SSL_CTX, const void *);
typedef CURLcode (_curl_ssl_ctx_callback7)(CURL *, const SSL_CTX, void *);
typedef CURLcode (_curl_ssl_ctx_callback8)(CURL *, const SSL_CTX, const void *);
#else
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback5;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback6;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback7;
typedef _curl_ssl_ctx_callback1 _curl_ssl_ctx_callback8;
#endif
/* evaluates to true if expr is of type curl_conv_callback or "similar" */
#define _curl_is_conv_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_conv_callback) || \
_curl_callback_compatible((expr), _curl_conv_callback1) || \
_curl_callback_compatible((expr), _curl_conv_callback2) || \
_curl_callback_compatible((expr), _curl_conv_callback3) || \
_curl_callback_compatible((expr), _curl_conv_callback4))
typedef CURLcode (*_curl_conv_callback1)(char *, size_t length);
typedef CURLcode (*_curl_conv_callback2)(const char *, size_t length);
typedef CURLcode (*_curl_conv_callback3)(void *, size_t length);
typedef CURLcode (*_curl_conv_callback4)(const void *, size_t length);
/* evaluates to true if expr is of type curl_seek_callback or "similar" */
#define _curl_is_seek_cb(expr) \
(_curl_is_NULL(expr) || \
__builtin_types_compatible_p(__typeof__(expr), curl_seek_callback) || \
_curl_callback_compatible((expr), _curl_seek_callback1) || \
_curl_callback_compatible((expr), _curl_seek_callback2))
typedef CURLcode (*_curl_seek_callback1)(void *, curl_off_t, int);
typedef CURLcode (*_curl_seek_callback2)(const void *, curl_off_t, int);
#endif /* __CURL_TYPECHECK_GCC_H */

View file

@ -0,0 +1 @@
/* not used */

View file

@ -0,0 +1,137 @@
The "Clarified Artistic License"
Preamble
The intent of this document is to state the conditions under which a
Package may be copied, such that the Copyright Holder maintains some
semblance of artistic control over the development of the package,
while giving the users of the package the right to use and distribute
the Package in a more-or-less customary fashion, plus the right to make
reasonable modifications.
Definitions:
"Package" refers to the collection of files distributed by the
Copyright Holder, and derivatives of that collection of files
created through textual modification.
"Standard Version" refers to such a Package if it has not been
modified, or has been modified in accordance with the wishes
of the Copyright Holder as specified below.
"Copyright Holder" is whoever is named in the copyright or
copyrights for the package.
"You" is you, if you're thinking about copying or distributing
this Package.
"Distribution fee" is a fee you charge for providing a copy of this
Package to another party.
"Freely Available" means that no fee is charged for the right to use
the item, though there may be fees involved in handling the item.
1. You may make and give away verbatim copies of the source form of the
Standard Version of this Package without restriction, provided that you
duplicate all of the original copyright notices and associated disclaimers.
2. You may apply bug fixes, portability fixes and other modifications
derived from the Public Domain, or those made Freely Available, or from
the Copyright Holder. A Package modified in such a way shall still be
considered the Standard Version.
3. You may otherwise modify your copy of this Package in any way, provided
that you insert a prominent notice in each changed file stating how and
when you changed that file, and provided that you do at least ONE of the
following:
a) place your modifications in the Public Domain or otherwise make them
Freely Available, such as by posting said modifications to Usenet or
an equivalent medium, or placing the modifications on a major archive
site allowing unrestricted access to them, or by allowing the Copyright
Holder to include your modifications in the Standard Version of the
Package.
b) use the modified Package only within your corporation or organization.
c) rename any non-standard executables so the names do not conflict
with standard executables, which must also be provided, and provide
a separate manual page for each non-standard executable that clearly
documents how it differs from the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) permit and encourge anyone who receives a copy of the modified Package
permission to make your modifications Freely Available in some specific
way.
4. You may distribute the programs of this Package in object code or
executable form, provided that you do at least ONE of the following:
a) distribute a Standard Version of the executables and library files,
together with instructions (in the manual page or equivalent) on where
to get the Standard Version.
b) accompany the distribution with the machine-readable source of
the Package with your modifications.
c) give non-standard executables non-standard names, and clearly
document the differences in manual pages (or equivalent), together
with instructions on where to get the Standard Version.
d) make other distribution arrangements with the Copyright Holder.
e) offer the machine-readable source of the Package, with your
modifications, by mail order.
5. You may charge a distribution fee for any distribution of this Package.
If you offer support for this Package, you may charge any fee you choose
for that support. You may not charge a license fee for the right to use
this Package itself. You may distribute this Package in aggregate with
other (possibly commercial and possibly nonfree) programs as part of a
larger (possibly commercial and possibly nonfree) software distribution,
and charge license fees for other parts of that software distribution,
provided that you do not advertise this Package as a product of your own.
If the Package includes an interpreter, You may embed this Package's
interpreter within an executable of yours (by linking); this shall be
construed as a mere form of aggregation, provided that the complete
Standard Version of the interpreter is so embedded.
6. The scripts and library files supplied as input to or produced as
output from the programs of this Package do not automatically fall
under the copyright of this Package, but belong to whoever generated
them, and may be sold commercially, and may be aggregated with this
Package. If such scripts or library files are aggregated with this
Package via the so-called "undump" or "unexec" methods of producing a
binary executable image, then distribution of such an image shall
neither be construed as a distribution of this Package nor shall it
fall under the restrictions of Paragraphs 3 and 4, provided that you do
not represent such an executable image as a Standard Version of this
Package.
7. C subroutines (or comparably compiled subroutines in other
languages) supplied by you and linked into this Package in order to
emulate subroutines and variables of the language defined by this
Package shall not be considered part of this Package, but are the
equivalent of input as in Paragraph 6, provided these subroutines do
not change the language in any way that would cause it to fail the
regression tests for the language.
8. Aggregation of the Standard Version of the Package with a commercial
distribution is always permitted provided that the use of this Package is
embedded; that is, when no overt attempt is made to make this Package's
interfaces visible to the end user of the commercial distribution.
Such use shall not be construed as a distribution of this Package.
9. The name of the Copyright Holder may not be used to endorse or promote
products derived from this software without specific prior written permission.
10. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
The End

View file

@ -0,0 +1,43 @@
include_HEADERS = libdis.h
lib_LTLIBRARIES = libdisasm.la
libdisasm_la_SOURCES = \
ia32_implicit.c \
ia32_implicit.h \
ia32_insn.c \
ia32_insn.h \
ia32_invariant.c \
ia32_invariant.h \
ia32_modrm.c \
ia32_modrm.h \
ia32_opcode_tables.c \
ia32_opcode_tables.h \
ia32_operand.c \
ia32_operand.h \
ia32_reg.c \
ia32_reg.h \
ia32_settings.c \
ia32_settings.h \
libdis.h \
qword.h \
x86_disasm.c \
x86_format.c \
x86_imm.c \
x86_imm.h \
x86_insn.c \
x86_misc.c \
x86_operand_list.c \
x86_operand_list.h
# Cheat to get non-autoconf swig into tarball,
# even if it doesn't build by default.
EXTRA_DIST = \
swig/Makefile \
swig/libdisasm.i \
swig/libdisasm_oop.i \
swig/python/Makefile-swig \
swig/perl/Makefile-swig \
swig/perl/Makefile.PL \
swig/ruby/Makefile-swig \
swig/ruby/extconf.rb \
swig/tcl/Makefile-swig \
swig/README

View file

@ -0,0 +1,9 @@
Name: libdisasm
URL: https://sourceforge.net/projects/bastard/files/libdisasm/0.23/libdisasm-0.23.tar.gz/download
Version: 0.23
License: Clarified-Artistic
License File: LICENSE
Description:
This contains a copy of libdisasm. It is no longer under development upstream,
so we keep a copy here to maintain fixes ourselves.

View file

@ -0,0 +1,43 @@
x86_format.c
------------
intel: jmpf -> jmp, callf -> call
att: jmpf -> ljmp, callf -> lcall
opcode table
------------
finish typing instructions
fix flag clear/set/toggle types
ix64 stuff
----------
document output file formats in web page
features doc: register aliases, implicit operands, stack mods,
ring0 flags, eflags, cpu model/isa
ia32_handle_* implementation
fix operand 0F C2
CMPPS
* sysenter, sysexit as CALL types -- preceded by MSR writes
* SYSENTER/SYSEXIT stack : overwrites SS, ESP
* stos, cmps, scas, movs, ins, outs, lods -> OP_PTR
* OP_SIZE in implicit operands
* use OP_SIZE to choose reg sizes!
DONE?? :
implicit operands: provide action ?
e.g. add/inc for stach, write, etc
replace table numbers in opcodes.dat with
#defines for table names
replace 0 with INSN_INVALID [or maybe FF for imnvalid and 00 for Not Applicable */
no wait that is only for prefix tables -- n/p
if ( prefx) only use if insn != invalid
these should cover all the wacky disasm exceptions
for the rep one we can chet, match only a 0x90
todo: privilege | ring

View file

@ -0,0 +1,422 @@
#include <stdlib.h>
#include "ia32_implicit.h"
#include "ia32_insn.h"
#include "ia32_reg.h"
#include "x86_operand_list.h"
/* Conventions: Register operands which are aliases of another register
* operand (e.g. AX in one operand and AL in another) assume that the
* operands are different registers and that alias tracking will resolve
* data flow. This means that something like
* mov ax, al
* would have 'write only' access for AX and 'read only' access for AL,
* even though both AL and AX are read and written */
typedef struct {
uint32_t type;
uint32_t operand;
} op_implicit_list_t;
static op_implicit_list_t list_aaa[] =
/* 37 : AAA : rw AL */
/* 3F : AAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* aaa */
static op_implicit_list_t list_aad[] =
/* D5 0A, D5 (ib) : AAD : rw AX */
/* D4 0A, D4 (ib) : AAM : rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET }, {0}}; /* aad */
static op_implicit_list_t list_call[] =
/* E8, FF, 9A, FF : CALL : rw ESP, rw EIP */
/* C2, C3, CA, CB : RET : rw ESP, rw EIP */
{{ OP_R | OP_W, REG_EIP_INDEX },
{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* call, ret */
static op_implicit_list_t list_cbw[] =
/* 98 : CBW : r AL, rw AX */
{{ OP_R | OP_W, REG_WORD_OFFSET },
{ OP_R, REG_BYTE_OFFSET}, {0}}; /* cbw */
static op_implicit_list_t list_cwde[] =
/* 98 : CWDE : r AX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_R, REG_WORD_OFFSET }, {0}}; /* cwde */
static op_implicit_list_t list_clts[] =
/* 0F 06 : CLTS : rw CR0 */
{{ OP_R | OP_W, REG_CTRL_OFFSET}, {0}}; /* clts */
static op_implicit_list_t list_cmpxchg[] =
/* 0F B0 : CMPXCHG : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchgb[] =
/* 0F B1 : CMPXCHG : rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* cmpxchg */
static op_implicit_list_t list_cmpxchg8b[] =
/* 0F C7 : CMPXCHG8B : rw EDX, rw EAX, r ECX, r EBX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_R, REG_DWORD_OFFSET + 3 }, {0}}; /* cmpxchg8b */
static op_implicit_list_t list_cpuid[] =
/* 0F A2 : CPUID : rw EAX, w EBX, w ECX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 3 }, {0}}; /* cpuid */
static op_implicit_list_t list_cwd[] =
/* 99 : CWD/CWQ : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* cwd */
static op_implicit_list_t list_daa[] =
/* 27 : DAA : rw AL */
/* 2F : DAS : rw AL */
{{ OP_R | OP_W, REG_BYTE_OFFSET }, {0}}; /* daa */
static op_implicit_list_t list_idiv[] =
/* F6 : DIV, IDIV : r AX, w AL, w AH */
/* FIXED: first op was EAX, not Aw. TODO: verify! */
{{ OP_R, REG_WORD_OFFSET },
{ OP_W, REG_BYTE_OFFSET },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* div */
static op_implicit_list_t list_div[] =
/* F7 : DIV, IDIV : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* div */
static op_implicit_list_t list_enter[] =
/* C8 : ENTER : rw ESP w EBP */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 4 },
{ OP_R, REG_DWORD_OFFSET + 5 }, {0}}; /* enter */
static op_implicit_list_t list_f2xm1[] =
/* D9 F0 : F2XM1 : rw ST(0) */
/* D9 E1 : FABS : rw ST(0) */
/* D9 E0 : FCHS : rw ST(0) */
/* D9 FF : FCOS : rw ST(0)*/
/* D8, DA : FDIV : rw ST(0) */
/* D8, DA : FDIVR : rw ST(0) */
/* D9 F2 : FPTAN : rw ST(0) */
/* D9 FC : FRNDINT : rw ST(0) */
/* D9 FB : FSINCOS : rw ST(0) */
/* D9 FE : FSIN : rw ST(0) */
/* D9 FA : FSQRT : rw ST(0) */
/* D9 F4 : FXTRACT : rw ST(0) */
{{ OP_R | OP_W, REG_FPU_OFFSET }, {0}}; /* f2xm1 */
static op_implicit_list_t list_fcom[] =
/* D8, DC, DE D9 : FCOM : r ST(0) */
/* DE, DA : FICOM : r ST(0) */
/* DF, D8 : FIST : r ST(0) */
/* D9 E4 : FTST : r ST(0) */
/* D9 E5 : FXAM : r ST(0) */
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fcom */
static op_implicit_list_t list_fpatan[] =
/* D9 F3 : FPATAN : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET }, {0}}; /* fpatan */
static op_implicit_list_t list_fprem[] =
/* D9 F8, D9 F5 : FPREM : rw ST(0) r ST(1) */
/* D9 FD : FSCALE : rw ST(0), r ST(1) */
{{ OP_R | OP_W, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fprem */
static op_implicit_list_t list_faddp[] =
/* DE C1 : FADDP : r ST(0), rw ST(1) */
/* DE E9 : FSUBP : r ST(0), rw ST(1) */
/* D9 F1 : FYL2X : r ST(0), rw ST(1) */
/* D9 F9 : FYL2XP1 : r ST(0), rw ST(1) */
{{ OP_R, REG_FPU_OFFSET },
{ OP_R | OP_W, REG_FPU_OFFSET + 1 }, {0}}; /* faddp */
static op_implicit_list_t list_fucompp[] =
/* DA E9 : FUCOMPP : r ST(0), r ST(1) */
{{ OP_R, REG_FPU_OFFSET },
{ OP_R, REG_FPU_OFFSET + 1 }, {0}}; /* fucompp */
static op_implicit_list_t list_imul[] =
/* F6 : IMUL : r AL, w AX */
/* F6 : MUL : r AL, w AX */
{{ OP_R, REG_BYTE_OFFSET },
{ OP_W, REG_WORD_OFFSET }, {0}}; /* imul */
static op_implicit_list_t list_mul[] =
/* F7 : IMUL : rw EAX, w EDX */
/* F7 : MUL : rw EAX, w EDX */
{{ OP_R | OP_W, REG_DWORD_OFFSET },
{ OP_W, REG_DWORD_OFFSET + 2 }, {0}}; /* imul */
static op_implicit_list_t list_lahf[] =
/* 9F : LAHF : r EFLAGS, w AH */
{{ OP_R, REG_FLAGS_INDEX },
{ OP_W, REG_BYTE_OFFSET + 4 }, {0}}; /* lahf */
static op_implicit_list_t list_ldmxcsr[] =
/* 0F AE : LDMXCSR : w MXCSR SSE Control Status Reg */
{{ OP_W, REG_MXCSG_INDEX }, {0}}; /* ldmxcsr */
static op_implicit_list_t list_leave[] =
/* C9 : LEAVE : rw ESP, w EBP */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_DWORD_OFFSET + 5 }, {0}}; /* leave */
static op_implicit_list_t list_lgdt[] =
/* 0F 01 : LGDT : w GDTR */
{{ OP_W, REG_GDTR_INDEX }, {0}}; /* lgdt */
static op_implicit_list_t list_lidt[] =
/* 0F 01 : LIDT : w IDTR */
{{ OP_W, REG_IDTR_INDEX }, {0}}; /* lidt */
static op_implicit_list_t list_lldt[] =
/* 0F 00 : LLDT : w LDTR */
{{ OP_W, REG_LDTR_INDEX }, {0}}; /* lldt */
static op_implicit_list_t list_lmsw[] =
/* 0F 01 : LMSW : w CR0 */
{{ OP_W, REG_CTRL_OFFSET }, {0}}; /* lmsw */
static op_implicit_list_t list_loop[] =
/* E0, E1, E2 : LOOP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* loop */
static op_implicit_list_t list_ltr[] =
/* 0F 00 : LTR : w Task Register */
{{ OP_W, REG_TR_INDEX }, {0}}; /* ltr */
static op_implicit_list_t list_pop[] =
/* 8F, 58, 1F, 07, 17, 0F A1, 0F A9 : POP : rw ESP */
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
{{ OP_R | OP_W, REG_ESP_INDEX }, {0}}; /* pop, push */
static op_implicit_list_t list_popad[] =
/* 61 : POPAD : rw esp, w edi esi ebp ebx edx ecx eax */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_DWORD_OFFSET + 7 },
{ OP_W, REG_DWORD_OFFSET + 6 },
{ OP_W, REG_DWORD_OFFSET + 5 },
{ OP_W, REG_DWORD_OFFSET + 3 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* popad */
static op_implicit_list_t list_popfd[] =
/* 9D : POPFD : rw esp, w eflags */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_W, REG_FLAGS_INDEX }, {0}}; /* popfd */
static op_implicit_list_t list_pushad[] =
/* FF, 50, 6A, 68, 0E, 16, 1E, 06, 0F A0, 0F A8 : PUSH : rw ESP */
/* 60 : PUSHAD : rw esp, r eax ecx edx ebx esp ebp esi edi */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_R, REG_DWORD_OFFSET },
{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_R, REG_DWORD_OFFSET + 2 },
{ OP_R, REG_DWORD_OFFSET + 3 },
{ OP_R, REG_DWORD_OFFSET + 5 },
{ OP_R, REG_DWORD_OFFSET + 6 },
{ OP_R, REG_DWORD_OFFSET + 7 }, {0}}; /* pushad */
static op_implicit_list_t list_pushfd[] =
/* 9C : PUSHFD : rw esp, r eflags */
{{ OP_R | OP_W, REG_ESP_INDEX },
{ OP_R, REG_FLAGS_INDEX }, {0}}; /* pushfd */
static op_implicit_list_t list_rdmsr[] =
/* 0F 32 : RDMSR : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdmsr */
static op_implicit_list_t list_rdpmc[] =
/* 0F 33 : RDPMC : r ECX, w EDX, w EAX */
{{ OP_R, REG_DWORD_OFFSET + 1 },
{ OP_W, REG_DWORD_OFFSET + 2 },
{ OP_W, REG_DWORD_OFFSET }, {0}}; /* rdpmc */
static op_implicit_list_t list_rdtsc[] =
/* 0F 31 : RDTSC : rw EDX, rw EAX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 2 },
{ OP_R | OP_W, REG_DWORD_OFFSET }, {0}}; /* rdtsc */
static op_implicit_list_t list_rep[] =
/* F3, F2 ... : REP : rw ECX */
{{ OP_R | OP_W, REG_DWORD_OFFSET + 1 }, {0}};/* rep */
static op_implicit_list_t list_rsm[] =
/* 0F AA : RSM : r CR4, r CR0 */
{{ OP_R, REG_CTRL_OFFSET + 4 },
{ OP_R, REG_CTRL_OFFSET }, {0}}; /* rsm */
static op_implicit_list_t list_sahf[] =
/* 9E : SAHF : r ah, rw eflags (set SF ZF AF PF CF) */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sahf */
static op_implicit_list_t list_sgdt[] =
/* 0F : SGDT : r gdtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sgdt */
static op_implicit_list_t list_sidt[] =
/* 0F : SIDT : r idtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sidt */
static op_implicit_list_t list_sldt[] =
/* 0F : SLDT : r ldtr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sldt */
static op_implicit_list_t list_smsw[] =
/* 0F : SMSW : r CR0 */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* smsw */
static op_implicit_list_t list_stmxcsr[] =
/* 0F AE : STMXCSR : r MXCSR */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* stmxcsr */
static op_implicit_list_t list_str[] =
/* 0F 00 : STR : r TR (task register) */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* str */
static op_implicit_list_t list_sysenter[] =
/* 0F 34 : SYSENTER : w cs, w eip, w ss, w esp, r CR0, w eflags
* r sysenter_cs_msr, sysenter_esp_msr, sysenter_eip_msr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysenter */
static op_implicit_list_t list_sysexit[] =
/* 0F 35 : SYSEXIT : r edx, r ecx, w cs, w eip, w ss, w esp
* r sysenter_cs_msr */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* sysexit */
static op_implicit_list_t list_wrmsr[] =
/* 0F 30 : WRMST : r edx, r eax, r ecx */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* wrmsr */
static op_implicit_list_t list_xlat[] =
/* D7 : XLAT : rw al r ebx (ptr) */
/* TODO: finish this! */
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* xlat */
/* TODO:
* monitor 0f 01 c8 eax OP_R ecx OP_R edx OP_R
* mwait 0f 01 c9 eax OP_R ecx OP_R
*/
static op_implicit_list_t list_monitor[] =
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* monitor */
static op_implicit_list_t list_mwait[] =
{{ OP_R, REG_DWORD_OFFSET }, {0}}; /* mwait */
op_implicit_list_t *op_implicit_list[] = {
/* This is a list of implicit operands which are read/written by
* various x86 instructions. Note that modifications to the stack
* register are mentioned here, but that additional information on
* the effect an instruction has on the stack is contained in the
* x86_insn_t 'stack_mod' and 'stack_mod_val' fields. Use of the
* eflags register, i.e. setting, clearing, and testing flags, is
* not recorded here but rather in the flags_set and flags_tested
* fields of the x86_insn_t.*/
NULL,
list_aaa, list_aad, list_call, list_cbw, /* 1 - 4 */
list_cwde, list_clts, list_cmpxchg, list_cmpxchgb, /* 5 - 8 */
list_cmpxchg8b, list_cpuid, list_cwd, list_daa, /* 9 - 12 */
list_idiv, list_div, list_enter, list_f2xm1, /* 13 - 16 */
list_fcom, list_fpatan, list_fprem, list_faddp, /* 17 - 20 */
list_fucompp, list_imul, list_mul, list_lahf, /* 21 - 24 */
list_ldmxcsr, list_leave, list_lgdt, list_lidt, /* 25 - 28 */
list_lldt, list_lmsw, list_loop, list_ltr, /* 29 - 32 */
list_pop, list_popad, list_popfd, list_pushad, /* 33 - 36 */
list_pushfd, list_rdmsr, list_rdpmc, list_rdtsc, /* 37 - 40 */
/* NOTE: 'REP' is a hack since it is a prefix: if its position
* in the table changes, then change IDX_IMPLICIT_REP in the .h */
list_rep, list_rsm, list_sahf, list_sgdt, /* 41 - 44 */
list_sidt, list_sldt, list_smsw, list_stmxcsr, /* 45 - 48 */
list_str, list_sysenter, list_sysexit, list_wrmsr, /* 49 - 52 */
list_xlat, list_monitor, list_mwait, /* 53 - 55*/
NULL /* end of list */
};
#define LAST_IMPL_IDX 55
static void handle_impl_reg( x86_op_t *op, uint32_t val ) {
x86_reg_t *reg = &op->data.reg;
op->type = op_register;
ia32_handle_register( reg, (unsigned int) val );
switch (reg->size) {
case 1:
op->datatype = op_byte; break;
case 2:
op->datatype = op_word; break;
case 4:
op->datatype = op_dword; break;
case 8:
op->datatype = op_qword; break;
case 10:
op->datatype = op_extreal; break;
case 16:
op->datatype = op_dqword; break;
}
return;
}
/* 'impl_idx' is the value from the opcode table: between 1 and LAST_IMPL_IDX */
/* returns number of operands added */
unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx ) {
op_implicit_list_t *list;
x86_op_t *op;
unsigned int num = 0;
if (! impl_idx || impl_idx > LAST_IMPL_IDX ) {
return 0;
}
for ( list = op_implicit_list[impl_idx]; list->type; list++, num++ ) {
enum x86_op_access access = (enum x86_op_access) OP_PERM(list->type);
enum x86_op_flags flags = (enum x86_op_flags) (OP_FLAGS(list->type) >> 12);
op = NULL;
/* In some cases (MUL), EAX is an implicit operand hardcoded in
* the instruction without being explicitly listed in assembly.
* For this situation, find the hardcoded operand and add the
* implied flag rather than adding a new implicit operand. */
x86_oplist_t * existing;
if (ia32_true_register_id(list->operand) == REG_DWORD_OFFSET) {
for ( existing = insn->operands; existing; existing = existing->next ) {
if (existing->op.type == op_register &&
existing->op.data.reg.id == list->operand) {
op = &existing->op;
break;
}
}
}
if (!op) {
op = x86_operand_new( insn );
/* all implicit operands are registers */
handle_impl_reg( op, list->operand );
/* decrement the 'explicit count' incremented by default in
* x86_operand_new */
insn->explicit_count = insn->explicit_count -1;
}
if (!op) {
return num; /* gah! return early */
}
op->access |= access;
op->flags |= flags;
op->flags |= op_implied;
}
return num;
}

View file

@ -0,0 +1,13 @@
#ifndef IA32_IMPLICIT_H
#define IA32_IMPLICIT_H
#include "libdis.h"
/* OK, this is a hack to deal with prefixes having implicit operands...
* thought I had removed all the old hackishness ;( */
#define IDX_IMPLICIT_REP 41 /* change this if the table changes! */
unsigned int ia32_insn_implicit_ops( x86_insn_t *insn, unsigned int impl_idx );
#endif

View file

@ -0,0 +1,623 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "qword.h"
#include "ia32_insn.h"
#include "ia32_opcode_tables.h"
#include "ia32_reg.h"
#include "ia32_operand.h"
#include "ia32_implicit.h"
#include "ia32_settings.h"
#include "libdis.h"
extern ia32_table_desc_t ia32_tables[];
extern ia32_settings_t ia32_settings;
#define IS_SP( op ) (op->type == op_register && \
(op->data.reg.id == REG_ESP_INDEX || \
op->data.reg.alias == REG_ESP_INDEX) )
#define IS_IMM( op ) (op->type == op_immediate )
#ifdef WIN32
# define INLINE
#else
# define INLINE inline
#endif
/* for calculating stack modification based on an operand */
static INLINE int32_t long_from_operand( x86_op_t *op ) {
if (! IS_IMM(op) ) {
return 0L;
}
switch ( op->datatype ) {
case op_byte:
return (int32_t) op->data.sbyte;
case op_word:
return (int32_t) op->data.sword;
case op_qword:
return (int32_t) op->data.sqword;
case op_dword:
return op->data.sdword;
default:
/* these are not used in stack insn */
break;
}
return 0L;
}
/* determine what this insn does to the stack */
static void ia32_stack_mod(x86_insn_t *insn) {
x86_op_t *dest, *src = NULL;
if (! insn || ! insn->operands ) {
return;
}
dest = &insn->operands->op;
if ( dest ) {
src = &insn->operands->next->op;
}
insn->stack_mod = 0;
insn->stack_mod_val = 0;
switch ( insn->type ) {
case insn_call:
case insn_callcc:
insn->stack_mod = 1;
insn->stack_mod_val = insn->addr_size * -1;
break;
case insn_push:
insn->stack_mod = 1;
insn->stack_mod_val = insn->addr_size * -1;
break;
case insn_return:
insn->stack_mod = 1;
insn->stack_mod_val = insn->addr_size;
case insn_int: case insn_intcc:
case insn_iret:
break;
case insn_pop:
insn->stack_mod = 1;
if (! IS_SP( dest ) ) {
insn->stack_mod_val = insn->op_size;
} /* else we don't know the stack change in a pop esp */
break;
case insn_enter:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_leave:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_pushregs:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_popregs:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_pushflags:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_popflags:
insn->stack_mod = 1;
insn->stack_mod_val = 0; /* TODO : FIX */
break;
case insn_add:
if ( IS_SP( dest ) ) {
insn->stack_mod = 1;
insn->stack_mod_val = long_from_operand( src );
}
break;
case insn_sub:
if ( IS_SP( dest ) ) {
insn->stack_mod = 1;
insn->stack_mod_val = long_from_operand( src );
insn->stack_mod_val *= -1;
}
break;
case insn_inc:
if ( IS_SP( dest ) ) {
insn->stack_mod = 1;
insn->stack_mod_val = 1;
}
break;
case insn_dec:
if ( IS_SP( dest ) ) {
insn->stack_mod = 1;
insn->stack_mod_val = 1;
}
break;
case insn_mov: case insn_movcc:
case insn_xchg: case insn_xchgcc:
case insn_mul: case insn_div:
case insn_shl: case insn_shr:
case insn_rol: case insn_ror:
case insn_and: case insn_or:
case insn_not: case insn_neg:
case insn_xor:
if ( IS_SP( dest ) ) {
insn->stack_mod = 1;
}
break;
default:
break;
}
if (! strcmp("enter", insn->mnemonic) ) {
insn->stack_mod = 1;
} else if (! strcmp("leave", insn->mnemonic) ) {
insn->stack_mod = 1;
}
/* for mov, etc we return 0 -- unknown stack mod */
return;
}
/* get the cpu details for this insn from cpu flags int */
static void ia32_handle_cpu( x86_insn_t *insn, unsigned int cpu ) {
insn->cpu = (enum x86_insn_cpu) CPU_MODEL(cpu);
insn->isa = (enum x86_insn_isa) (ISA_SUBSET(cpu)) >> 16;
return;
}
/* handle mnemonic type and group */
static void ia32_handle_mnemtype(x86_insn_t *insn, unsigned int mnemtype) {
unsigned int type = mnemtype & ~INS_FLAG_MASK;
insn->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
insn->type = (enum x86_insn_type) INS_TYPE(type);
return;
}
static void ia32_handle_notes(x86_insn_t *insn, unsigned int notes) {
insn->note = (enum x86_insn_note) notes;
return;
}
static void ia32_handle_eflags( x86_insn_t *insn, unsigned int eflags) {
unsigned int flags;
/* handle flags effected */
flags = INS_FLAGS_TEST(eflags);
/* handle weird OR cases */
/* these are either JLE (ZF | SF<>OF) or JBE (CF | ZF) */
if (flags & INS_TEST_OR) {
flags &= ~INS_TEST_OR;
if ( flags & INS_TEST_ZERO ) {
flags &= ~INS_TEST_ZERO;
if ( flags & INS_TEST_CARRY ) {
flags &= ~INS_TEST_CARRY ;
flags |= (int)insn_carry_or_zero_set;
} else if ( flags & INS_TEST_SFNEOF ) {
flags &= ~INS_TEST_SFNEOF;
flags |= (int)insn_zero_set_or_sign_ne_oflow;
}
}
}
insn->flags_tested = (enum x86_flag_status) flags;
insn->flags_set = (enum x86_flag_status) INS_FLAGS_SET(eflags) >> 16;
return;
}
static void ia32_handle_prefix( x86_insn_t *insn, unsigned int prefixes ) {
insn->prefix = (enum x86_insn_prefix) prefixes & PREFIX_MASK; // >> 20;
if (! (insn->prefix & PREFIX_PRINT_MASK) ) {
/* no printable prefixes */
insn->prefix = insn_no_prefix;
}
/* concat all prefix strings */
if ( (unsigned int)insn->prefix & PREFIX_LOCK ) {
strncat(insn->prefix_string, "lock ", 32 -
strlen(insn->prefix_string));
}
if ( (unsigned int)insn->prefix & PREFIX_REPNZ ) {
strncat(insn->prefix_string, "repnz ", 32 -
strlen(insn->prefix_string));
} else if ( (unsigned int)insn->prefix & PREFIX_REPZ ) {
strncat(insn->prefix_string, "repz ", 32 -
strlen(insn->prefix_string));
}
return;
}
static void reg_32_to_16( x86_op_t *op, x86_insn_t *insn, void *arg ) {
/* if this is a 32-bit register and it is a general register ... */
if ( op->type == op_register && op->data.reg.size == 4 &&
(op->data.reg.type & reg_gen) ) {
/* WORD registers are 8 indices off from DWORD registers */
ia32_handle_register( &(op->data.reg),
op->data.reg.id + 8 );
}
}
static void handle_insn_metadata( x86_insn_t *insn, ia32_insn_t *raw_insn ) {
ia32_handle_mnemtype( insn, raw_insn->mnem_flag );
ia32_handle_notes( insn, raw_insn->notes );
ia32_handle_eflags( insn, raw_insn->flags_effected );
ia32_handle_cpu( insn, raw_insn->cpu );
ia32_stack_mod( insn );
}
static size_t ia32_decode_insn( unsigned char *buf, size_t buf_len,
ia32_insn_t *raw_insn, x86_insn_t *insn,
unsigned int prefixes ) {
size_t size, op_size;
unsigned char modrm;
/* this should never happen, but just in case... */
if ( raw_insn->mnem_flag == INS_INVALID ) {
return 0;
}
if (ia32_settings.options & opt_16_bit) {
insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
} else {
insn->op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
insn->addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
}
/* ++++ 1. Copy mnemonic and mnemonic-flags to CODE struct */
if ((ia32_settings.options & opt_att_mnemonics) && raw_insn->mnemonic_att[0]) {
strncpy( insn->mnemonic, raw_insn->mnemonic_att, 16 );
}
else {
strncpy( insn->mnemonic, raw_insn->mnemonic, 16 );
}
ia32_handle_prefix( insn, prefixes );
handle_insn_metadata( insn, raw_insn );
/* prefetch the next byte in case it is a modr/m byte -- saves
* worrying about whether the 'mod/rm' operand or the 'reg' operand
* occurs first */
modrm = GET_BYTE( buf, buf_len );
/* ++++ 2. Decode Explicit Operands */
/* Intel uses up to 3 explicit operands in its instructions;
* the first is 'dest', the second is 'src', and the third
* is an additional source value (usually an immediate value,
* e.g. in the MUL instructions). These three explicit operands
* are encoded in the opcode tables, even if they are not used
* by the instruction. Additional implicit operands are stored
* in a supplemental table and are handled later. */
op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->dest,
raw_insn->dest_flag, prefixes, modrm );
/* advance buffer, increase size if necessary */
buf += op_size;
buf_len -= op_size;
size = op_size;
op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->src,
raw_insn->src_flag, prefixes, modrm );
buf += op_size;
buf_len -= op_size;
size += op_size;
op_size = ia32_decode_operand( buf, buf_len, insn, raw_insn->aux,
raw_insn->aux_flag, prefixes, modrm );
size += op_size;
/* ++++ 3. Decode Implicit Operands */
/* apply implicit operands */
ia32_insn_implicit_ops( insn, raw_insn->implicit_ops );
/* we have one small inelegant hack here, to deal with
* the two prefixes that have implicit operands. If Intel
* adds more, we'll change the algorithm to suit :) */
if ( (prefixes & PREFIX_REPZ) || (prefixes & PREFIX_REPNZ) ) {
ia32_insn_implicit_ops( insn, IDX_IMPLICIT_REP );
}
/* 16-bit hack: foreach operand, if 32-bit reg, make 16-bit reg */
if ( insn->op_size == 2 ) {
x86_operand_foreach( insn, reg_32_to_16, NULL, op_any );
}
return size;
}
/* convenience routine */
#define USES_MOD_RM(flag) \
(flag == ADDRMETH_E || flag == ADDRMETH_M || flag == ADDRMETH_Q || \
flag == ADDRMETH_W || flag == ADDRMETH_R)
static int uses_modrm_flag( unsigned int flag ) {
unsigned int meth;
if ( flag == ARG_NONE ) {
return 0;
}
meth = (flag & ADDRMETH_MASK);
if ( USES_MOD_RM(meth) ) {
return 1;
}
return 0;
}
/* This routine performs the actual byte-by-byte opcode table lookup.
* Originally it was pretty simple: get a byte, adjust it to a proper
* index into the table, then check the table row at that index to
* determine what to do next. But is anything that simple with Intel?
* This is now a huge, convoluted mess, mostly of bitter comments. */
/* buf: pointer to next byte to read from stream
* buf_len: length of buf
* table: index of table to use for lookups
* raw_insn: output pointer that receives opcode definition
* prefixes: output integer that is encoded with prefixes in insn
* returns : number of bytes consumed from stream during lookup */
size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
unsigned int table, ia32_insn_t **raw_insn,
unsigned int *prefixes ) {
unsigned char *next, op = buf[0]; /* byte value -- 'opcode' */
size_t size = 1, sub_size = 0, next_len;
ia32_table_desc_t *table_desc;
unsigned int subtable, prefix = 0, recurse_table = 0;
table_desc = &ia32_tables[table];
op = GET_BYTE( buf, buf_len );
if ( table_desc->type == tbl_fpu && op > table_desc->maxlim) {
/* one of the fucking FPU tables out of the 00-BH range */
/* OK,. this is a bit of a hack -- the proper way would
* have been to use subtables in the 00-BF FPU opcode tables,
* but that is rather wasteful of space... */
table_desc = &ia32_tables[table +1];
}
/* PERFORM TABLE LOOKUP */
/* ModR/M trick: shift extension bits into lowest bits of byte */
/* Note: non-ModR/M tables have a shift value of 0 */
op >>= table_desc->shift;
/* ModR/M trick: mask out high bits to turn extension into an index */
/* Note: non-ModR/M tables have a mask value of 0xFF */
op &= table_desc->mask;
/* Sparse table trick: check that byte is <= max value */
/* Note: full (256-entry) tables have a maxlim of 155 */
if ( op > table_desc->maxlim ) {
/* this is a partial table, truncated at the tail,
and op is out of range! */
return INVALID_INSN;
}
/* Sparse table trick: check that byte is >= min value */
/* Note: full (256-entry) tables have a minlim of 0 */
if ( table_desc->minlim > op ) {
/* this is a partial table, truncated at the head,
and op is out of range! */
return INVALID_INSN;
}
/* adjust op to be an offset from table index 0 */
op -= table_desc->minlim;
/* Yay! 'op' is now fully adjusted to be an index into 'table' */
*raw_insn = &(table_desc->table[op]);
//printf("BYTE %X TABLE %d OP %X\n", buf[0], table, op );
if ( (*raw_insn)->mnem_flag & INS_FLAG_PREFIX ) {
prefix = (*raw_insn)->mnem_flag & PREFIX_MASK;
}
/* handle escape to a multibyte/coproc/extension/etc table */
/* NOTE: if insn is a prefix and has a subtable, then we
* only recurse if this is the first prefix byte --
* that is, if *prefixes is 0.
* NOTE also that suffix tables are handled later */
subtable = (*raw_insn)->table;
if ( subtable && ia32_tables[subtable].type != tbl_suffix &&
(! prefix || ! *prefixes) ) {
if ( ia32_tables[subtable].type == tbl_ext_ext ||
ia32_tables[subtable].type == tbl_fpu_ext ) {
/* opcode extension: reuse current byte in buffer */
next = buf;
next_len = buf_len;
} else {
/* "normal" opcode: advance to next byte in buffer */
if ( buf_len > 1 ) {
next = &buf[1];
next_len = buf_len - 1;
}
else {
// buffer is truncated
return INVALID_INSN;
}
}
/* we encountered a multibyte opcode: recurse using the
* table specified in the opcode definition */
sub_size = ia32_table_lookup( next, next_len, subtable,
raw_insn, prefixes );
/* SSE/prefix hack: if the original opcode def was a
* prefix that specified a subtable, and the subtable
* lookup returned a valid insn, then we have encountered
* an SSE opcode definition; otherwise, we pretend we
* never did the subtable lookup, and deal with the
* prefix normally later */
if ( prefix && ( sub_size == INVALID_INSN ||
INS_TYPE((*raw_insn)->mnem_flag) == INS_INVALID ) ) {
/* this is a prefix, not an SSE insn :
* lookup next byte in main table,
* subsize will be reset during the
* main table lookup */
recurse_table = 1;
} else {
/* this is either a subtable (two-byte) insn
* or an invalid insn: either way, set prefix
* to NULL and end the opcode lookup */
prefix = 0;
// short-circuit lookup on invalid insn
if (sub_size == INVALID_INSN) return INVALID_INSN;
}
} else if ( prefix ) {
recurse_table = 1;
}
/* by default, we assume that we have the opcode definition,
* and there is no need to recurse on the same table, but
* if we do then a prefix was encountered... */
if ( recurse_table ) {
/* this must have been a prefix: use the same table for
* lookup of the next byte */
sub_size = ia32_table_lookup( &buf[1], buf_len - 1, table,
raw_insn, prefixes );
// short-circuit lookup on invalid insn
if (sub_size == INVALID_INSN) return INVALID_INSN;
/* a bit of a hack for branch hints */
if ( prefix & BRANCH_HINT_MASK ) {
if ( INS_GROUP((*raw_insn)->mnem_flag) == INS_EXEC ) {
/* segment override prefixes are invalid for
* all branch instructions, so delete them */
prefix &= ~PREFIX_REG_MASK;
} else {
prefix &= ~BRANCH_HINT_MASK;
}
}
/* apply prefix to instruction */
/* TODO: implement something enforcing prefix groups */
(*prefixes) |= prefix;
}
/* if this lookup was in a ModR/M table, then an opcode byte is
* NOT consumed: subtract accordingly. NOTE that if none of the
* operands used the ModR/M, then we need to consume the byte
* here, but ONLY in the 'top-level' opcode extension table */
if ( table_desc->type == tbl_ext_ext ) {
/* extensions-to-extensions never consume a byte */
--size;
} else if ( (table_desc->type == tbl_extension ||
table_desc->type == tbl_fpu ||
table_desc->type == tbl_fpu_ext ) &&
/* extensions that have an operand encoded in ModR/M
* never consume a byte */
(uses_modrm_flag((*raw_insn)->dest_flag) ||
uses_modrm_flag((*raw_insn)->src_flag) ) ) {
--size;
}
size += sub_size;
return size;
}
static size_t handle_insn_suffix( unsigned char *buf, size_t buf_len,
ia32_insn_t *raw_insn, x86_insn_t * insn ) {
ia32_insn_t *sfx_insn;
size_t size;
unsigned int prefixes = 0;
size = ia32_table_lookup( buf, buf_len, raw_insn->table, &sfx_insn,
&prefixes );
if (size == INVALID_INSN || sfx_insn->mnem_flag == INS_INVALID ) {
return 0;
}
strncpy( insn->mnemonic, sfx_insn->mnemonic, 16 );
handle_insn_metadata( insn, sfx_insn );
return 1;
}
/* invalid instructions are handled by returning 0 [error] from the
* function, setting the size of the insn to 1 byte, and copying
* the byte at the start of the invalid insn into the x86_insn_t.
* if the caller is saving the x86_insn_t for invalid instructions,
* instead of discarding them, this will maintain a consistent
* address space in the x86_insn_ts */
/* this function is called by the controlling disassembler, so its name and
* calling convention cannot be changed */
/* buf points to the loc of the current opcode (start of the
* instruction) in the instruction stream. The instruction
* stream is assumed to be a buffer of bytes read directly
* from the file for the purpose of disassembly; a mem-mapped
* file is ideal for * this.
* insn points to a code structure to be filled by instr_decode
* returns the size of the decoded instruction in bytes */
size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len,
x86_insn_t *insn ) {
ia32_insn_t *raw_insn = NULL;
unsigned int prefixes = 0;
size_t size, sfx_size;
if ( (ia32_settings.options & opt_ignore_nulls) && buf_len > 3 &&
!buf[0] && !buf[1] && !buf[2] && !buf[3]) {
/* IF IGNORE_NULLS is set AND
* first 4 bytes in the intruction stream are NULL
* THEN return 0 (END_OF_DISASSEMBLY) */
/* TODO: set errno */
MAKE_INVALID( insn, buf );
return 0; /* 4 00 bytes in a row? This isn't code! */
}
/* Perform recursive table lookup starting with main table (0) */
size = ia32_table_lookup(buf, buf_len, idx_Main, &raw_insn, &prefixes);
if ( size == INVALID_INSN || size > buf_len || raw_insn->mnem_flag == INS_INVALID ) {
MAKE_INVALID( insn, buf );
/* TODO: set errno */
return 0;
}
/* We now have the opcode itself figured out: we can decode
* the rest of the instruction. */
size += ia32_decode_insn( &buf[size], buf_len - size, raw_insn, insn,
prefixes );
if ( raw_insn->mnem_flag & INS_FLAG_SUFFIX ) {
/* AMD 3DNow! suffix -- get proper operand type here */
sfx_size = handle_insn_suffix( &buf[size], buf_len - size,
raw_insn, insn );
if (! sfx_size ) {
/* TODO: set errno */
MAKE_INVALID( insn, buf );
return 0;
}
size += sfx_size;
}
if (! size ) {
/* invalid insn */
MAKE_INVALID( insn, buf );
return 0;
}
insn->size = size;
return size; /* return size of instruction in bytes */
}

View file

@ -0,0 +1,506 @@
#ifndef IA32_INSN_H
#define IA32_INSN_H
/* this file contains the structure of opcode definitions and the
* constants they use */
#include <sys/types.h>
#include "libdis.h"
#define GET_BYTE( buf, buf_len ) buf_len ? *buf : 0
#define OP_SIZE_16 1
#define OP_SIZE_32 2
#define ADDR_SIZE_16 4
#define ADDR_SIZE_32 8
#define MAX_INSTRUCTION_SIZE 20
/* invalid instructions are handled by returning 0 [error] from the
* function, setting the size of the insn to 1 byte, and copying
* the byte at the start of the invalid insn into the x86_insn_t.
* if the caller is saving the x86_insn_t for invalid instructions,
* instead of discarding them, this will maintain a consistent
* address space in the x86_insn_ts */
#define INVALID_INSN ((size_t) -1) /* return value for invalid insn */
#define MAKE_INVALID( i, buf ) \
strcpy( i->mnemonic, "invalid" ); \
x86_oplist_free( i ); \
i->size = 1; \
i->group = insn_none; \
i->type = insn_invalid; \
memcpy( i->bytes, buf, 1 );
size_t ia32_disasm_addr( unsigned char * buf, size_t buf_len,
x86_insn_t *insn);
/* --------------------------------------------------------- Table Lookup */
/* IA32 Instruction defintion for ia32_opcodes.c */
typedef struct {
unsigned int table; /* escape to this sub-table */
unsigned int mnem_flag; /* Flags referring to mnemonic */
unsigned int notes; /* Notes for this instruction */
unsigned int dest_flag, src_flag, aux_flag; /* and for specific operands */
unsigned int cpu; /* minimumCPU [AND with clocks?? */
char mnemonic[16]; /* buffers for building instruction */
char mnemonic_att[16]; /* at&t style mnemonic name */
int32_t dest;
int32_t src;
int32_t aux;
unsigned int flags_effected;
unsigned int implicit_ops; /* implicit operands */
} ia32_insn_t;
/* --------------------------------------------------------- Prefixes */
/* Prefix Flags */
/* Prefixes, same order as in the manual */
/* had to reverse the values of the first three as they were entered into
* libdis.h incorrectly. */
#define PREFIX_LOCK 0x0004
#define PREFIX_REPNZ 0x0002
#define PREFIX_REPZ 0x0001
#define PREFIX_OP_SIZE 0x0010
#define PREFIX_ADDR_SIZE 0x0020
#define PREFIX_CS 0x0100
#define PREFIX_SS 0x0200
#define PREFIX_DS 0x0300
#define PREFIX_ES 0x0400
#define PREFIX_FS 0x0500
#define PREFIX_GS 0x0600
#define PREFIX_TAKEN 0x1000 /* branch taken */
#define PREFIX_NOTTAKEN 0x2000 /* branch not taken */
#define PREFIX_REG_MASK 0x0F00
#define BRANCH_HINT_MASK 0x3000
#define PREFIX_PRINT_MASK 0x000F /* printable prefixes */
#define PREFIX_MASK 0xFFFF
/* ---------------------------------------------------------- CPU Type */
#define cpu_8086 0x0001
#define cpu_80286 0x0002
#define cpu_80386 0x0003
#define cpu_80387 0x0004 /* originally these were a co-proc */
#define cpu_80486 0x0005
#define cpu_PENTIUM 0x0006
#define cpu_PENTPRO 0x0007
#define cpu_PENTIUM2 0x0008
#define cpu_PENTIUM3 0x0009
#define cpu_PENTIUM4 0x000A
#define cpu_K6 0x0010
#define cpu_K7 0x0020
#define cpu_ATHLON 0x0030
#define CPU_MODEL_MASK 0xFFFF
#define CPU_MODEL(cpu) (cpu & CPU_MODEL_MASK)
/* intel instruction subsets */
#define isa_GP 0x10000 /* General Purpose Instructions */
#define isa_FPU 0x20000 /* FPU instructions */
#define isa_FPUMGT 0x30000 /* FPU/SIMD Management */
#define isa_MMX 0x40000 /* MMX */
#define isa_SSE1 0x50000 /* SSE */
#define isa_SSE2 0x60000 /* SSE 2 */
#define isa_SSE3 0x70000 /* SSE 3 */
#define isa_3DNOW 0x80000 /* AMD 3d Now */
#define isa_SYS 0x90000 /* System Instructions */
#define ISA_SUBSET_MASK 0xFFFF0000
#define ISA_SUBSET(isa) (isa & ISA_SUBSET_MASK)
/* ------------------------------------------------------ Operand Decoding */
#define ARG_NONE 0
/* Using a mask allows us to store info such as OP_SIGNED in the
* operand flags field */
#define OPFLAGS_MASK 0x0000FFFF
/* Operand Addressing Methods, per intel manual */
#define ADDRMETH_MASK 0x00FF0000
/* note: for instructions with implied operands, use no ADDRMETH */
#define ADDRMETH_A 0x00010000
#define ADDRMETH_C 0x00020000
#define ADDRMETH_D 0x00030000
#define ADDRMETH_E 0x00040000
#define ADDRMETH_F 0x00050000
#define ADDRMETH_G 0x00060000
#define ADDRMETH_I 0x00070000
#define ADDRMETH_J 0x00080000
#define ADDRMETH_M 0x00090000
#define ADDRMETH_O 0x000A0000
#define ADDRMETH_P 0x000B0000
#define ADDRMETH_Q 0x000C0000
#define ADDRMETH_R 0x000D0000
#define ADDRMETH_S 0x000E0000
#define ADDRMETH_T 0x000F0000
#define ADDRMETH_V 0x00100000
#define ADDRMETH_W 0x00110000
#define ADDRMETH_X 0x00120000
#define ADDRMETH_Y 0x00130000
#define ADDRMETH_RR 0x00140000 /* gen reg hard-coded in opcode */
#define ADDRMETH_RS 0x00150000 /* seg reg hard-coded in opcode */
#define ADDRMETH_RT 0x00160000 /* test reg hard-coded in opcode */
#define ADDRMETH_RF 0x00170000 /* fpu reg hard-coded in opcode */
#define ADDRMETH_II 0x00180000 /* immediate hard-coded in opcode */
#define ADDRMETH_PP 0x00190000 /* mm reg ONLY in modr/m field */
#define ADDRMETH_VV 0x001A0000 /* xmm reg ONLY in mod/rm field */
/* Operand Types, per intel manual */
#define OPTYPE_MASK 0xFF000000
#define OPTYPE_a 0x01000000 /* BOUND: h:h or w:w */
#define OPTYPE_b 0x02000000 /* byte */
#define OPTYPE_c 0x03000000 /* byte or word */
#define OPTYPE_d 0x04000000 /* word */
#define OPTYPE_dq 0x05000000 /* qword */
#define OPTYPE_p 0x06000000 /* 16:16 or 16:32 pointer */
#define OPTYPE_pi 0x07000000 /* dword MMX reg */
#define OPTYPE_ps 0x08000000 /* 128-bit single fp */
#define OPTYPE_q 0x09000000 /* dword */
#define OPTYPE_s 0x0A000000 /* 6-byte descriptor */
#define OPTYPE_ss 0x0B000000 /* scalar of 128-bit single fp */
#define OPTYPE_si 0x0C000000 /* word general register */
#define OPTYPE_v 0x0D000000 /* hword or word */
#define OPTYPE_w 0x0E000000 /* hword */
#define OPTYPE_m 0x0F000000 /* to handle LEA */
#define OPTYPE_none 0xFF000000 /* no valid operand size, INVLPG */
/* custom ones for FPU instructions */
#define OPTYPE_fs 0x10000000 /* pointer to single-real*/
#define OPTYPE_fd 0x20000000 /* pointer to double real */
#define OPTYPE_fe 0x30000000 /* pointer to extended real */
#define OPTYPE_fb 0x40000000 /* pointer to packed BCD */
#define OPTYPE_fv 0x50000000 /* pointer to FPU env: 14|28-bytes */
#define OPTYPE_ft 0x60000000 /* pointer to FPU state: 94|108-bytes */
#define OPTYPE_fx 0x70000000 /* pointer to FPU regs: 512 bites */
#define OPTYPE_fp 0x80000000 /* general fpu register: dbl ext */
/* SSE2 operand types */
#define OPTYPE_sd 0x90000000 /* scalar of 128-bit double fp */
#define OPTYPE_pd 0xA0000000 /* 128-bit double fp */
/* ---------------------------------------------- Opcode Table Descriptions */
/* the table type describes how to handle byte/size increments before
* and after lookup. Some tables re-use the current byte, others
* consume a byte only if the ModR/M encodes no operands, etc */
enum ia32_tbl_type_id {
tbl_opcode = 0, /* standard opcode table: no surprises */
tbl_prefix, /* Prefix Override, e.g. 66/F2/F3 */
tbl_suffix, /* 3D Now style */
tbl_extension, /* ModR/M extension: 00-FF -> 00-07 */
tbl_ext_ext, /* extension of modr/m using R/M field */
tbl_fpu, /* fpu table: 00-BF -> 00-0F */
tbl_fpu_ext /* fpu extension : C0-FF -> 00-1F */
};
/* How it works:
* Bytes are 'consumed' if the next table lookup requires that the byte
* pointer be advanced in the instruction stream. 'Does not consume' means
* that, when the lookup function recurses, the same byte it re-used in the
* new table. It also means that size is not decremented, for example when
* a ModR/M byte is used. Note that tbl_extension (ModR/M) instructions that
* do not increase the size of an insn with their operands have a forced
3 size increase in the lookup algo. Weird, yes, confusing, yes, welcome
* to the Intel ISA. Another note: tbl_prefix is used as an override, so an
* empty insn in a prefix table causes the instruction in the original table
* to be used, rather than an invalid insn being generated.
* tbl_opcode uses current byte and consumes it
* tbl_prefix uses current byte but does not consume it
* tbl_suffix uses and consumes last byte in insn
* tbl_extension uses current byte but does not consume it
* tbl_ext_ext uses current byte but does not consume it
* tbl_fpu uses current byte and consumes it
* tbl_fpu_ext uses current byte but does not consume it
*/
/* Convenience struct for opcode tables : these will be stored in a
* 'table of tables' so we can use a table index instead of a pointer */
typedef struct { /* Assembly instruction tables */
ia32_insn_t *table; /* Pointer to table of instruction encodings */
enum ia32_tbl_type_id type;
unsigned char shift; /* amount to shift modrm byte */
unsigned char mask; /* bit mask for look up */
unsigned char minlim,maxlim; /* limits on min/max entries. */
} ia32_table_desc_t;
/* ---------------------------------------------- 'Cooked' Operand Type Info */
/* Permissions: */
#define OP_R 0x001 /* operand is READ */
#define OP_W 0x002 /* operand is WRITTEN */
#define OP_RW 0x003 /* (OP_R|OP_W): convenience macro */
#define OP_X 0x004 /* operand is EXECUTED */
#define OP_PERM_MASK 0x0000007 /* perms are NOT mutually exclusive */
#define OP_PERM( type ) (type & OP_PERM_MASK)
/* Flags */
#define OP_SIGNED 0x010 /* operand is signed */
#define OP_FLAG_MASK 0x0F0 /* mods are NOT mutually exclusive */
#define OP_FLAGS( type ) (type & OP_FLAG_MASK)
#define OP_REG_MASK 0x0000FFFF /* lower WORD is register ID */
#define OP_REGTBL_MASK 0xFFFF0000 /* higher word is register type [gen/dbg] */
#define OP_REGID( type ) (type & OP_REG_MASK)
#define OP_REGTYPE( type ) (type & OP_REGTBL_MASK)
/* ------------------------------------------'Cooked' Instruction Type Info */
/* high-bit opcode types/insn meta-types */
#define INS_FLAG_PREFIX 0x10000000 /* insn is a prefix */
#define INS_FLAG_SUFFIX 0x20000000 /* followed by a suffix byte */
#define INS_FLAG_MASK 0xFF000000
/* insn notes */
#define INS_NOTE_RING0 0x00000001 /* insn is privileged */
#define INS_NOTE_SMM 0x00000002 /* Sys Mgt Mode only */
#define INS_NOTE_SERIAL 0x00000004 /* serializes */
#define INS_NOTE_NONSWAP 0x00000008 /* insn is not swapped in att format */ // could be separate field?
#define INS_NOTE_NOSUFFIX 0x00000010 /* insn has no size suffix in att format */ // could be separate field?
//#define INS_NOTE_NMI
#define INS_INVALID 0
/* instruction groups */
#define INS_EXEC 0x1000
#define INS_ARITH 0x2000
#define INS_LOGIC 0x3000
#define INS_STACK 0x4000
#define INS_COND 0x5000
#define INS_LOAD 0x6000
#define INS_ARRAY 0x7000
#define INS_BIT 0x8000
#define INS_FLAG 0x9000
#define INS_FPU 0xA000
#define INS_TRAPS 0xD000
#define INS_SYSTEM 0xE000
#define INS_OTHER 0xF000
#define INS_GROUP_MASK 0xF000
#define INS_GROUP( type ) ( type & INS_GROUP_MASK )
/* INS_EXEC group */
#define INS_BRANCH (INS_EXEC | 0x01) /* Unconditional branch */
#define INS_BRANCHCC (INS_EXEC | 0x02) /* Conditional branch */
#define INS_CALL (INS_EXEC | 0x03) /* Jump to subroutine */
#define INS_CALLCC (INS_EXEC | 0x04) /* Jump to subroutine */
#define INS_RET (INS_EXEC | 0x05) /* Return from subroutine */
/* INS_ARITH group */
#define INS_ADD (INS_ARITH | 0x01)
#define INS_SUB (INS_ARITH | 0x02)
#define INS_MUL (INS_ARITH | 0x03)
#define INS_DIV (INS_ARITH | 0x04)
#define INS_INC (INS_ARITH | 0x05) /* increment */
#define INS_DEC (INS_ARITH | 0x06) /* decrement */
#define INS_SHL (INS_ARITH | 0x07) /* shift right */
#define INS_SHR (INS_ARITH | 0x08) /* shift left */
#define INS_ROL (INS_ARITH | 0x09) /* rotate left */
#define INS_ROR (INS_ARITH | 0x0A) /* rotate right */
#define INS_MIN (INS_ARITH | 0x0B) /* min func */
#define INS_MAX (INS_ARITH | 0x0C) /* max func */
#define INS_AVG (INS_ARITH | 0x0D) /* avg func */
#define INS_FLR (INS_ARITH | 0x0E) /* floor func */
#define INS_CEIL (INS_ARITH | 0x0F) /* ceiling func */
/* INS_LOGIC group */
#define INS_AND (INS_LOGIC | 0x01)
#define INS_OR (INS_LOGIC | 0x02)
#define INS_XOR (INS_LOGIC | 0x03)
#define INS_NOT (INS_LOGIC | 0x04)
#define INS_NEG (INS_LOGIC | 0x05)
#define INS_NAND (INS_LOGIC | 0x06)
/* INS_STACK group */
#define INS_PUSH (INS_STACK | 0x01)
#define INS_POP (INS_STACK | 0x02)
#define INS_PUSHREGS (INS_STACK | 0x03) /* push register context */
#define INS_POPREGS (INS_STACK | 0x04) /* pop register context */
#define INS_PUSHFLAGS (INS_STACK | 0x05) /* push all flags */
#define INS_POPFLAGS (INS_STACK | 0x06) /* pop all flags */
#define INS_ENTER (INS_STACK | 0x07) /* enter stack frame */
#define INS_LEAVE (INS_STACK | 0x08) /* leave stack frame */
/* INS_COND group */
#define INS_TEST (INS_COND | 0x01)
#define INS_CMP (INS_COND | 0x02)
/* INS_LOAD group */
#define INS_MOV (INS_LOAD | 0x01)
#define INS_MOVCC (INS_LOAD | 0x02)
#define INS_XCHG (INS_LOAD | 0x03)
#define INS_XCHGCC (INS_LOAD | 0x04)
#define INS_CONV (INS_LOAD | 0x05) /* move and convert type */
/* INS_ARRAY group */
#define INS_STRCMP (INS_ARRAY | 0x01)
#define INS_STRLOAD (INS_ARRAY | 0x02)
#define INS_STRMOV (INS_ARRAY | 0x03)
#define INS_STRSTOR (INS_ARRAY | 0x04)
#define INS_XLAT (INS_ARRAY | 0x05)
/* INS_BIT group */
#define INS_BITTEST (INS_BIT | 0x01)
#define INS_BITSET (INS_BIT | 0x02)
#define INS_BITCLR (INS_BIT | 0x03)
/* INS_FLAG group */
#define INS_CLEARCF (INS_FLAG | 0x01) /* clear Carry flag */
#define INS_CLEARZF (INS_FLAG | 0x02) /* clear Zero flag */
#define INS_CLEAROF (INS_FLAG | 0x03) /* clear Overflow flag */
#define INS_CLEARDF (INS_FLAG | 0x04) /* clear Direction flag */
#define INS_CLEARSF (INS_FLAG | 0x05) /* clear Sign flag */
#define INS_CLEARPF (INS_FLAG | 0x06) /* clear Parity flag */
#define INS_SETCF (INS_FLAG | 0x07)
#define INS_SETZF (INS_FLAG | 0x08)
#define INS_SETOF (INS_FLAG | 0x09)
#define INS_SETDF (INS_FLAG | 0x0A)
#define INS_SETSF (INS_FLAG | 0x0B)
#define INS_SETPF (INS_FLAG | 0x0C)
#define INS_TOGCF (INS_FLAG | 0x10) /* toggle */
#define INS_TOGZF (INS_FLAG | 0x20)
#define INS_TOGOF (INS_FLAG | 0x30)
#define INS_TOGDF (INS_FLAG | 0x40)
#define INS_TOGSF (INS_FLAG | 0x50)
#define INS_TOGPF (INS_FLAG | 0x60)
/* INS_FPU */
#define INS_FMOV (INS_FPU | 0x1)
#define INS_FMOVCC (INS_FPU | 0x2)
#define INS_FNEG (INS_FPU | 0x3)
#define INS_FABS (INS_FPU | 0x4)
#define INS_FADD (INS_FPU | 0x5)
#define INS_FSUB (INS_FPU | 0x6)
#define INS_FMUL (INS_FPU | 0x7)
#define INS_FDIV (INS_FPU | 0x8)
#define INS_FSQRT (INS_FPU | 0x9)
#define INS_FCMP (INS_FPU | 0xA)
#define INS_FCOS (INS_FPU | 0xC) /* cosine */
#define INS_FLDPI (INS_FPU | 0xD) /* load pi */
#define INS_FLDZ (INS_FPU | 0xE) /* load 0 */
#define INS_FTAN (INS_FPU | 0xF) /* tanget */
#define INS_FSINE (INS_FPU | 0x10) /* sine */
#define INS_FSYS (INS_FPU | 0x20) /* misc */
/* INS_TRAP */
#define INS_TRAP (INS_TRAPS | 0x01) /* generate trap */
#define INS_TRAPCC (INS_TRAPS | 0x02) /* conditional trap gen */
#define INS_TRET (INS_TRAPS | 0x03) /* return from trap */
#define INS_BOUNDS (INS_TRAPS | 0x04) /* gen bounds trap */
#define INS_DEBUG (INS_TRAPS | 0x05) /* gen breakpoint trap */
#define INS_TRACE (INS_TRAPS | 0x06) /* gen single step trap */
#define INS_INVALIDOP (INS_TRAPS | 0x07) /* gen invalid insn */
#define INS_OFLOW (INS_TRAPS | 0x08) /* gen overflow trap */
#define INS_ICEBP (INS_TRAPS | 0x09) /* ICE breakpoint */
/* INS_SYSTEM */
#define INS_HALT (INS_SYSTEM | 0x01) /* halt machine */
#define INS_IN (INS_SYSTEM | 0x02) /* input form port */
#define INS_OUT (INS_SYSTEM | 0x03) /* output to port */
#define INS_CPUID (INS_SYSTEM | 0x04) /* identify cpu */
/* INS_OTHER */
#define INS_NOP (INS_OTHER | 0x01)
#define INS_BCDCONV (INS_OTHER | 0x02) /* convert to/from BCD */
#define INS_SZCONV (INS_OTHER | 0x03) /* convert size of operand */
#define INS_SALC (INS_OTHER | 0x04) /* set %al on carry */
#define INS_UNKNOWN (INS_OTHER | 0x05)
#define INS_TYPE_MASK 0xFFFF
#define INS_TYPE( type ) ( type & INS_TYPE_MASK )
/* flags effected by instruction */
#define INS_TEST_CARRY 0x01 /* carry */
#define INS_TEST_ZERO 0x02 /* zero/equal */
#define INS_TEST_OFLOW 0x04 /* overflow */
#define INS_TEST_DIR 0x08 /* direction */
#define INS_TEST_SIGN 0x10 /* negative */
#define INS_TEST_PARITY 0x20 /* parity */
#define INS_TEST_OR 0x40 /* used in jle */
#define INS_TEST_NCARRY 0x100 /* ! carry */
#define INS_TEST_NZERO 0x200 /* ! zero */
#define INS_TEST_NOFLOW 0x400 /* ! oflow */
#define INS_TEST_NDIR 0x800 /* ! dir */
#define INS_TEST_NSIGN 0x100 /* ! sign */
#define INS_TEST_NPARITY 0x2000 /* ! parity */
/* SF == OF */
#define INS_TEST_SFEQOF 0x4000
/* SF != OF */
#define INS_TEST_SFNEOF 0x8000
#define INS_TEST_ALL INS_TEST_CARRY | INS_TEST_ZERO | \
INS_TEST_OFLOW | INS_TEST_SIGN | \
INS_TEST_PARITY
#define INS_SET_CARRY 0x010000 /* carry */
#define INS_SET_ZERO 0x020000 /* zero/equal */
#define INS_SET_OFLOW 0x040000 /* overflow */
#define INS_SET_DIR 0x080000 /* direction */
#define INS_SET_SIGN 0x100000 /* negative */
#define INS_SET_PARITY 0x200000 /* parity */
#define INS_SET_NCARRY 0x1000000
#define INS_SET_NZERO 0x2000000
#define INS_SET_NOFLOW 0x4000000
#define INS_SET_NDIR 0x8000000
#define INS_SET_NSIGN 0x10000000
#define INS_SET_NPARITY 0x20000000
#define INS_SET_SFEQOF 0x40000000
#define INS_SET_SFNEOF 0x80000000
#define INS_SET_ALL INS_SET_CARRY | INS_SET_ZERO | \
INS_SET_OFLOW | INS_SET_SIGN | \
INS_SET_PARITY
#define INS_TEST_MASK 0x0000FFFF
#define INS_FLAGS_TEST(x) (x & INS_TEST_MASK)
#define INS_SET_MASK 0xFFFF0000
#define INS_FLAGS_SET(x) (x & INS_SET_MASK)
#if 0
/* TODO: actually start using these */
#define X86_PAIR_NP 1 /* not pairable; execs in U */
#define X86_PAIR_PU 2 /* pairable in U pipe */
#define X86_PAIR_PV 3 /* pairable in V pipe */
#define X86_PAIR_UV 4 /* pairable in UV pipe */
#define X86_PAIR_FX 5 /* pairable with FXCH */
#define X86_EXEC_PORT_0 1
#define X86_EXEC_PORT_1 2
#define X86_EXEC_PORT_2 4
#define X86_EXEC_PORT_3 8
#define X86_EXEC_PORT_4 16
#define X86_EXEC_UNITS
typedef struct { /* representation of an insn during decoding */
uint32_t flags; /* runtime settings */
/* instruction prefixes and other foolishness */
uint32_t prefix; /* encoding of prefix */
char prefix_str[16]; /* mnemonics for prefix */
uint32_t branch_hint; /* gah! */
unsigned int cpu_ver; /* TODO: cpu version */
unsigned int clocks; /* TODO: clock cycles: min/max */
unsigned char last_prefix;
/* runtime intruction decoding helpers */
unsigned char mode; /* 16, 32, 64 */
unsigned char gen_regs; /* offset of default general reg set */
unsigned char sz_operand; /* operand size for insn */
unsigned char sz_address; /* address size for insn */
unsigned char uops; /* uops per insn */
unsigned char pairing; /* np,pu,pv.lv */
unsigned char exec_unit;
unsigned char exec_port;
unsigned char latency;
} ia32_info_t;
#define MODE_32 0 /* default */
#define MODE_16 1
#define MODE_64 2
#endif
#endif

View file

@ -0,0 +1,313 @@
#include <stdlib.h>
#include <string.h>
#include "ia32_invariant.h"
#include "ia32_insn.h"
#include "ia32_settings.h"
extern ia32_table_desc_t *ia32_tables;
extern ia32_settings_t ia32_settings;
extern size_t ia32_table_lookup( unsigned char *buf, size_t buf_len,
unsigned int table, ia32_insn_t **raw_insn,
unsigned int *prefixes );
/* -------------------------------- ModR/M, SIB */
/* Convenience flags */
#define MODRM_EA 1 /* ModR/M is an effective addr */
#define MODRM_reg 2 /* ModR/M is a register */
/* ModR/M flags */
#define MODRM_RM_SIB 0x04 /* R/M == 100 */
#define MODRM_RM_NOREG 0x05 /* R/B == 101 */
/* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */
#define MODRM_MOD_NODISP 0x00 /* mod == 00 */
#define MODRM_MOD_DISP8 0x01 /* mod == 01 */
#define MODRM_MOD_DISP32 0x02 /* mod == 10 */
#define MODRM_MOD_NOEA 0x03 /* mod == 11 */
/* 16-bit modrm flags */
#define MOD16_MOD_NODISP 0
#define MOD16_MOD_DISP8 1
#define MOD16_MOD_DISP16 2
#define MOD16_MOD_REG 3
#define MOD16_RM_BXSI 0
#define MOD16_RM_BXDI 1
#define MOD16_RM_BPSI 2
#define MOD16_RM_BPDI 3
#define MOD16_RM_SI 4
#define MOD16_RM_DI 5
#define MOD16_RM_BP 6
#define MOD16_RM_BX 7
/* SIB flags */
#define SIB_INDEX_NONE 0x04
#define SIB_BASE_EBP 0x05
#define SIB_SCALE_NOBASE 0x00
/* Convenience struct for modR/M bitfield */
struct modRM_byte {
unsigned int mod : 2;
unsigned int reg : 3;
unsigned int rm : 3;
};
/* Convenience struct for SIB bitfield */
struct SIB_byte {
unsigned int scale : 2;
unsigned int index : 3;
unsigned int base : 3;
};
#ifdef WIN32
static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
#else
static inline void byte_decode(unsigned char b, struct modRM_byte *modrm) {
#endif
/* generic bitfield-packing routine */
modrm->mod = b >> 6; /* top 2 bits */
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
modrm->rm = b & 7; /* bottom 3 bits */
}
static int ia32_invariant_modrm( unsigned char *in, unsigned char *out,
unsigned int mode_16, x86_invariant_op_t *op) {
struct modRM_byte modrm;
struct SIB_byte sib;
unsigned char *c, *cin;
unsigned short *s;
unsigned int *i;
int size = 0; /* modrm byte is already counted */
byte_decode(*in, &modrm); /* get bitfields */
out[0] = in[0]; /* save modrm byte */
cin = &in[1];
c = &out[1];
s = (unsigned short *)&out[1];
i = (unsigned int *)&out[1];
op->type = op_expression;
op->flags |= op_pointer;
if ( ! mode_16 && modrm.rm == MODRM_RM_SIB &&
modrm.mod != MODRM_MOD_NOEA ) {
size ++;
byte_decode(*cin, (struct modRM_byte *)(void*)&sib);
out[1] = in[1]; /* save sib byte */
cin = &in[2];
c = &out[2];
s = (unsigned short *)&out[2];
i = (unsigned int *)&out[2];
if ( sib.base == SIB_BASE_EBP && ! modrm.mod ) {
/* disp 32 is variant! */
memset( i, X86_WILDCARD_BYTE, 4 );
size += 4;
}
}
if (! modrm.mod && modrm.rm == 101) {
if ( mode_16 ) { /* straight RVA in disp */
memset( s, X86_WILDCARD_BYTE, 2 );
size += 2;
} else {
memset( i, X86_WILDCARD_BYTE, 2 );
size += 4;
}
} else if (modrm.mod && modrm.mod < 3) {
if (modrm.mod == MODRM_MOD_DISP8) { /* offset in disp */
*c = *cin;
size += 1;
} else if ( mode_16 ) {
*s = (* ((unsigned short *) cin));
size += 2;
} else {
*i = (*((unsigned int *) cin));
size += 4;
}
} else if ( modrm.mod == 3 ) {
op->type = op_register;
op->flags &= ~op_pointer;
}
return (size);
}
static int ia32_decode_invariant( unsigned char *buf, size_t buf_len,
ia32_insn_t *t, unsigned char *out,
unsigned int prefixes, x86_invariant_t *inv) {
unsigned int addr_size, op_size, mode_16;
unsigned int op_flags[3] = { t->dest_flag, t->src_flag, t->aux_flag };
int x, type, bytes = 0, size = 0, modrm = 0;
/* set addressing mode */
if (ia32_settings.options & opt_16_bit) {
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 4 : 2;
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 4 : 2;
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 0 : 1;
} else {
op_size = ( prefixes & PREFIX_OP_SIZE ) ? 2 : 4;
addr_size = ( prefixes & PREFIX_ADDR_SIZE ) ? 2 : 4;
mode_16 = ( prefixes & PREFIX_ADDR_SIZE ) ? 1 : 0;
}
for (x = 0; x < 3; x++) {
inv->operands[x].access = (enum x86_op_access)
OP_PERM(op_flags[x]);
inv->operands[x].flags = (enum x86_op_flags)
(OP_FLAGS(op_flags[x]) >> 12);
switch (op_flags[x] & OPTYPE_MASK) {
case OPTYPE_c:
size = (op_size == 4) ? 2 : 1;
break;
case OPTYPE_a: case OPTYPE_v:
size = (op_size == 4) ? 4 : 2;
break;
case OPTYPE_p:
size = (op_size == 4) ? 6 : 4;
break;
case OPTYPE_b:
size = 1;
break;
case OPTYPE_w:
size = 2;
break;
case OPTYPE_d: case OPTYPE_fs: case OPTYPE_fd:
case OPTYPE_fe: case OPTYPE_fb: case OPTYPE_fv:
case OPTYPE_si: case OPTYPE_fx:
size = 4;
break;
case OPTYPE_s:
size = 6;
break;
case OPTYPE_q: case OPTYPE_pi:
size = 8;
break;
case OPTYPE_dq: case OPTYPE_ps: case OPTYPE_ss:
case OPTYPE_pd: case OPTYPE_sd:
size = 16;
break;
case OPTYPE_m:
size = (addr_size == 4) ? 4 : 2;
break;
default:
break;
}
type = op_flags[x] & ADDRMETH_MASK;
switch (type) {
case ADDRMETH_E: case ADDRMETH_M: case ADDRMETH_Q:
case ADDRMETH_R: case ADDRMETH_W:
modrm = 1;
bytes += ia32_invariant_modrm( buf, out,
mode_16, &inv->operands[x]);
break;
case ADDRMETH_C: case ADDRMETH_D: case ADDRMETH_G:
case ADDRMETH_P: case ADDRMETH_S: case ADDRMETH_T:
case ADDRMETH_V:
inv->operands[x].type = op_register;
modrm = 1;
break;
case ADDRMETH_A: case ADDRMETH_O:
/* pad with xF4's */
memset( &out[bytes + modrm], X86_WILDCARD_BYTE,
size );
bytes += size;
inv->operands[x].type = op_offset;
if ( type == ADDRMETH_O ) {
inv->operands[x].flags |= op_signed |
op_pointer;
}
break;
case ADDRMETH_I: case ADDRMETH_J:
/* grab imm value */
if ((op_flags[x] & OPTYPE_MASK) == OPTYPE_v) {
/* assume this is an address */
memset( &out[bytes + modrm],
X86_WILDCARD_BYTE, size );
} else {
memcpy( &out[bytes + modrm],
&buf[bytes + modrm], size );
}
bytes += size;
if ( type == ADDRMETH_J ) {
if ( size == 1 ) {
inv->operands[x].type =
op_relative_near;
} else {
inv->operands[x].type =
op_relative_far;
}
inv->operands[x].flags |= op_signed;
} else {
inv->operands[x].type = op_immediate;
}
break;
case ADDRMETH_F:
inv->operands[x].type = op_register;
break;
case ADDRMETH_X:
inv->operands[x].flags |= op_signed |
op_pointer | op_ds_seg | op_string;
break;
case ADDRMETH_Y:
inv->operands[x].flags |= op_signed |
op_pointer | op_es_seg | op_string;
break;
case ADDRMETH_RR:
inv->operands[x].type = op_register;
break;
case ADDRMETH_II:
inv->operands[x].type = op_immediate;
break;
default:
inv->operands[x].type = op_unused;
break;
}
}
return (bytes + modrm);
}
size_t ia32_disasm_invariant( unsigned char * buf, size_t buf_len,
x86_invariant_t *inv ) {
ia32_insn_t *raw_insn = NULL;
unsigned int prefixes;
unsigned int type;
size_t size;
/* Perform recursive table lookup starting with main table (0) */
size = ia32_table_lookup( buf, buf_len, 0, &raw_insn, &prefixes );
if ( size == INVALID_INSN || size > buf_len ) {
/* TODO: set errno */
return 0;
}
/* copy opcode bytes to buffer */
memcpy( inv->bytes, buf, size );
/* set mnemonic type and group */
type = raw_insn->mnem_flag & ~INS_FLAG_MASK;
inv->group = (enum x86_insn_group) (INS_GROUP(type)) >> 12;
inv->type = (enum x86_insn_type) INS_TYPE(type);
/* handle operands */
size += ia32_decode_invariant( buf + size, buf_len - size, raw_insn,
&buf[size - 1], prefixes, inv );
inv->size = size;
return size; /* return size of instruction in bytes */
}
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len ) {
x86_invariant_t inv = { {0} };
return( ia32_disasm_invariant( buf, buf_len, &inv ) );
}

View file

@ -0,0 +1,11 @@
#ifndef IA32_INVARIANT_H
#define IA32_INVARIANT_H
#include "libdis.h"
size_t ia32_disasm_invariant( unsigned char *buf, size_t buf_len,
x86_invariant_t *inv);
size_t ia32_disasm_size( unsigned char *buf, size_t buf_len );
#endif

View file

@ -0,0 +1,310 @@
#include "ia32_modrm.h"
#include "ia32_reg.h"
#include "x86_imm.h"
/* NOTE: when decoding ModR/M and SIB, we have to add 1 to all register
* values obtained from decoding the ModR/M or SIB byte, since they
* are encoded with eAX = 0 and the tables in ia32_reg.c use eAX = 1.
* ADDENDUM: this is only the case when the register value is used
* directly as an index into the register table, not when it is added to
* a genregs offset. */
/* -------------------------------- ModR/M, SIB */
/* ModR/M flags */
#define MODRM_RM_SIB 0x04 /* R/M == 100 */
#define MODRM_RM_NOREG 0x05 /* R/B == 101 */
/* if (MODRM.MOD_NODISP && MODRM.RM_NOREG) then just disp32 */
#define MODRM_MOD_NODISP 0x00 /* mod == 00 */
#define MODRM_MOD_DISP8 0x01 /* mod == 01 */
#define MODRM_MOD_DISP32 0x02 /* mod == 10 */
#define MODRM_MOD_NOEA 0x03 /* mod == 11 */
/* 16-bit modrm flags */
#define MOD16_MOD_NODISP 0
#define MOD16_MOD_DISP8 1
#define MOD16_MOD_DISP16 2
#define MOD16_MOD_REG 3
#define MOD16_RM_BXSI 0
#define MOD16_RM_BXDI 1
#define MOD16_RM_BPSI 2
#define MOD16_RM_BPDI 3
#define MOD16_RM_SI 4
#define MOD16_RM_DI 5
#define MOD16_RM_BP 6
#define MOD16_RM_BX 7
/* SIB flags */
#define SIB_INDEX_NONE 0x04
#define SIB_BASE_EBP 0x05
#define SIB_SCALE_NOBASE 0x00
/* Convenience struct for modR/M bitfield */
struct modRM_byte {
unsigned int mod : 2;
unsigned int reg : 3;
unsigned int rm : 3;
};
/* Convenience struct for SIB bitfield */
struct SIB_byte {
unsigned int scale : 2;
unsigned int index : 3;
unsigned int base : 3;
};
#if 0
int modrm_rm[] = {0,1,2,3,MODRM_RM_SIB,MODRM_MOD_DISP32,6,7};
int modrm_reg[] = {0, 1, 2, 3, 4, 5, 6, 7};
int modrm_mod[] = {0, MODRM_MOD_DISP8, MODRM_MOD_DISP32, MODRM_MOD_NOEA};
int sib_scl[] = {0, 2, 4, 8};
int sib_idx[] = {0, 1, 2, 3, SIB_INDEX_NONE, 5, 6, 7 };
int sib_bas[] = {0, 1, 2, 3, 4, SIB_SCALE_NOBASE, 6, 7 };
#endif
/* this is needed to replace x86_imm_signsized() which does not sign-extend
* to dest */
static unsigned int imm32_signsized( unsigned char *buf, size_t buf_len,
int32_t *dest, unsigned int size ) {
if ( size > buf_len ) {
return 0;
}
switch (size) {
case 1:
*dest = *((signed char *) buf);
break;
case 2:
*dest = *((signed short *) buf);
break;
case 4:
default:
*dest = *((signed int *) buf);
break;
}
return size;
}
static void byte_decode(unsigned char b, struct modRM_byte *modrm) {
/* generic bitfield-packing routine */
modrm->mod = b >> 6; /* top 2 bits */
modrm->reg = (b & 56) >> 3; /* middle 3 bits */
modrm->rm = b & 7; /* bottom 3 bits */
}
static size_t sib_decode( unsigned char *buf, size_t buf_len, x86_ea_t *ea,
unsigned int mod ) {
/* set Address Expression fields (scale, index, base, disp)
* according to the contents of the SIB byte.
* b points to the SIB byte in the instruction-stream buffer; the
* byte after b[0] is therefore the byte after the SIB
* returns number of bytes 'used', including the SIB byte */
size_t size = 1; /* start at 1 for SIB byte */
struct SIB_byte sib;
if ( buf_len < 1 ) {
return 0;
}
byte_decode( *buf, (struct modRM_byte *)(void*)&sib ); /* get bit-fields */
if ( sib.base == SIB_BASE_EBP && ! mod ) { /* if base == 101 (ebp) */
/* IF BASE == EBP, deal with exception */
/* IF (ModR/M did not create a Disp */
/* ... create a 32-bit Displacement */
imm32_signsized( &buf[1], buf_len, &ea->disp, sizeof(int32_t));
ea->disp_size = sizeof(int32_t);
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
size += 4; /* add sizeof disp to count */
} else {
/* ELSE BASE refers to a General Register */
ia32_handle_register( &ea->base, sib.base + 1 );
}
/* set scale to 1, 2, 4, 8 */
ea->scale = 1 << sib.scale;
if (sib.index != SIB_INDEX_NONE) {
/* IF INDEX is not 'ESP' (100) */
ia32_handle_register( &ea->index, sib.index + 1 );
}
return (size); /* return number of bytes processed */
}
static size_t modrm_decode16( unsigned char *buf, unsigned int buf_len,
x86_op_t *op, struct modRM_byte *modrm ) {
/* 16-bit mode: hackish, but not as hackish as 32-bit mode ;) */
size_t size = 1; /* # of bytes decoded [1 for modR/M byte] */
x86_ea_t * ea = &op->data.expression;
switch( modrm->rm ) {
case MOD16_RM_BXSI:
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
break;
case MOD16_RM_BXDI:
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
case MOD16_RM_BPSI:
op->flags |= op_ss_seg;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 6);
break;
case MOD16_RM_BPDI:
op->flags |= op_ss_seg;
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 5);
ia32_handle_register(&ea->index, REG_WORD_OFFSET + 7);
break;
case MOD16_RM_SI:
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 6);
break;
case MOD16_RM_DI:
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 7);
break;
case MOD16_RM_BP:
if ( modrm->mod != MOD16_MOD_NODISP ) {
op->flags |= op_ss_seg;
ia32_handle_register(&ea->base,
REG_WORD_OFFSET + 5);
}
break;
case MOD16_RM_BX:
ia32_handle_register(&ea->base, REG_WORD_OFFSET + 3);
break;
}
/* move to byte after ModR/M */
++buf;
--buf_len;
if ( modrm->mod == MOD16_MOD_DISP8 ) {
imm32_signsized( buf, buf_len, &ea->disp, sizeof(char) );
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
ea->disp_size = sizeof(char);
size += sizeof(char);
} else if ( modrm->mod == MOD16_MOD_DISP16 ) {
imm32_signsized( buf, buf_len, &ea->disp, sizeof(short) );
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
ea->disp_size = sizeof(short);
size += sizeof(short);
}
return size;
}
/* TODO : Mark index modes
Use addressing mode flags to imply arrays (index), structure (disp),
two-dimensional arrays [disp + index], classes [ea reg], and so on.
*/
size_t ia32_modrm_decode( unsigned char *buf, unsigned int buf_len,
x86_op_t *op, x86_insn_t *insn, size_t gen_regs ) {
/* create address expression and/or fill operand based on value of
* ModR/M byte. Calls sib_decode as appropriate.
* flags specifies whether Reg or mod+R/M fields are being decoded
* returns the number of bytes in the instruction, including modR/M */
struct modRM_byte modrm;
size_t size = 1; /* # of bytes decoded [1 for modR/M byte] */
x86_ea_t * ea;
byte_decode(*buf, &modrm); /* get bitfields */
/* first, handle the case where the mod field is a register only */
if ( modrm.mod == MODRM_MOD_NOEA ) {
op->type = op_register;
ia32_handle_register(&op->data.reg, modrm.rm + gen_regs);
/* increase insn size by 1 for modrm byte */
return 1;
}
/* then deal with cases where there is an effective address */
ea = &op->data.expression;
op->type = op_expression;
op->flags |= op_pointer;
if ( insn->addr_size == 2 ) {
/* gah! 16 bit mode! */
return modrm_decode16( buf, buf_len, op, &modrm);
}
/* move to byte after ModR/M */
++buf;
--buf_len;
if (modrm.mod == MODRM_MOD_NODISP) { /* if mod == 00 */
/* IF MOD == No displacement, just Indirect Register */
if (modrm.rm == MODRM_RM_NOREG) { /* if r/m == 101 */
/* IF RM == No Register, just Displacement */
/* This is an Intel Moronic Exception TM */
imm32_signsized( buf, buf_len, &ea->disp,
sizeof(int32_t) );
ea->disp_size = sizeof(int32_t);
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
size += 4; /* add sizeof disp to count */
} else if (modrm.rm == MODRM_RM_SIB) { /* if r/m == 100 */
/* ELSE IF an SIB byte is present */
/* TODO: check for 0 retval */
size += sib_decode( buf, buf_len, ea, modrm.mod);
/* move to byte after SIB for displacement */
++buf;
--buf_len;
} else { /* modR/M specifies base register */
/* ELSE RM encodes a general register */
ia32_handle_register( &ea->base, modrm.rm + 1 );
}
} else { /* mod is 01 or 10 */
if (modrm.rm == MODRM_RM_SIB) { /* rm == 100 */
/* IF base is an AddrExpr specified by an SIB byte */
/* TODO: check for 0 retval */
size += sib_decode( buf, buf_len, ea, modrm.mod);
/* move to byte after SIB for displacement */
++buf;
--buf_len;
} else {
/* ELSE base is a general register */
ia32_handle_register( &ea->base, modrm.rm + 1 );
}
/* ELSE mod + r/m specify a disp##[base] or disp##(SIB) */
if (modrm.mod == MODRM_MOD_DISP8) { /* mod == 01 */
/* If this is an 8-bit displacement */
imm32_signsized( buf, buf_len, &ea->disp,
sizeof(char));
ea->disp_size = sizeof(char);
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
size += 1; /* add sizeof disp to count */
} else {
/* Displacement is dependent on address size */
imm32_signsized( buf, buf_len, &ea->disp,
insn->addr_size);
ea->disp_size = insn->addr_size;
ea->disp_sign = (ea->disp < 0) ? 1 : 0;
size += 4;
}
}
return size; /* number of bytes found in instruction */
}
void ia32_reg_decode( unsigned char byte, x86_op_t *op, size_t gen_regs ) {
struct modRM_byte modrm;
byte_decode( byte, &modrm ); /* get bitfields */
/* set operand to register ID */
op->type = op_register;
ia32_handle_register(&op->data.reg, modrm.reg + gen_regs);
return;
}

View file

@ -0,0 +1,13 @@
#ifndef IA32_MODRM_H
#define IA32_MODRM_H
#include "libdis.h"
#include "ia32_insn.h"
size_t ia32_modrm_decode( unsigned char *buf, unsigned int buf_len,
x86_op_t *op, x86_insn_t *insn,
size_t gen_regs );
void ia32_reg_decode( unsigned char byte, x86_op_t *op, size_t gen_regs );
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,57 @@
#define idx_Main 0
#define idx_66 1
#define idx_F2 2
#define idx_F3 3
#define idx_0F 4
#define idx_660F 5
#define idx_F20F 6
#define idx_F30F 7
#define idx_0F00 8
#define idx_0F01 9
#define idx_0F0111 10
#define idx_0F12 11
#define idx_0F16 12
#define idx_0F18 13
#define idx_0F71 14
#define idx_660F71 15
#define idx_0F72 16
#define idx_660F72 17
#define idx_0F73 18
#define idx_660F73 19
#define idx_0FAE 20
#define idx_0FBA 21
#define idx_0FC7 22
#define idx_0FB9 23
#define idx_C6 24
#define idx_C7 25
#define idx_80 26
#define idx_81 27
#define idx_82 28
#define idx_83 29
#define idx_C0 30
#define idx_C1 31
#define idx_D0 32
#define idx_D1 33
#define idx_D2 34
#define idx_D3 35
#define idx_F6 36
#define idx_F7 37
#define idx_FE 38
#define idx_FF 39
#define idx_D8 40
#define idx_D8C0 41
#define idx_D9 42
#define idx_D9C0 43
#define idx_DA 44
#define idx_DAC0 45
#define idx_DB 46
#define idx_DBC0 47
#define idx_DC 48
#define idx_DCC0 49
#define idx_DD 50
#define idx_DDC0 51
#define idx_DE 52
#define idx_DEC0 53
#define idx_DF 54
#define idx_DFC0 55
#define idx_0F0F 56

View file

@ -0,0 +1,425 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libdis.h"
#include "ia32_insn.h"
#include "ia32_operand.h"
#include "ia32_modrm.h"
#include "ia32_reg.h"
#include "x86_imm.h"
#include "x86_operand_list.h"
/* apply segment override to memory operand in insn */
static void apply_seg( x86_op_t *op, unsigned int prefixes ) {
if (! prefixes ) return;
/* apply overrides from prefix */
switch ( prefixes & PREFIX_REG_MASK ) {
case PREFIX_CS:
op->flags |= op_cs_seg; break;
case PREFIX_SS:
op->flags |= op_ss_seg; break;
case PREFIX_DS:
op->flags |= op_ds_seg; break;
case PREFIX_ES:
op->flags |= op_es_seg; break;
case PREFIX_FS:
op->flags |= op_fs_seg; break;
case PREFIX_GS:
op->flags |= op_gs_seg; break;
}
return;
}
static size_t decode_operand_value( unsigned char *buf, size_t buf_len,
x86_op_t *op, x86_insn_t *insn,
unsigned int addr_meth, size_t op_size,
unsigned int op_value, unsigned char modrm,
size_t gen_regs ) {
size_t size = 0;
/* ++ Do Operand Addressing Method / Decode operand ++ */
switch (addr_meth) {
/* This sets the operand Size based on the Intel Opcode Map
* (Vol 2, Appendix A). Letter encodings are from section
* A.1.1, 'Codes for Addressing Method' */
/* ---------------------- Addressing Method -------------- */
/* Note that decoding mod ModR/M operand adjusts the size of
* the instruction, but decoding the reg operand does not.
* This should not cause any problems, as every 'reg' operand
* has an associated 'mod' operand.
* Goddamn-Intel-Note:
* Some Intel addressing methods [M, R] specify that modR/M
* byte may only refer to a memory address/may only refer to
* a register -- however Intel provides no clues on what to do
* if, say, the modR/M for an M opcode decodes to a register
* rather than a memory address ... returning 0 is out of the
* question, as this would be an Immediate or a RelOffset, so
* instead these modR/Ms are decoded with total disregard to
* the M, R constraints. */
/* MODRM -- mod operand. sets size to at least 1! */
case ADDRMETH_E: /* ModR/M present, Gen reg or memory */
size = ia32_modrm_decode( buf, buf_len, op, insn,
gen_regs );
break;
case ADDRMETH_M: /* ModR/M only refers to memory */
size = ia32_modrm_decode( buf, buf_len, op, insn,
gen_regs );
break;
case ADDRMETH_Q: /* ModR/M present, MMX or Memory */
size = ia32_modrm_decode( buf, buf_len, op, insn,
REG_MMX_OFFSET );
break;
case ADDRMETH_R: /* ModR/M mod == gen reg */
size = ia32_modrm_decode( buf, buf_len, op, insn,
gen_regs );
break;
case ADDRMETH_W: /* ModR/M present, mem or SIMD reg */
size = ia32_modrm_decode( buf, buf_len, op, insn,
REG_SIMD_OFFSET );
break;
/* MODRM -- reg operand. does not effect size! */
case ADDRMETH_C: /* ModR/M reg == control reg */
ia32_reg_decode( modrm, op, REG_CTRL_OFFSET );
break;
case ADDRMETH_D: /* ModR/M reg == debug reg */
ia32_reg_decode( modrm, op, REG_DEBUG_OFFSET );
break;
case ADDRMETH_G: /* ModR/M reg == gen-purpose reg */
ia32_reg_decode( modrm, op, gen_regs );
break;
case ADDRMETH_P: /* ModR/M reg == qword MMX reg */
ia32_reg_decode( modrm, op, REG_MMX_OFFSET );
break;
case ADDRMETH_S: /* ModR/M reg == segment reg */
ia32_reg_decode( modrm, op, REG_SEG_OFFSET );
break;
case ADDRMETH_T: /* ModR/M reg == test reg */
ia32_reg_decode( modrm, op, REG_TEST_OFFSET );
break;
case ADDRMETH_V: /* ModR/M reg == SIMD reg */
ia32_reg_decode( modrm, op, REG_SIMD_OFFSET );
break;
/* No MODRM : note these set operand type explicitly */
case ADDRMETH_A: /* No modR/M -- direct addr */
op->type = op_absolute;
/* segment:offset address used in far calls */
x86_imm_sized( buf, buf_len,
&op->data.absolute.segment, 2 );
if ( insn->addr_size == 4 ) {
x86_imm_sized( buf, buf_len,
&op->data.absolute.offset.off32, 4 );
size = 6;
} else {
x86_imm_sized( buf, buf_len,
&op->data.absolute.offset.off16, 2 );
size = 4;
}
break;
case ADDRMETH_I: /* Immediate val */
op->type = op_immediate;
/* if it ever becomes legal to have imm as dest and
* there is a src ModR/M operand, we are screwed! */
if ( op->flags & op_signed ) {
x86_imm_signsized(buf, buf_len, &op->data.byte,
op_size);
} else {
x86_imm_sized(buf, buf_len, &op->data.byte,
op_size);
}
size = op_size;
break;
case ADDRMETH_J: /* Rel offset to add to IP [jmp] */
/* this fills op->data.near_offset or
op->data.far_offset depending on the size of
the operand */
op->flags |= op_signed;
if ( op_size == 1 ) {
/* one-byte near offset */
op->type = op_relative_near;
x86_imm_signsized(buf, buf_len,
&op->data.relative_near, 1);
} else {
/* far offset...is this truly signed? */
op->type = op_relative_far;
x86_imm_signsized(buf, buf_len,
&op->data.relative_far, op_size );
}
size = op_size;
break;
case ADDRMETH_O: /* No ModR/M; op is word/dword offset */
/* NOTE: these are actually RVAs not offsets to seg!! */
/* note bene: 'O' ADDR_METH uses addr_size to
determine operand size */
op->type = op_offset;
op->flags |= op_pointer;
x86_imm_sized( buf, buf_len, &op->data.offset,
insn->addr_size );
size = insn->addr_size;
break;
/* Hard-coded: these are specified in the insn definition */
case ADDRMETH_F: /* EFLAGS register */
op->type = op_register;
op->flags |= op_hardcode;
ia32_handle_register( &op->data.reg, REG_FLAGS_INDEX );
break;
case ADDRMETH_X: /* Memory addressed by DS:SI [string] */
op->type = op_expression;
op->flags |= op_hardcode;
op->flags |= op_ds_seg | op_pointer | op_string;
ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 6 );
break;
case ADDRMETH_Y: /* Memory addressed by ES:DI [string] */
op->type = op_expression;
op->flags |= op_hardcode;
op->flags |= op_es_seg | op_pointer | op_string;
ia32_handle_register( &op->data.expression.base,
REG_DWORD_OFFSET + 7 );
break;
case ADDRMETH_RR: /* Gen Register hard-coded in opcode */
op->type = op_register;
op->flags |= op_hardcode;
ia32_handle_register( &op->data.reg,
op_value + gen_regs );
break;
case ADDRMETH_RS: /* Seg Register hard-coded in opcode */
op->type = op_register;
op->flags |= op_hardcode;
ia32_handle_register( &op->data.reg,
op_value + REG_SEG_OFFSET );
break;
case ADDRMETH_RF: /* FPU Register hard-coded in opcode */
op->type = op_register;
op->flags |= op_hardcode;
ia32_handle_register( &op->data.reg,
op_value + REG_FPU_OFFSET );
break;
case ADDRMETH_RT: /* TST Register hard-coded in opcode */
op->type = op_register;
op->flags |= op_hardcode;
ia32_handle_register( &op->data.reg,
op_value + REG_TEST_OFFSET );
break;
case ADDRMETH_II: /* Immediate hard-coded in opcode */
op->type = op_immediate;
op->data.dword = op_value;
op->flags |= op_hardcode;
break;
case 0: /* Operand is not used */
default:
/* ignore -- operand not used in this insn */
op->type = op_unused; /* this shouldn't happen! */
break;
}
return size;
}
static size_t decode_operand_size( unsigned int op_type, x86_insn_t *insn,
x86_op_t *op ){
size_t size;
/* ++ Do Operand Type ++ */
switch (op_type) {
/* This sets the operand Size based on the Intel Opcode Map
* (Vol 2, Appendix A). Letter encodings are from section
* A.1.2, 'Codes for Operand Type' */
/* NOTE: in this routines, 'size' refers to the size
* of the operand in the raw (encoded) instruction;
* 'datatype' stores the actual size and datatype
* of the operand */
/* ------------------------ Operand Type ----------------- */
case OPTYPE_c: /* byte or word [op size attr] */
size = (insn->op_size == 4) ? 2 : 1;
op->datatype = (size == 4) ? op_word : op_byte;
break;
case OPTYPE_a: /* 2 word or 2 dword [op size attr] */
/* pointer to a 16:16 or 32:32 BOUNDS operand */
size = (insn->op_size == 4) ? 8 : 4;
op->datatype = (size == 4) ? op_bounds32 : op_bounds16;
break;
case OPTYPE_v: /* word or dword [op size attr] */
size = (insn->op_size == 4) ? 4 : 2;
op->datatype = (size == 4) ? op_dword : op_word;
break;
case OPTYPE_p: /* 32/48-bit ptr [op size attr] */
/* technically these flags are not accurate: the
* value s a 16:16 pointer or a 16:32 pointer, where
* the first '16' is a segment */
size = (insn->addr_size == 4) ? 6 : 4;
op->datatype = (size == 4) ? op_descr32 : op_descr16;
break;
case OPTYPE_b: /* byte, ignore op-size */
size = 1;
op->datatype = op_byte;
break;
case OPTYPE_w: /* word, ignore op-size */
size = 2;
op->datatype = op_word;
break;
case OPTYPE_d: /* dword , ignore op-size */
size = 4;
op->datatype = op_dword;
break;
case OPTYPE_s: /* 6-byte psuedo-descriptor */
/* ptr to 6-byte value which is 32:16 in 32-bit
* mode, or 8:24:16 in 16-bit mode. The high byte
* is ignored in 16-bit mode. */
size = 6;
op->datatype = (insn->addr_size == 4) ?
op_pdescr32 : op_pdescr16;
break;
case OPTYPE_q: /* qword, ignore op-size */
size = 8;
op->datatype = op_qword;
break;
case OPTYPE_dq: /* d-qword, ignore op-size */
size = 16;
op->datatype = op_dqword;
break;
case OPTYPE_ps: /* 128-bit FP data */
size = 16;
/* really this is 4 packed SP FP values */
op->datatype = op_ssimd;
break;
case OPTYPE_pd: /* 128-bit FP data */
size = 16;
/* really this is 2 packed DP FP values */
op->datatype = op_dsimd;
break;
case OPTYPE_ss: /* Scalar elem of 128-bit FP data */
size = 16;
/* this only looks at the low dword (4 bytes)
* of the xmmm register passed as a param.
* This is a 16-byte register where only 4 bytes
* are used in the insn. Painful, ain't it? */
op->datatype = op_sssimd;
break;
case OPTYPE_sd: /* Scalar elem of 128-bit FP data */
size = 16;
/* this only looks at the low qword (8 bytes)
* of the xmmm register passed as a param.
* This is a 16-byte register where only 8 bytes
* are used in the insn. Painful, again... */
op->datatype = op_sdsimd;
break;
case OPTYPE_pi: /* qword mmx register */
size = 8;
op->datatype = op_qword;
break;
case OPTYPE_si: /* dword integer register */
size = 4;
op->datatype = op_dword;
break;
case OPTYPE_fs: /* single-real */
size = 4;
op->datatype = op_sreal;
break;
case OPTYPE_fd: /* double real */
size = 8;
op->datatype = op_dreal;
break;
case OPTYPE_fe: /* extended real */
size = 10;
op->datatype = op_extreal;
break;
case OPTYPE_fb: /* packed BCD */
size = 10;
op->datatype = op_bcd;
break;
case OPTYPE_fv: /* pointer to FPU env: 14 or 28-bytes */
size = (insn->addr_size == 4)? 28 : 14;
op->datatype = (size == 28)? op_fpuenv32: op_fpuenv16;
break;
case OPTYPE_ft: /* pointer to FPU env: 94 or 108 bytes */
size = (insn->addr_size == 4)? 108 : 94;
op->datatype = (size == 108)?
op_fpustate32: op_fpustate16;
break;
case OPTYPE_fx: /* 512-byte register stack */
size = 512;
op->datatype = op_fpregset;
break;
case OPTYPE_fp: /* floating point register */
size = 10; /* double extended precision */
op->datatype = op_fpreg;
break;
case OPTYPE_m: /* fake operand type used for "lea Gv, M" */
size = insn->addr_size;
op->datatype = (size == 4) ? op_dword : op_word;
break;
case OPTYPE_none: /* handle weird instructions that have no encoding but use a dword datatype, like invlpg */
size = 0;
op->datatype = op_none;
break;
case 0:
default:
size = insn->op_size;
op->datatype = (size == 4) ? op_dword : op_word;
break;
}
return size;
}
size_t ia32_decode_operand( unsigned char *buf, size_t buf_len,
x86_insn_t *insn, unsigned int raw_op,
unsigned int raw_flags, unsigned int prefixes,
unsigned char modrm ) {
unsigned int addr_meth, op_type, op_size, gen_regs;
x86_op_t *op;
size_t size;
/* ++ Yank optype and addr mode out of operand flags */
addr_meth = raw_flags & ADDRMETH_MASK;
op_type = raw_flags & OPTYPE_MASK;
if ( raw_flags == ARG_NONE ) {
/* operand is not used in this instruction */
return 0;
}
/* allocate a new operand */
op = x86_operand_new( insn );
/* ++ Copy flags from opcode table to x86_insn_t */
op->access = (enum x86_op_access) OP_PERM(raw_flags);
op->flags = (enum x86_op_flags) (OP_FLAGS(raw_flags) >> 12);
/* Get size (for decoding) and datatype of operand */
op_size = decode_operand_size(op_type, insn, op);
/* override default register set based on Operand Type */
/* this allows mixing of 8, 16, and 32 bit regs in insn */
if (op_size == 1) {
gen_regs = REG_BYTE_OFFSET;
} else if (op_size == 2) {
gen_regs = REG_WORD_OFFSET;
} else {
gen_regs = REG_DWORD_OFFSET;
}
size = decode_operand_value( buf, buf_len, op, insn, addr_meth,
op_size, raw_op, modrm, gen_regs );
/* if operand is an address, apply any segment override prefixes */
if ( op->type == op_expression || op->type == op_offset ) {
apply_seg(op, prefixes);
}
return size; /* return number of bytes in instruction */
}

View file

@ -0,0 +1,11 @@
#ifndef IA32_OPERAND_H
#define IA32_OPERAND_H
#include "libdis.h"
#include "ia32_insn.h"
size_t ia32_decode_operand( unsigned char *buf, size_t buf_len,
x86_insn_t *insn, unsigned int raw_op,
unsigned int raw_flags, unsigned int prefixes,
unsigned char modrm );
#endif

View file

@ -0,0 +1,234 @@
#include <stdlib.h>
#include <string.h>
#include "ia32_reg.h"
#include "ia32_insn.h"
#define NUM_X86_REGS 92
/* register sizes */
#define REG_DWORD_SIZE 4
#define REG_WORD_SIZE 2
#define REG_BYTE_SIZE 1
#define REG_MMX_SIZE 8
#define REG_SIMD_SIZE 16
#define REG_DEBUG_SIZE 4
#define REG_CTRL_SIZE 4
#define REG_TEST_SIZE 4
#define REG_SEG_SIZE 2
#define REG_FPU_SIZE 10
#define REG_FLAGS_SIZE 4
#define REG_FPCTRL_SIZE 2
#define REG_FPSTATUS_SIZE 2
#define REG_FPTAG_SIZE 2
#define REG_EIP_SIZE 4
#define REG_IP_SIZE 2
/* REGISTER ALIAS TABLE:
*
* NOTE: the MMX register mapping is fixed to the physical registers
* used by the FPU. The floating FP stack does not effect the location
* of the MMX registers, so this aliasing is not 100% accurate.
* */
static struct {
unsigned char alias; /* id of register this is an alias for */
unsigned char shift; /* # of bits register must be shifted */
} ia32_reg_aliases[] = {
{ 0,0 },
{ REG_DWORD_OFFSET, 0 }, /* al : 1 */
{ REG_DWORD_OFFSET, 8 }, /* ah : 2 */
{ REG_DWORD_OFFSET, 0 }, /* ax : 3 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cl : 4 */
{ REG_DWORD_OFFSET + 1, 8 }, /* ch : 5 */
{ REG_DWORD_OFFSET + 1, 0 }, /* cx : 6 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dl : 7 */
{ REG_DWORD_OFFSET + 2, 8 }, /* dh : 8 */
{ REG_DWORD_OFFSET + 2, 0 }, /* dx : 9 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bl : 10 */
{ REG_DWORD_OFFSET + 3, 8 }, /* bh : 11 */
{ REG_DWORD_OFFSET + 3, 0 }, /* bx : 12 */
{ REG_DWORD_OFFSET + 4, 0 }, /* sp : 13 */
{ REG_DWORD_OFFSET + 5, 0 }, /* bp : 14 */
{ REG_DWORD_OFFSET + 6, 0 }, /* si : 15 */
{ REG_DWORD_OFFSET + 7, 0 }, /* di : 16 */
{ REG_EIP_INDEX, 0 }, /* ip : 17 */
{ REG_FPU_OFFSET, 0 }, /* mm0 : 18 */
{ REG_FPU_OFFSET + 1, 0 }, /* mm1 : 19 */
{ REG_FPU_OFFSET + 2, 0 }, /* mm2 : 20 */
{ REG_FPU_OFFSET + 3, 0 }, /* mm3 : 21 */
{ REG_FPU_OFFSET + 4, 0 }, /* mm4 : 22 */
{ REG_FPU_OFFSET + 5, 0 }, /* mm5 : 23 */
{ REG_FPU_OFFSET + 6, 0 }, /* mm6 : 24 */
{ REG_FPU_OFFSET + 7, 0 } /* mm7 : 25 */
};
/* REGISTER TABLE: size, type, and name of every register in the
* CPU. Does not include MSRs since the are, after all,
* model specific. */
static struct {
unsigned int size;
enum x86_reg_type type;
unsigned int alias;
char mnemonic[8];
} ia32_reg_table[NUM_X86_REGS + 2] = {
{ 0, 0, 0, "" },
/* REG_DWORD_OFFSET */
{ REG_DWORD_SIZE, reg_gen | reg_ret, 0, "eax" },
{ REG_DWORD_SIZE, reg_gen | reg_count, 0, "ecx" },
{ REG_DWORD_SIZE, reg_gen, 0, "edx" },
{ REG_DWORD_SIZE, reg_gen, 0, "ebx" },
/* REG_ESP_INDEX */
{ REG_DWORD_SIZE, reg_gen | reg_sp, 0, "esp" },
{ REG_DWORD_SIZE, reg_gen | reg_fp, 0, "ebp" },
{ REG_DWORD_SIZE, reg_gen | reg_src, 0, "esi" },
{ REG_DWORD_SIZE, reg_gen | reg_dest, 0, "edi" },
/* REG_WORD_OFFSET */
{ REG_WORD_SIZE, reg_gen | reg_ret, 3, "ax" },
{ REG_WORD_SIZE, reg_gen | reg_count, 6, "cx" },
{ REG_WORD_SIZE, reg_gen, 9, "dx" },
{ REG_WORD_SIZE, reg_gen, 12, "bx" },
{ REG_WORD_SIZE, reg_gen | reg_sp, 13, "sp" },
{ REG_WORD_SIZE, reg_gen | reg_fp, 14, "bp" },
{ REG_WORD_SIZE, reg_gen | reg_src, 15, "si" },
{ REG_WORD_SIZE, reg_gen | reg_dest, 16, "di" },
/* REG_BYTE_OFFSET */
{ REG_BYTE_SIZE, reg_gen, 1, "al" },
{ REG_BYTE_SIZE, reg_gen, 4, "cl" },
{ REG_BYTE_SIZE, reg_gen, 7, "dl" },
{ REG_BYTE_SIZE, reg_gen, 10, "bl" },
{ REG_BYTE_SIZE, reg_gen, 2, "ah" },
{ REG_BYTE_SIZE, reg_gen, 5, "ch" },
{ REG_BYTE_SIZE, reg_gen, 8, "dh" },
{ REG_BYTE_SIZE, reg_gen, 11, "bh" },
/* REG_MMX_OFFSET */
{ REG_MMX_SIZE, reg_simd, 18, "mm0" },
{ REG_MMX_SIZE, reg_simd, 19, "mm1" },
{ REG_MMX_SIZE, reg_simd, 20, "mm2" },
{ REG_MMX_SIZE, reg_simd, 21, "mm3" },
{ REG_MMX_SIZE, reg_simd, 22, "mm4" },
{ REG_MMX_SIZE, reg_simd, 23, "mm5" },
{ REG_MMX_SIZE, reg_simd, 24, "mm6" },
{ REG_MMX_SIZE, reg_simd, 25, "mm7" },
/* REG_SIMD_OFFSET */
{ REG_SIMD_SIZE, reg_simd, 0, "xmm0" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm1" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm2" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm3" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm4" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm5" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm6" },
{ REG_SIMD_SIZE, reg_simd, 0, "xmm7" },
/* REG_DEBUG_OFFSET */
{ REG_DEBUG_SIZE, reg_sys, 0, "dr0" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr1" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr2" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr3" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr4" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr5" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr6" },
{ REG_DEBUG_SIZE, reg_sys, 0, "dr7" },
/* REG_CTRL_OFFSET */
{ REG_CTRL_SIZE, reg_sys, 0, "cr0" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr1" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr2" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr3" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr4" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr5" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr6" },
{ REG_CTRL_SIZE, reg_sys, 0, "cr7" },
/* REG_TEST_OFFSET */
{ REG_TEST_SIZE, reg_sys, 0, "tr0" },
{ REG_TEST_SIZE, reg_sys, 0, "tr1" },
{ REG_TEST_SIZE, reg_sys, 0, "tr2" },
{ REG_TEST_SIZE, reg_sys, 0, "tr3" },
{ REG_TEST_SIZE, reg_sys, 0, "tr4" },
{ REG_TEST_SIZE, reg_sys, 0, "tr5" },
{ REG_TEST_SIZE, reg_sys, 0, "tr6" },
{ REG_TEST_SIZE, reg_sys, 0, "tr7" },
/* REG_SEG_OFFSET */
{ REG_SEG_SIZE, reg_seg, 0, "es" },
{ REG_SEG_SIZE, reg_seg, 0, "cs" },
{ REG_SEG_SIZE, reg_seg, 0, "ss" },
{ REG_SEG_SIZE, reg_seg, 0, "ds" },
{ REG_SEG_SIZE, reg_seg, 0, "fs" },
{ REG_SEG_SIZE, reg_seg, 0, "gs" },
/* REG_LDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "ldtr" },
/* REG_GDTR_INDEX */
{ REG_DWORD_SIZE, reg_sys, 0, "gdtr" },
/* REG_FPU_OFFSET */
{ REG_FPU_SIZE, reg_fpu, 0, "st(0)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(1)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(2)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(3)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(4)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(5)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(6)" },
{ REG_FPU_SIZE, reg_fpu, 0, "st(7)" },
/* REG_FLAGS_INDEX : 81 */
{ REG_FLAGS_SIZE, reg_cond, 0, "eflags" },
/* REG_FPCTRL_INDEX : 82*/
{ REG_FPCTRL_SIZE, reg_fpu | reg_sys, 0, "fpctrl" },
/* REG_FPSTATUS_INDEX : 83*/
{ REG_FPSTATUS_SIZE, reg_fpu | reg_sys, 0, "fpstat" },
/* REG_FPTAG_INDEX : 84 */
{ REG_FPTAG_SIZE, reg_fpu | reg_sys, 0, "fptag" },
/* REG_EIP_INDEX : 85 */
{ REG_EIP_SIZE, reg_pc, 0, "eip" },
/* REG_IP_INDEX : 86 */
{ REG_IP_SIZE, reg_pc, 17, "ip" },
/* REG_IDTR_INDEX : 87 */
{ REG_DWORD_SIZE, reg_sys, 0, "idtr" },
/* REG_MXCSG_INDEX : SSE Control Reg : 88 */
{ REG_DWORD_SIZE, reg_sys | reg_simd, 0, "mxcsr" },
/* REG_TR_INDEX : Task Register : 89 */
{ 16 + 64, reg_sys, 0, "tr" },
/* REG_CSMSR_INDEX : SYSENTER_CS_MSR : 90 */
{ REG_DWORD_SIZE, reg_sys, 0, "cs_msr" },
/* REG_ESPMSR_INDEX : SYSENTER_ESP_MSR : 91 */
{ REG_DWORD_SIZE, reg_sys, 0, "esp_msr" },
/* REG_EIPMSR_INDEX : SYSENTER_EIP_MSR : 92 */
{ REG_DWORD_SIZE, reg_sys, 0, "eip_msr" },
{ 0 }
};
static size_t sz_regtable = NUM_X86_REGS + 1;
void ia32_handle_register( x86_reg_t *reg, size_t id ) {
unsigned int alias;
if (! id || id > sz_regtable ) {
return;
}
memset( reg, 0, sizeof(x86_reg_t) );
strncpy( reg->name, ia32_reg_table[id].mnemonic, MAX_REGNAME );
reg->type = ia32_reg_table[id].type;
reg->size = ia32_reg_table[id].size;
alias = ia32_reg_table[id].alias;
if ( alias ) {
reg->alias = ia32_reg_aliases[alias].alias;
reg->shift = ia32_reg_aliases[alias].shift;
}
reg->id = id;
return;
}
size_t ia32_true_register_id( size_t id ) {
size_t reg;
if (! id || id > sz_regtable ) {
return 0;
}
reg = id;
if (ia32_reg_table[reg].alias) {
reg = ia32_reg_aliases[ia32_reg_table[reg].alias].alias;
}
return reg;
}

View file

@ -0,0 +1,41 @@
#ifndef IA32_REG_H
#define IA32_REG_H
#include <sys/types.h> /* for size_t */
#include "libdis.h" /* for x86_reg_t */
/* NOTE these are used in opcode tables for hard-coded registers */
#define REG_DWORD_OFFSET 1 /* 0 + 1 */
#define REG_ECX_INDEX 2 /* 0 + 1 + 1 */
#define REG_ESP_INDEX 5 /* 0 + 4 + 1 */
#define REG_EBP_INDEX 6 /* 0 + 5 + 1 */
#define REG_ESI_INDEX 7 /* 0 + 6 + 1 */
#define REG_EDI_INDEX 8 /* 0 + 7 + 1 */
#define REG_WORD_OFFSET 9 /* 1 * 8 + 1 */
#define REG_BYTE_OFFSET 17 /* 2 * 8 + 1 */
#define REG_MMX_OFFSET 25 /* 3 * 8 + 1 */
#define REG_SIMD_OFFSET 33 /* 4 * 8 + 1 */
#define REG_DEBUG_OFFSET 41 /* 5 * 8 + 1 */
#define REG_CTRL_OFFSET 49 /* 6 * 8 + 1 */
#define REG_TEST_OFFSET 57 /* 7 * 8 + 1 */
#define REG_SEG_OFFSET 65 /* 8 * 8 + 1 */
#define REG_LDTR_INDEX 71 /* 8 * 8 + 1 + 1 */
#define REG_GDTR_INDEX 72 /* 8 * 8 + 2 + 1 */
#define REG_FPU_OFFSET 73 /* 9 * 8 + 1 */
#define REG_FLAGS_INDEX 81 /* 10 * 8 + 1 */
#define REG_FPCTRL_INDEX 82 /* 10 * 8 + 1 + 1 */
#define REG_FPSTATUS_INDEX 83 /* 10 * 8 + 2 + 1 */
#define REG_FPTAG_INDEX 84 /* 10 * 8 + 3 + 1 */
#define REG_EIP_INDEX 85 /* 10 * 8 + 4 + 1 */
#define REG_IP_INDEX 86 /* 10 * 8 + 5 + 1 */
#define REG_IDTR_INDEX 87 /* 10 * 8 + 6 + 1 */
#define REG_MXCSG_INDEX 88 /* 10 * 8 + 7 + 1 */
#define REG_TR_INDEX 89 /* 10 * 8 + 8 + 1 */
#define REG_CSMSR_INDEX 90 /* 10 * 8 + 9 + 1 */
#define REG_ESPMSR_INDEX 91 /* 10 * 8 + 10 + 1 */
#define REG_EIPMSR_INDEX 92 /* 10 * 8 + 11 + 1 */
void ia32_handle_register( x86_reg_t *reg, size_t id );
size_t ia32_true_register_id( size_t id );
#endif

View file

@ -0,0 +1,13 @@
#include "libdis.h"
#include "ia32_settings.h"
#include "ia32_reg.h"
#include "ia32_insn.h"
ia32_settings_t ia32_settings = {
1, 0xF4,
MAX_INSTRUCTION_SIZE,
4, 4, 8, 4, 8,
REG_ESP_INDEX, REG_EBP_INDEX, REG_EIP_INDEX, REG_FLAGS_INDEX,
REG_DWORD_OFFSET, REG_SEG_OFFSET, REG_FPU_OFFSET,
opt_none
};

View file

@ -0,0 +1,27 @@
#ifndef IA32_SETTINGS_H
#define IA32_SETTINGS_H
#include "libdis.h"
typedef struct {
/* options */
unsigned char endian, /* 0 = big, 1 = little */
wc_byte, /* wildcard byte */
max_insn, /* max insn size */
sz_addr, /* default address size */
sz_oper, /* default operand size */
sz_byte, /* # bits in byte */
sz_word, /* # bytes in machine word */
sz_dword; /* # bytes in machine dword */
unsigned int id_sp_reg, /* id of stack pointer */
id_fp_reg, /* id of frame pointer */
id_ip_reg, /* id of instruction pointer */
id_flag_reg, /* id of flags register */
offset_gen_regs, /* start of general regs */
offset_seg_regs, /* start of segment regs */
offset_fpu_regs; /* start of floating point regs */
/* user-controlled settings */
enum x86_options options;
} ia32_settings_t;
#endif

View file

@ -0,0 +1,832 @@
#ifndef LIBDISASM_H
#define LIBDISASM_H
#include <stdint.h>
/* 'NEW" types
* __________________________________________________________________________*/
#ifndef LIBDISASM_QWORD_H /* do not interfere with qword.h */
#define LIBDISASM_QWORD_H
#ifdef _MSC_VER
typedef __int64 qword_t;
#else
typedef int64_t qword_t;
#endif
#endif
#include <sys/types.h>
#ifdef __cplusplus
extern "C" {
#endif
/* 'NEW" x86 API
* __________________________________________________________________________*/
/* ========================================= Error Reporting */
/* REPORT CODES
* These are passed to a reporter function passed at initialization.
* Each code determines the type of the argument passed to the reporter;
* this allows the report to recover from errors, or just log them.
*/
enum x86_report_codes {
report_disasm_bounds, /* RVA OUT OF BOUNDS : The disassembler could
not disassemble the supplied RVA as it is
out of the range of the buffer. The
application should store the address and
attempt to determine what section of the
binary it is in, then disassemble the
address from the bytes in that section.
data: uint32_t rva */
report_insn_bounds, /* INSTRUCTION OUT OF BOUNDS: The disassembler
could not disassemble the instruction as
the instruction would require bytes beyond
the end of the current buffer. This usually
indicated garbage bytes at the end of a
buffer, or an incorrectly-sized buffer.
data: uint32_t rva */
report_invalid_insn, /* INVALID INSTRUCTION: The disassembler could
not disassemble the instruction as it has an
invalid combination of opcodes and operands.
This will stop automated disassembly; the
application can restart the disassembly
after the invalid instruction.
data: uint32_t rva */
report_unknown
};
/* 'arg' is optional arbitrary data provided by the code passing the
* callback -- for example, it could be 'this' or 'self' in OOP code.
* 'code' is provided by libdisasm, it is one of the above
* 'data' is provided by libdisasm and is context-specific, per the enums */
typedef void (*DISASM_REPORTER)( enum x86_report_codes code,
void *data, void *arg );
/* x86_report_error : Call the register reporter to report an error */
void x86_report_error( enum x86_report_codes code, void *data );
/* ========================================= Libdisasm Management Routines */
enum x86_options { /* these can be ORed together */
opt_none= 0,
opt_ignore_nulls=1, /* ignore sequences of > 4 NULL bytes */
opt_16_bit=2, /* 16-bit/DOS disassembly */
opt_att_mnemonics=4, /* use AT&T syntax names for alternate opcode mnemonics */
};
/* management routines */
/* 'arg' is caller-specific data which is passed as the first argument
* to the reporter callback routine */
int x86_init( enum x86_options options, DISASM_REPORTER reporter, void *arg);
void x86_set_reporter( DISASM_REPORTER reporter, void *arg);
void x86_set_options( enum x86_options options );
enum x86_options x86_get_options( void );
int x86_cleanup(void);
/* ========================================= Instruction Representation */
/* these defines are only intended for use in the array decl's */
#define MAX_REGNAME 8
#define MAX_PREFIX_STR 32
#define MAX_MNEM_STR 16
#define MAX_INSN_SIZE 20 /* same as in i386.h */
#define MAX_OP_STRING 32 /* max possible operand size in string form */
#define MAX_OP_RAW_STRING 64 /* max possible operand size in raw form */
#define MAX_OP_XML_STRING 256 /* max possible operand size in xml form */
#define MAX_NUM_OPERANDS 8 /* max # implicit and explicit operands */
/* in these, the '2 *' is arbitrary: the max # of operands should require
* more space than the rest of the insn */
#define MAX_INSN_STRING 512 /* 2 * 8 * MAX_OP_STRING */
#define MAX_INSN_RAW_STRING 1024 /* 2 * 8 * MAX_OP_RAW_STRING */
#define MAX_INSN_XML_STRING 4096 /* 2 * 8 * MAX_OP_XML_STRING */
enum x86_reg_type { /* NOTE: these may be ORed together */
reg_gen = 0x00001, /* general purpose */
reg_in = 0x00002, /* incoming args, ala RISC */
reg_out = 0x00004, /* args to calls, ala RISC */
reg_local = 0x00008, /* local vars, ala RISC */
reg_fpu = 0x00010, /* FPU data register */
reg_seg = 0x00020, /* segment register */
reg_simd = 0x00040, /* SIMD/MMX reg */
reg_sys = 0x00080, /* restricted/system register */
reg_sp = 0x00100, /* stack pointer */
reg_fp = 0x00200, /* frame pointer */
reg_pc = 0x00400, /* program counter */
reg_retaddr = 0x00800, /* return addr for func */
reg_cond = 0x01000, /* condition code / flags */
reg_zero = 0x02000, /* zero register, ala RISC */
reg_ret = 0x04000, /* return value */
reg_src = 0x10000, /* array/rep source */
reg_dest = 0x20000, /* array/rep destination */
reg_count = 0x40000 /* array/rep/loop counter */
};
/* x86_reg_t : an X86 CPU register */
typedef struct {
char name[MAX_REGNAME];
enum x86_reg_type type; /* what register is used for */
unsigned int size; /* size of register in bytes */
unsigned int id; /* register ID #, for quick compares */
unsigned int alias; /* ID of reg this is an alias for */
unsigned int shift; /* amount to shift aliased reg by */
} x86_reg_t;
/* x86_ea_t : an X86 effective address (address expression) */
typedef struct {
unsigned int scale; /* scale factor */
x86_reg_t index, base; /* index, base registers */
int32_t disp; /* displacement */
char disp_sign; /* is negative? 1/0 */
char disp_size; /* 0, 1, 2, 4 */
} x86_ea_t;
/* x86_absolute_t : an X86 segment:offset address (descriptor) */
typedef struct {
unsigned short segment; /* loaded directly into CS */
union {
unsigned short off16; /* loaded directly into IP */
uint32_t off32; /* loaded directly into EIP */
} offset;
} x86_absolute_t;
enum x86_op_type { /* mutually exclusive */
op_unused = 0, /* empty/unused operand: should never occur */
op_register = 1, /* CPU register */
op_immediate = 2, /* Immediate Value */
op_relative_near = 3, /* Relative offset from IP */
op_relative_far = 4, /* Relative offset from IP */
op_absolute = 5, /* Absolute address (ptr16:32) */
op_expression = 6, /* Address expression (scale/index/base/disp) */
op_offset = 7, /* Offset from start of segment (m32) */
op_unknown
};
#define x86_optype_is_address( optype ) \
( optype == op_absolute || optype == op_offset )
#define x86_optype_is_relative( optype ) \
( optype == op_relative_near || optype == op_relative_far )
#define x86_optype_is_memory( optype ) \
( optype > op_immediate && optype < op_unknown )
enum x86_op_datatype { /* these use Intel's lame terminology */
op_byte = 1, /* 1 byte integer */
op_word = 2, /* 2 byte integer */
op_dword = 3, /* 4 byte integer */
op_qword = 4, /* 8 byte integer */
op_dqword = 5, /* 16 byte integer */
op_sreal = 6, /* 4 byte real (single real) */
op_dreal = 7, /* 8 byte real (double real) */
op_extreal = 8, /* 10 byte real (extended real) */
op_bcd = 9, /* 10 byte binary-coded decimal */
op_ssimd = 10, /* 16 byte : 4 packed single FP (SIMD, MMX) */
op_dsimd = 11, /* 16 byte : 2 packed double FP (SIMD, MMX) */
op_sssimd = 12, /* 4 byte : scalar single FP (SIMD, MMX) */
op_sdsimd = 13, /* 8 byte : scalar double FP (SIMD, MMX) */
op_descr32 = 14, /* 6 byte Intel descriptor 2:4 */
op_descr16 = 15, /* 4 byte Intel descriptor 2:2 */
op_pdescr32 = 16, /* 6 byte Intel pseudo-descriptor 32:16 */
op_pdescr16 = 17, /* 6 byte Intel pseudo-descriptor 8:24:16 */
op_bounds16 = 18, /* signed 16:16 lower:upper bounds */
op_bounds32 = 19, /* signed 32:32 lower:upper bounds */
op_fpuenv16 = 20, /* 14 byte FPU control/environment data */
op_fpuenv32 = 21, /* 28 byte FPU control/environment data */
op_fpustate16 = 22, /* 94 byte FPU state (env & reg stack) */
op_fpustate32 = 23, /* 108 byte FPU state (env & reg stack) */
op_fpregset = 24, /* 512 bytes: register set */
op_fpreg = 25, /* FPU register */
op_none = 0xFF, /* operand without a datatype (INVLPG) */
};
enum x86_op_access { /* ORed together */
op_read = 1,
op_write = 2,
op_execute = 4
};
enum x86_op_flags { /* ORed together, but segs are mutually exclusive */
op_signed = 1, /* signed integer */
op_string = 2, /* possible string or array */
op_constant = 4, /* symbolic constant */
op_pointer = 8, /* operand points to a memory address */
op_sysref = 0x010, /* operand is a syscall number */
op_implied = 0x020, /* operand is implicit in the insn */
op_hardcode = 0x40, /* operand is hardcoded in insn definition */
/* NOTE: an 'implied' operand is one which can be considered a side
* effect of the insn, e.g. %esp being modified by PUSH or POP. A
* 'hard-coded' operand is one which is specified in the instruction
* definition, e.g. %es:%edi in MOVSB or 1 in ROL Eb, 1. The difference
* is that hard-coded operands are printed by disassemblers and are
* required to re-assemble, while implicit operands are invisible. */
op_es_seg = 0x100, /* ES segment override */
op_cs_seg = 0x200, /* CS segment override */
op_ss_seg = 0x300, /* SS segment override */
op_ds_seg = 0x400, /* DS segment override */
op_fs_seg = 0x500, /* FS segment override */
op_gs_seg = 0x600 /* GS segment override */
};
/* x86_op_t : an X86 instruction operand */
typedef struct {
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
enum x86_op_flags flags; /* misc flags */
union {
/* sizeof will have to work on these union members! */
/* immediate values */
char sbyte;
short sword;
int32_t sdword;
qword_t sqword;
unsigned char byte;
unsigned short word;
uint32_t dword;
qword_t qword;
float sreal;
double dreal;
/* misc large/non-native types */
unsigned char extreal[10];
unsigned char bcd[10];
qword_t dqword[2];
unsigned char simd[16];
unsigned char fpuenv[28];
/* offset from segment */
uint32_t offset;
/* ID of CPU register */
x86_reg_t reg;
/* offsets from current insn */
char relative_near;
int32_t relative_far;
/* segment:offset */
x86_absolute_t absolute;
/* effective address [expression] */
x86_ea_t expression;
} data;
/* this is needed to make formatting operands more sane */
void * insn; /* pointer to x86_insn_t owning operand */
} x86_op_t;
/* Linked list of x86_op_t; provided for manual traversal of the operand
* list in an insn. Users wishing to add operands to this list, e.g. to add
* implicit operands, should use x86_operand_new in x86_operand_list.h */
typedef struct x86_operand_list {
x86_op_t op;
struct x86_operand_list *next;
} x86_oplist_t;
enum x86_insn_group {
insn_none = 0, /* invalid instruction */
insn_controlflow = 1,
insn_arithmetic = 2,
insn_logic = 3,
insn_stack = 4,
insn_comparison = 5,
insn_move = 6,
insn_string = 7,
insn_bit_manip = 8,
insn_flag_manip = 9,
insn_fpu = 10,
insn_interrupt = 13,
insn_system = 14,
insn_other = 15
};
enum x86_insn_type {
insn_invalid = 0, /* invalid instruction */
/* insn_controlflow */
insn_jmp = 0x1001,
insn_jcc = 0x1002,
insn_call = 0x1003,
insn_callcc = 0x1004,
insn_return = 0x1005,
/* insn_arithmetic */
insn_add = 0x2001,
insn_sub = 0x2002,
insn_mul = 0x2003,
insn_div = 0x2004,
insn_inc = 0x2005,
insn_dec = 0x2006,
insn_shl = 0x2007,
insn_shr = 0x2008,
insn_rol = 0x2009,
insn_ror = 0x200A,
/* insn_logic */
insn_and = 0x3001,
insn_or = 0x3002,
insn_xor = 0x3003,
insn_not = 0x3004,
insn_neg = 0x3005,
/* insn_stack */
insn_push = 0x4001,
insn_pop = 0x4002,
insn_pushregs = 0x4003,
insn_popregs = 0x4004,
insn_pushflags = 0x4005,
insn_popflags = 0x4006,
insn_enter = 0x4007,
insn_leave = 0x4008,
/* insn_comparison */
insn_test = 0x5001,
insn_cmp = 0x5002,
/* insn_move */
insn_mov = 0x6001, /* move */
insn_movcc = 0x6002, /* conditional move */
insn_xchg = 0x6003, /* exchange */
insn_xchgcc = 0x6004, /* conditional exchange */
/* insn_string */
insn_strcmp = 0x7001,
insn_strload = 0x7002,
insn_strmov = 0x7003,
insn_strstore = 0x7004,
insn_translate = 0x7005, /* xlat */
/* insn_bit_manip */
insn_bittest = 0x8001,
insn_bitset = 0x8002,
insn_bitclear = 0x8003,
/* insn_flag_manip */
insn_clear_carry = 0x9001,
insn_clear_zero = 0x9002,
insn_clear_oflow = 0x9003,
insn_clear_dir = 0x9004,
insn_clear_sign = 0x9005,
insn_clear_parity = 0x9006,
insn_set_carry = 0x9007,
insn_set_zero = 0x9008,
insn_set_oflow = 0x9009,
insn_set_dir = 0x900A,
insn_set_sign = 0x900B,
insn_set_parity = 0x900C,
insn_tog_carry = 0x9010,
insn_tog_zero = 0x9020,
insn_tog_oflow = 0x9030,
insn_tog_dir = 0x9040,
insn_tog_sign = 0x9050,
insn_tog_parity = 0x9060,
/* insn_fpu */
insn_fmov = 0xA001,
insn_fmovcc = 0xA002,
insn_fneg = 0xA003,
insn_fabs = 0xA004,
insn_fadd = 0xA005,
insn_fsub = 0xA006,
insn_fmul = 0xA007,
insn_fdiv = 0xA008,
insn_fsqrt = 0xA009,
insn_fcmp = 0xA00A,
insn_fcos = 0xA00C,
insn_fldpi = 0xA00D,
insn_fldz = 0xA00E,
insn_ftan = 0xA00F,
insn_fsine = 0xA010,
insn_fsys = 0xA020,
/* insn_interrupt */
insn_int = 0xD001,
insn_intcc = 0xD002, /* not present in x86 ISA */
insn_iret = 0xD003,
insn_bound = 0xD004,
insn_debug = 0xD005,
insn_trace = 0xD006,
insn_invalid_op = 0xD007,
insn_oflow = 0xD008,
/* insn_system */
insn_halt = 0xE001,
insn_in = 0xE002, /* input from port/bus */
insn_out = 0xE003, /* output to port/bus */
insn_cpuid = 0xE004,
/* insn_other */
insn_nop = 0xF001,
insn_bcdconv = 0xF002, /* convert to or from BCD */
insn_szconv = 0xF003 /* change size of operand */
};
/* These flags specify special characteristics of the instruction, such as
* whether the inatruction is privileged or whether it serializes the
* pipeline.
* NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */
enum x86_insn_note {
insn_note_ring0 = 1, /* Only available in ring 0 */
insn_note_smm = 2, /* "" in System Management Mode */
insn_note_serial = 4, /* Serializing instruction */
insn_note_nonswap = 8, /* Does not swap arguments in att-style formatting */
insn_note_nosuffix = 16, /* Does not have size suffix in att-style formatting */
};
/* This specifies what effects the instruction has on the %eflags register */
enum x86_flag_status {
insn_carry_set = 0x1, /* CF */
insn_zero_set = 0x2, /* ZF */
insn_oflow_set = 0x4, /* OF */
insn_dir_set = 0x8, /* DF */
insn_sign_set = 0x10, /* SF */
insn_parity_set = 0x20, /* PF */
insn_carry_or_zero_set = 0x40,
insn_zero_set_or_sign_ne_oflow = 0x80,
insn_carry_clear = 0x100,
insn_zero_clear = 0x200,
insn_oflow_clear = 0x400,
insn_dir_clear = 0x800,
insn_sign_clear = 0x1000,
insn_parity_clear = 0x2000,
insn_sign_eq_oflow = 0x4000,
insn_sign_ne_oflow = 0x8000
};
/* The CPU model in which the insturction first appeared; this can be used
* to mask out instructions appearing in earlier or later models or to
* check the portability of a binary.
* NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */
enum x86_insn_cpu {
cpu_8086 = 1, /* Intel */
cpu_80286 = 2,
cpu_80386 = 3,
cpu_80387 = 4,
cpu_80486 = 5,
cpu_pentium = 6,
cpu_pentiumpro = 7,
cpu_pentium2 = 8,
cpu_pentium3 = 9,
cpu_pentium4 = 10,
cpu_k6 = 16, /* AMD */
cpu_k7 = 32,
cpu_athlon = 48
};
/* CPU ISA subsets: These are derived from the Instruction Groups in
* Intel Vol 1 Chapter 5; they represent subsets of the IA32 ISA but
* do not reflect the 'type' of the instruction in the same way that
* x86_insn_group does. In short, these are AMD/Intel's somewhat useless
* designations.
* NOTE : These may not be accurate for all instructions; updates to the
* opcode tables have not been completed. */
enum x86_insn_isa {
isa_gp = 1, /* general purpose */
isa_fp = 2, /* floating point */
isa_fpumgt = 3, /* FPU/SIMD management */
isa_mmx = 4, /* Intel MMX */
isa_sse1 = 5, /* Intel SSE SIMD */
isa_sse2 = 6, /* Intel SSE2 SIMD */
isa_sse3 = 7, /* Intel SSE3 SIMD */
isa_3dnow = 8, /* AMD 3DNow! SIMD */
isa_sys = 9 /* system instructions */
};
enum x86_insn_prefix {
insn_no_prefix = 0,
insn_rep_zero = 1, /* REPZ and REPE */
insn_rep_notzero = 2, /* REPNZ and REPNZ */
insn_lock = 4 /* LOCK: */
};
/* TODO: maybe provide insn_new/free(), and have disasm return new insn_t */
/* x86_insn_t : an X86 instruction */
typedef struct {
/* information about the instruction */
uint32_t addr; /* load address */
uint32_t offset; /* offset into file/buffer */
enum x86_insn_group group; /* meta-type, e.g. INS_EXEC */
enum x86_insn_type type; /* type, e.g. INS_BRANCH */
enum x86_insn_note note; /* note, e.g. RING0 */
unsigned char bytes[MAX_INSN_SIZE];
unsigned char size; /* size of insn in bytes */
/* 16/32-bit mode settings */
unsigned char addr_size; /* default address size : 2 or 4 */
unsigned char op_size; /* default operand size : 2 or 4 */
/* CPU/instruction set */
enum x86_insn_cpu cpu;
enum x86_insn_isa isa;
/* flags */
enum x86_flag_status flags_set; /* flags set or tested by insn */
enum x86_flag_status flags_tested;
/* stack */
unsigned char stack_mod; /* 0 or 1 : is the stack modified? */
int32_t stack_mod_val; /* val stack is modified by if known */
/* the instruction proper */
enum x86_insn_prefix prefix; /* prefixes ORed together */
char prefix_string[MAX_PREFIX_STR]; /* prefixes [might be truncated] */
char mnemonic[MAX_MNEM_STR];
x86_oplist_t *operands; /* list of explicit/implicit operands */
size_t operand_count; /* total number of operands */
size_t explicit_count; /* number of explicit operands */
/* convenience fields for user */
void *block; /* code block containing this insn */
void *function; /* function containing this insn */
int tag; /* tag the insn as seen/processed */
} x86_insn_t;
/* returns 0 if an instruction is invalid, 1 if valid */
int x86_insn_is_valid( x86_insn_t *insn );
/* DISASSEMBLY ROUTINES
* Canonical order of arguments is
* (buf, buf_len, buf_rva, offset, len, insn, func, arg, resolve_func)
* ...but of course all of these are not used at the same time.
*/
/* Function prototype for caller-supplied callback routine
* These callbacks are intended to process 'insn' further, e.g. by
* adding it to a linked list, database, etc */
typedef void (*DISASM_CALLBACK)( x86_insn_t *insn, void * arg );
/* Function prototype for caller-supplied address resolver.
* This routine is used to determine the rva to disassemble next, given
* the 'dest' operand of a jump/call. This allows the caller to resolve
* jump/call targets stored in a register or on the stack, and also allows
* the caller to prevent endless loops by checking if an address has
* already been disassembled. If an address cannot be resolved from the
* operand, or if the address has already been disassembled, this routine
* should return -1; in all other cases the RVA to be disassembled next
* should be returned. */
typedef int32_t (*DISASM_RESOLVER)( x86_op_t *op, x86_insn_t * current_insn,
void *arg );
/* x86_disasm: Disassemble a single instruction from a buffer of bytes.
* Returns size of instruction in bytes.
* Caller is responsible for calling x86_oplist_free() on
* a reused "insn" to avoid leaking memory when calling this
* function repeatedly.
* buf : Buffer of bytes to disassemble
* buf_len : Length of the buffer
* buf_rva : Load address of the start of the buffer
* offset : Offset in buffer to disassemble
* insn : Structure to fill with disassembled instruction
*/
unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
x86_insn_t * insn );
/* x86_disasm_range: Sequential disassembly of a range of bytes in a buffer,
* invoking a callback function each time an instruction
* is successfully disassembled. The 'range' refers to the
* bytes between 'offset' and 'offset + len' in the buffer;
* 'len' is assumed to be less than the length of the buffer.
* Returns number of instructions processed.
* buf : Buffer of bytes to disassemble (e.g. .text section)
* buf_rva : Load address of buffer (e.g. ELF Virtual Address)
* offset : Offset in buffer to start disassembly at
* len : Number of bytes to disassemble
* func : Callback function to invoke (may be NULL)
* arg : Arbitrary data to pass to callback (may be NULL)
*/
unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg );
/* x86_disasm_forward: Flow-of-execution disassembly of the bytes in a buffer,
* invoking a callback function each time an instruction
* is successfully disassembled.
* buf : Buffer to disassemble (e.g. .text section)
* buf_len : Number of bytes in buffer
* buf_rva : Load address of buffer (e.g. ELF Virtual Address)
* offset : Offset in buffer to start disassembly at (e.g. entry point)
* func : Callback function to invoke (may be NULL)
* arg : Arbitrary data to pass to callback (may be NULL)
* resolver: Caller-supplied address resolver. If no resolver is
* supplied, a default internal one is used -- however the
* internal resolver does NOT catch loops and could end up
* disassembling forever..
* r_arg : Arbitrary data to pass to resolver (may be NULL)
*/
unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg );
/* Instruction operands: these are stored as a list of explicit and
* implicit operands. It is recommended that the 'foreach' routines
* be used to when examining operands for purposes of data flow analysis */
/* Operand FOREACH callback: 'arg' is an abritrary parameter passed to the
* foreach routine, 'insn' is the x86_insn_t whose operands are being
* iterated over, and 'op' is the current x86_op_t */
typedef void (*x86_operand_fn)(x86_op_t *op, x86_insn_t *insn, void *arg);
/* FOREACH types: these are used to limit the foreach results to
* operands which match a certain "type" (implicit or explicit)
* or which are accessed in certain ways (e.g. read or write). Note
* that this operates on the operand list of single instruction, so
* specifying the 'real' operand type (register, memory, etc) is not
* useful. Note also that by definition Execute Access implies Read
* Access and implies Not Write Access.
* The "type" (implicit or explicit) and the access method can
* be ORed together, e.g. op_wo | op_explicit */
enum x86_op_foreach_type {
op_any = 0, /* ALL operands (explicit, implicit, rwx) */
op_dest = 1, /* operands with Write access */
op_src = 2, /* operands with Read access */
op_ro = 3, /* operands with Read but not Write access */
op_wo = 4, /* operands with Write but not Read access */
op_xo = 5, /* operands with Execute access */
op_rw = 6, /* operands with Read AND Write access */
op_implicit = 0x10, /* operands that are implied by the opcode */
op_explicit = 0x20 /* operands that are not side-effects */
};
/* free the operand list associated with an instruction -- useful for
* preventing memory leaks when free()ing an x86_insn_t */
void x86_oplist_free( x86_insn_t *insn );
/* Operand foreach: invokes 'func' with 'insn' and 'arg' as arguments. The
* 'type' parameter is used to select only operands matching specific
* criteria. */
int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg,
enum x86_op_foreach_type type);
/* convenience routine: returns count of operands matching 'type' */
size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type );
/* accessor functions for the operands */
x86_op_t * x86_operand_1st( x86_insn_t *insn );
x86_op_t * x86_operand_2nd( x86_insn_t *insn );
x86_op_t * x86_operand_3rd( x86_insn_t *insn );
/* these allow libdisasm 2.0 accessor functions to still be used */
#define x86_get_dest_operand( insn ) x86_operand_1st( insn )
#define x86_get_src_operand( insn ) x86_operand_2nd( insn )
#define x86_get_imm_operand( insn ) x86_operand_3rd( insn )
/* get size of operand data in bytes */
unsigned int x86_operand_size( x86_op_t *op );
/* Operand Convenience Routines: the following three routines are common
* operations on operands, intended to ease the burden of the programmer. */
/* Get Address: return the value of an offset operand, or the offset of
* a segment:offset absolute address */
uint32_t x86_get_address( x86_insn_t *insn );
/* Get Relative Offset: return as a sign-extended int32_t the near or far
* relative offset operand, or 0 if there is none. There can be only one
* relaive offset operand in an instruction. */
int32_t x86_get_rel_offset( x86_insn_t *insn );
/* Get Branch Target: return the x86_op_t containing the target of
* a jump or call operand, or NULL if there is no branch target.
* Internally, a 'branch target' is defined as any operand with
* Execute Access set. There can be only one branch target per instruction. */
x86_op_t * x86_get_branch_target( x86_insn_t *insn );
/* Get Immediate: return the x86_op_t containing the immediate operand
* for this instruction, or NULL if there is no immediate operand. There
* can be only one immediate operand per instruction */
x86_op_t * x86_get_imm( x86_insn_t *insn );
/* Get Raw Immediate Data: returns a pointer to the immediate data encoded
* in the instruction. This is useful for large data types [>32 bits] currently
* not supported by libdisasm, or for determining if the disassembler
* screwed up the conversion of the immediate data. Note that 'imm' in this
* context refers to immediate data encoded at the end of an instruction as
* detailed in the Intel Manual Vol II Chapter 2; it does not refer to the
* 'op_imm' operand (the third operand in instructions like 'mul' */
unsigned char * x86_get_raw_imm( x86_insn_t *insn );
/* More accessor fuctions, this time for user-defined info... */
/* set the address (usually RVA) of the insn */
void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr );
/* set the offset (usually offset into file) of the insn */
void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset );
/* set a pointer to the function owning the instruction. The
* type of 'func' is user-defined; libdisasm does not use the func field. */
void x86_set_insn_function( x86_insn_t *insn, void * func );
/* set a pointer to the block of code owning the instruction. The
* type of 'block' is user-defined; libdisasm does not use the block field. */
void x86_set_insn_block( x86_insn_t *insn, void * block );
/* instruction tagging: these routines allow the programmer to mark
* instructions as "seen" in a DFS, for example. libdisasm does not use
* the tag field.*/
/* set insn->tag to 1 */
void x86_tag_insn( x86_insn_t *insn );
/* set insn->tag to 0 */
void x86_untag_insn( x86_insn_t *insn );
/* return insn->tag */
int x86_insn_is_tagged( x86_insn_t *insn );
/* Disassembly formats:
* AT&T is standard AS/GAS-style: "mnemonic\tsrc, dest, imm"
* Intel is standard MASM/NASM/TASM: "mnemonic\tdest,src, imm"
* Native is tab-delimited: "RVA\tbytes\tmnemonic\tdest\tsrc\timm"
* XML is your typical <insn> ... </insn>
* Raw is addr|offset|size|bytes|prefix... see libdisasm_formats.7
*/
enum x86_asm_format {
unknown_syntax = 0, /* never use! */
native_syntax, /* header: 35 bytes */
intel_syntax, /* header: 23 bytes */
att_syntax, /* header: 23 bytes */
xml_syntax, /* header: 679 bytes */
raw_syntax /* header: 172 bytes */
};
/* format (sprintf) an operand into 'buf' using specified syntax */
int x86_format_operand(x86_op_t *op, char *buf, int len,
enum x86_asm_format format);
/* format (sprintf) an instruction mnemonic into 'buf' using specified syntax */
int x86_format_mnemonic(x86_insn_t *insn, char *buf, int len,
enum x86_asm_format format);
/* format (sprintf) an instruction into 'buf' using specified syntax;
* this includes formatting all operands */
int x86_format_insn(x86_insn_t *insn, char *buf, int len, enum x86_asm_format);
/* fill 'buf' with a description of the format's syntax */
int x86_format_header( char *buf, int len, enum x86_asm_format format);
/* Endianness of an x86 CPU : 0 is big, 1 is little; always returns 1 */
unsigned int x86_endian(void);
/* Default address and operand size in bytes */
unsigned int x86_addr_size(void);
unsigned int x86_op_size(void);
/* Size of a machine word in bytes */
unsigned int x86_word_size(void);
/* maximum size of a code instruction */
#define x86_max_inst_size(x) x86_max_insn_size(x)
unsigned int x86_max_insn_size(void);
/* register IDs of Stack, Frame, Instruction pointer and Flags register */
unsigned int x86_sp_reg(void);
unsigned int x86_fp_reg(void);
unsigned int x86_ip_reg(void);
unsigned int x86_flag_reg(void);
/* fill 'reg' struct with details of register 'id' */
void x86_reg_from_id( unsigned int id, x86_reg_t * reg );
/* convenience macro demonstrating how to get an aliased register; proto is
* void x86_get_aliased_reg( x86_reg_t *alias_reg, x86_reg_t *output_reg )
* where 'alias_reg' is a reg operand and 'output_reg' is filled with the
* register that the operand is an alias for */
#define x86_get_aliased_reg( alias_reg, output_reg ) \
x86_reg_from_id( alias_reg->alias, output_reg )
/* ================================== Invariant Instruction Representation */
/* Invariant instructions are used for generating binary signatures;
* the instruction is modified so that all variant bytes in an instruction
* are replaced with a wildcard byte.
*
* A 'variant byte' is one that is expected to be modified by either the
* static or the dynamic linker: for example, an address encoded in an
* instruction.
*
* By comparing the invariant representation of one instruction [or of a
* sequence of instructions] with the invariant representation of another,
* one determine whether the two invariant representations are from the same
* relocatable object [.o] file. Thus one can use binary signatures [which
* are just sequences of invariant instruction representations] to look for
* library routines which have been statically-linked into a binary.
*
* The invariant routines are faster and smaller than the disassembly
* routines; they can be used to determine the size of an instruction
* without all of the overhead of a full instruction disassembly.
*/
/* This byte is used to replace variant bytes */
#define X86_WILDCARD_BYTE 0xF4
typedef struct {
enum x86_op_type type; /* operand type */
enum x86_op_datatype datatype; /* operand size */
enum x86_op_access access; /* operand access [RWX] */
enum x86_op_flags flags; /* misc flags */
} x86_invariant_op_t;
typedef struct {
unsigned char bytes[64]; /* invariant representation */
unsigned int size; /* number of bytes in insn */
enum x86_insn_group group; /* meta-type, e.g. INS_EXEC */
enum x86_insn_type type; /* type, e.g. INS_BRANCH */
x86_invariant_op_t operands[3]; /* operands: dest, src, imm */
} x86_invariant_t;
/* return a version of the instruction with the variant bytes masked out */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv );
/* return the size in bytes of the intruction pointed to by 'buf';
* this used x86_invariant_disasm since it faster than x86_disasm */
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len );
#ifdef __cplusplus
}
#endif
#endif

View file

@ -0,0 +1,14 @@
#ifndef LIBDISASM_QWORD_H
#define LIBDISASM_QWORD_H
#include <stdint.h>
/* platform independent data types */
#ifdef _MSC_VER
typedef __int64 qword_t;
#else
typedef int64_t qword_t;
#endif
#endif

View file

@ -0,0 +1,70 @@
# change these values if you need to
SWIG = swig # apt-get install swig !
GCC = gcc
CC_FLAGS = -c -fPIC
LD_FLAGS = -shared -L../.. -ldisasm
BASE_NAME = x86disasm
export INTERFACE_FILE BASE_NAME SWIG GCC CC_FLAGS LD_FLAGS
#====================================================
# TARGETS
all: swig
dummy: swig swig-python swig-ruby swig-perl swig-tcl install uninstall clean
swig: swig-python swig-perl
# swig-rub swig-tcl
swig-python:
cd python && make -f Makefile-swig
swig-ruby:
cd ruby && make -f Makefile-swig
swig-perl:
cd perl && make -f Makefile-swig
swig-tcl:
cd tcl && make -f Makefile-swig
# ==================================================================
install: install-python install-perl
# install-ruby install-tcl
install-python:
cd python && sudo make -f Makefile-swig install
install-ruby:
cd ruby && sudo make -f Makefile-swig install
install-perl:
cd perl && sudo make -f Makefile-swig install
install-tcl:
cd tcl && sudo make -f Makefile-swig install
# ==================================================================
uninstall: uninstall-python
#uninstall-ruby uninstall-perl uninstall-tcl
uninstall-python:
cd python && sudo make -f Makefile-swig uninstall
uninstall-ruby:
cd ruby && sudo make -f Makefile-swig uninstall
uninstall-perl:
cd perl && sudo make -f Makefile-swig uninstall
uninstall-tcl:
cd tcl && sudo make -f Makefile-swig uninstall
# ==================================================================
clean:
cd python && make -f Makefile-swig clean
cd ruby && make -f Makefile-swig clean
cd perl && make -f Makefile-swig clean
cd tcl && make -f Makefile-swig clean

View file

@ -0,0 +1,128 @@
Libdisasm SWIG README
The SWIG utility (www.swig.org) can be used to generate
Building SWIG Modules
---------------------
make
make install
Make and Install both build Python, Perl, Ruby, and Tcl modules. If you
do not have one of these languages installed, comment out the relevant
target in the main Makefile.
Install uses 'sudo' to put files in the correct locations; if you
do not have sudo installed, change the install targets.
The Module API
--------------
The OOP API
-----------
The Python Module
-----------------
To test that the module loads:
bash# python
>>> import x86disasm
>>> x86disasm.version_string()
'0.21-pre'
>>>^D
bash#
>>> import x86disasm
>>> import array
>>> disasm = x86disasm.X86_Disasm( )
>>> tgt = open( "/tmp/a.out", "rb" )
>>> tgt.seek( 0, 2 )
>>> size = tgt.tell()
>>> tgt.seek( 0, 0 )
>>> buf = array.array( 'B' )
>>> buf.fromfile( tgt, size )
>>> tgt.close()
>>> data = x86disasm.byteArray( size )
>>> for i in range( size ):
... data[i] = buf.pop(0)
...
>>> del buf
>>> del tgt
>>> insn = disasm.disasm( data, size - 1, 0, 0 )
>>> insn.format( x86disasm.att_syntax )
'jg\t0x00000047'
>>> insn.format( x86disasm.raw_syntax )
'0x00000000|0x00000000|2|7F 45 |||controlflow|jcc|jg|80386|General Purpose|||zero_clear sign_eq_oflow |0|0|relative|sbyte|00000047|'
>>> ops = insn.operand_list()
>>> node = ops.first()
>>> while node is not None:
... s = node.op.format(x86disasm.raw_syntax)
... print s
... node = ops.next()
...
relative|sbyte|00000047|
The Perl Module
---------------
To test that the module loads:
bash# perl
use x86disasm;
print x86disasm::version_string() . "\n";
^D
0.21-pre
bash#
The Ruby Module
---------------
To test that the module loads:
bash# irb
irb(main):001:0> require 'x86disasm'
=> true
irb(main):002:0> X86disasm.version_string()
=> "0.21-pre"
irb(main):003:0> x = X86disasm::X86_Disasm.new
=> #<X86disasm::X86_Disasm:0xb7d624a4>
irb(main):004:0> x.max_register_string()
=> 8
irb(main):003:0> ^D
bash#
The Tcl Module
---------------
To test that the module loads:
bash# tclsh
% load /usr/lib/tcl8.3/x86disasm.so X86disasm
% version_string
0.21-pre
% ^D
bash#
% x86_init 0 NULL NULL
OR
% x86disasm dis
_486b0708_p_x86disasm
% puts "[dis cget -last_error]"
0
The Interface Files
-------------------
libdisasm.i -- interface file without shadow classes
libdisasm_oop.i -- interface file with shadow classes

View file

@ -0,0 +1,508 @@
%module x86disasm
%{
#include "../../libdis.h"
#include "../../../config.h"
%}
%rename(version_string) x86_version_string;
%include "../../libdis.h"
#include "../../../config.h"
%inline %{
const char * x86_version_string( void ) {
return PACKAGE_VERSION;
}
%}
%rename(report_codes) x86_report_codes;
%rename(report_error) x86_report_error;
%rename(options) x86_options;
%rename(init) x86_init;
%rename(set_reporter) x86_set_reporter;
%rename(set_options) x86_set_options;
%rename(options) x86_get_options;
%rename(cleanup) x86_cleanup;
%rename(reg_type) x86_reg_type;
%rename(reg) x86_reg_t;
%rename(eaddr) x86_ea_t;
%rename(op_type) x86_op_type;
%rename(optype_is_address) x86_optype_is_address;
%rename(optype_is_relative) x86_optype_is_relative;
%rename(op_datatype) x86_op_datatype;
%rename(op_access) x86_op_access;
%rename(op_flags) x86_op_flags;
%rename(operand) x86_op_t;
%rename(insn_group) x86_insn_group;
%rename(insn_type) x86_insn_type;
%rename(insn_note) x86_insn_note ;
%rename(flag_status) x86_flag_status;
%rename(insn_cpu) x86_insn_cpu ;
%rename(insn_isa) x86_insn_isa ;
%rename(insn_prefix) x86_insn_prefix ;
%rename(insn) x86_insn_t;
%rename(insn_is_valid) x86_insn_is_valid;
%rename(i_disasm) x86_disasm;
%rename(i_disasm_range) x86_disasm_range;
%rename(i_disasm_forward) x86_disasm_forward;
%rename(insn_operand_count) x86_operand_count;
%rename(insn_operand_1st) x86_operand_1st;
%rename(insn_operand_2nd) x86_operand_2nd;
%rename(insn_operand_3rd) x86_operand_3rd;
%rename(insn_dest_operand) x86_get_dest_operand;
%rename(insn_src_operand) x86_get_src_operand;
%rename(insn_imm_operand) x86_get_imm_operand;
%rename(operand_size) x86_operand_size;
%rename(insn_rel_offset) x86_get_rel_offset;
%rename(insn_branch_target) x86_get_branch_target;
%rename(insn_imm) x86_get_imm;
%rename(insn_raw_imm) x86_get_raw_imm;
%rename(insn_set_addr) x86_set_insn_addr;
%rename(insn_set_offset) x86_set_insn_offset;
%rename(insn_set_function) x86_set_insn_function;
%rename(insn_set_block) x86_set_insn_block;
%rename(insn_tag) x86_tag_insn;
%rename(insn_untag) x86_untag_insn;
%rename(insn_is_tagged) x86_insn_is_tagged;
%rename(asm_format) x86_asm_format;
%rename(operand_format) x86_format_operand;
%rename(insn_format_mnemonic) x86_format_mnemonic;
%rename(insn_format) x86_format_insn;
%rename(header_format) x86_format_header;
%rename(endian) x86_endian;
%rename(size_default_address) x86_addr_size;
%rename(size_default_operand) x86_op_size;
%rename(size_machine_word) x86_word_size;
%rename(size_max_insn) x86_max_insn_size;
%rename(reg_sp) x86_sp_reg;
%rename(reg_fp) x86_fp_reg;
%rename(reg_ip) x86_ip_reg;
%rename(reg_from_id) x86_reg_from_id;
%rename(reg_from_alias) x86_get_aliased_reg;
%rename(invariant_op) x86_invariant_op_t;
%rename(invariant) x86_invariant_t;
%rename(disasm_invariant) x86_invariant_disasm;
%rename(disasm_size) x86_size_disasm;
%include "carrays.i"
%array_class( unsigned char, byteArray );
%apply (unsigned char *STRING, int LENGTH) {
(unsigned char *buf, size_t buf_len)
};
%newobject x86_op_copy;
%inline %{
x86_op_t * x86_op_copy( x86_op_t * src ) {
x86_op_t *op;
if (! src ) {
return NULL;
}
op = (x86_op_t *) calloc( sizeof(x86_op_t), 1 );
if ( op ) {
memcpy( op, src, sizeof(x86_op_t) );
}
return op;
}
typedef struct x86_op_list_node {
x86_op_t *op;
struct x86_op_list_node *next, *prev;
} x86_op_list_node;
typedef struct x86_op_list {
size_t count;
x86_op_list_node *head, *tail, *curr;
} x86_op_list;
x86_op_list * x86_op_list_new () {
x86_op_list *list = (x86_op_list *)
calloc( sizeof(x86_op_list), 1 );
list->count = 0;
return list;
}
void x86_op_list_free(x86_op_list *list) {
x86_op_list_node *node, *next;
node = list->head;
while ( node ) {
next = node->next;
/* free( node->insn ); */
free( node );
node = next;
}
free( list );
}
x86_op_list_node * x86_op_list_first(x86_op_list *list) {
return list->head;
}
x86_op_list_node * x86_op_list_last(x86_op_list *list) {
return list->tail;
}
x86_op_list_node * x86_op_list_next(x86_op_list *list) {
if (! list->curr ) {
list->curr = list->head;
return list->head;
}
list->curr = list->curr->next;
return list->curr;
}
x86_op_list_node * x86_op_list_prev(x86_op_list *list) {
if (! list->curr ) {
list->curr = list->tail;
return list->tail;
}
list->curr = list->curr->prev;
return list->curr;
}
%}
%newobject x86_op_list_append;
%inline %{
void x86_op_list_append( x86_op_list * list, x86_op_t *op ) {
x86_op_list_node *node = (x86_op_list_node *)
calloc( sizeof(x86_op_list_node) , 1 );
if (! node ) {
return;
}
list->count++;
if ( ! list->tail ) {
list->head = list->tail = node;
} else {
list->tail->next = node;
node->prev = list->tail;
list->tail = node;
}
node->op = x86_op_copy( op );
}
x86_oplist_t * x86_op_list_node_copy( x86_oplist_t * list ) {
x86_oplist_t *ptr;
ptr = (x86_oplist_t *) calloc( sizeof(x86_oplist_t), 1 );
if ( ptr ) {
memcpy( &ptr->op, &list->op, sizeof(x86_op_t) );
}
return ptr;
}
x86_insn_t * x86_insn_new() {
x86_insn_t *insn = (x86_insn_t *)
calloc( sizeof(x86_insn_t), 1 );
return insn;
}
void x86_insn_free( x86_insn_t *insn ) {
x86_oplist_free( insn );
free( insn );
}
%}
%newobject x86_insn_copy;
%inline %{
x86_insn_t * x86_insn_copy( x86_insn_t *src) {
x86_oplist_t *ptr, *list, *last = NULL;
x86_insn_t *insn = (x86_insn_t *)
calloc( sizeof(x86_insn_t), 1 );
if ( insn ) {
memcpy( insn, src, sizeof(x86_insn_t) );
insn->operands = NULL;
insn->block = NULL;
insn->function = NULL;
/* copy operand list */
for ( list = src->operands; list; list = list->next ) {
ptr = x86_op_list_node_copy( list );
if (! ptr ) {
continue;
}
if ( insn->operands ) {
last->next = ptr;
} else {
insn->operands = ptr;
}
last = ptr;
}
}
return insn;
}
x86_op_list * x86_insn_op_list( x86_insn_t *insn ) {
x86_oplist_t *list = insn->operands;
x86_op_list *op_list = x86_op_list_new();
for ( list = insn->operands; list; list = list->next ) {
x86_op_list_append( op_list, &list->op );
}
return op_list;
}
typedef struct x86_insn_list_node {
x86_insn_t *insn;
struct x86_insn_list_node *next, *prev;
} x86_insn_list_node;
typedef struct x86_insn_list {
size_t count;
x86_insn_list_node *head, *tail, *curr;
} x86_insn_list;
%}
%newobject x86_insn_list_new;
%inline %{
x86_insn_list * x86_insn_list_new () {
x86_insn_list *list = (x86_insn_list *)
calloc( sizeof(x86_insn_list), 1 );
list->count = 0;
return list;
}
void x86_insn_list_free( x86_insn_list * list ) {
x86_insn_list_node *node, *next;
if (! list ) {
return;
}
node = list->head;
while ( node ) {
next = node->next;
/* free( node->insn ); */
free( node );
node = next;
}
free( list );
}
x86_insn_list_node * x86_insn_list_first( x86_insn_list *list ) {
if (! list ) {
return NULL;
}
return list->head;
}
x86_insn_list_node * x86_insn_list_last( x86_insn_list *list ) {
if (! list ) {
return NULL;
}
return list->tail;
}
x86_insn_list_node * x86_insn_list_next( x86_insn_list *list ) {
if (! list ) {
return NULL;
}
if (! list->curr ) {
list->curr = list->head;
return list->head;
}
list->curr = list->curr->next;
return list->curr;
}
x86_insn_list_node * x86_insn_list_prev( x86_insn_list *list ) {
if (! list ) {
return NULL;
}
if (! list->curr ) {
list->curr = list->tail;
return list->tail;
}
list->curr = list->curr->prev;
return list->curr;
}
%}
%newobject x86_insn_list_append;
%inline %{
void x86_insn_list_append( x86_insn_list *list, x86_insn_t *insn ) {
x86_insn_list_node *node;
if (! list ) {
return;
}
node = (x86_insn_list_node *)
calloc( sizeof(x86_insn_list_node) , 1 );
if (! node ) {
return;
}
list->count++;
if ( ! list->tail ) {
list->head = list->tail = node;
} else {
list->tail->next = node;
node->prev = list->tail;
list->tail = node;
}
node->insn = x86_insn_copy( insn );
}
typedef struct {
enum x86_report_codes last_error;
void * last_error_data;
void * disasm_callback;
void * disasm_resolver;
} x86disasm;
void x86_default_reporter( enum x86_report_codes code,
void *data, void *arg ) {
x86disasm *dis = (x86disasm *) arg;
if ( dis ) {
dis->last_error = code;
dis->last_error_data = data;
}
}
void x86_default_callback( x86_insn_t *insn, void *arg ) {
x86_insn_list *list = (x86_insn_list *) arg;
if ( list ) {
x86_insn_list_append( list, insn );
}
}
/* TODO: resolver stack, maybe a callback */
long x86_default_resolver( x86_op_t *op, x86_insn_t *insn, void *arg ) {
x86disasm *dis = (x86disasm *) arg;
if ( dis ) {
//return dis->resolver( op, insn );
return 0;
}
return 0;
}
%}
%newobject x86disasm_new;
%inline %{
x86disasm * x86disasm_new ( enum x86_options options ) {
x86disasm * dis = (x86disasm *)
calloc( sizeof( x86disasm ), 1 );
x86_init( options, x86_default_reporter, dis );
return dis;
}
void x86disasm_free( x86disasm * dis ) {
x86_cleanup();
free( dis );
}
%}
%newobject x86_disasm;
%inline %{
x86_insn_t * disasm( unsigned char *buf, size_t buf_len,
unsigned long buf_rva, unsigned int offset ) {
x86_insn_t *insn = calloc( sizeof( x86_insn_t ), 1 );
x86_disasm( buf, buf_len, buf_rva, offset, insn );
return insn;
}
int disasm_range( unsigned char *buf, size_t buf_len,
unsigned long buf_rva, unsigned int offset,
unsigned int len ) {
x86_insn_list *list = x86_insn_list_new();
if ( len > buf_len ) {
len = buf_len;
}
return x86_disasm_range( buf, buf_rva, offset, len,
x86_default_callback, list );
}
int disasm_forward( unsigned char *buf, size_t buf_len,
unsigned long buf_rva, unsigned int offset ) {
x86_insn_list *list = x86_insn_list_new();
/* use default resolver: damn SWIG callbacks! */
return x86_disasm_forward( buf, buf_len, buf_rva, offset,
x86_default_callback, list,
x86_default_resolver, NULL );
}
size_t disasm_invariant( unsigned char *buf, size_t buf_len,
x86_invariant_t *inv ) {
return x86_invariant_disasm( buf, buf_len, inv );
}
size_t disasm_size( unsigned char *buf, size_t buf_len ) {
return x86_size_disasm( buf, buf_len );
}
int x86_max_operand_string( enum x86_asm_format format ) {
switch ( format ) {
case xml_syntax:
return MAX_OP_XML_STRING;
break;
case raw_syntax:
return MAX_OP_RAW_STRING;
break;
case native_syntax:
case intel_syntax:
case att_syntax:
case unknown_syntax:
default:
return MAX_OP_STRING;
break;
}
}
int x86_max_insn_string( enum x86_asm_format format ) {
switch ( format ) {
case xml_syntax:
return MAX_INSN_XML_STRING;
break;
case raw_syntax:
return MAX_INSN_RAW_STRING;
break;
case native_syntax:
case intel_syntax:
case att_syntax:
case unknown_syntax:
default:
return MAX_INSN_STRING;
break;
}
}
int x86_max_num_operands( ) { return MAX_NUM_OPERANDS; }
%}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,65 @@
ifndef BASE_NAME
BASE_NAME = x86disasm
endif
ifndef SWIG
SWIG = swig # apt-get install swig !
endif
ifndef GCC
GCC = gcc
endif
ifndef CC_FLAGS
CC_FLAGS = -c -fPIC
endif
ifndef LD_FLAGS
LD_FLAGS = -shared -L.. -ldisasm
endif
INTERFACE_FILE = libdisasm_oop.i
SWIG_INTERFACE = ../$(INTERFACE_FILE)
# PERL rules
PERL_MOD = blib/arch/auto/$(BASE_NAME)/$(BASE_NAME).so
PERL_SHADOW = $(BASE_NAME)_wrap.c
PERL_SWIG = $(BASE_NAME).pl
PERL_OBJ = $(BASE_NAME)_wrap.o
PERL_INC = `perl -e 'use Config; print $$Config{archlib};'`/CORE
PERL_CC_FLAGS = `perl -e 'use Config; print $$Config{ccflags};'`
#====================================================
# TARGETS
all: swig-perl
dummy: swig-perl install uninstall clean
swig-perl: $(PERL_MOD)
$(PERL_MOD): $(PERL_OBJ)
perl Makefile.PL
make
#$(GCC) $(LD_FLAGS) $(PERL_OBJ) -o $@
$(PERL_OBJ): $(PERL_SHADOW)
$(GCC) $(CC_FLAGS) $(PERL_CC_FLAGS) -I$(PERL_INC) -o $@ $<
$(PERL_SHADOW): $(SWIG_INTERFACE)
swig -perl -shadow -o $(PERL_SHADOW) -outdir . $<
# ==================================================================
install: $(PERL_MOD)
make install
# ==================================================================
uninstall:
# ==================================================================
clean:
rm $(PERL_MOD) $(PERL_OBJ)
rm $(PERL_SHADOW)
rm -rf Makefile blib pm_to_blib

View file

@ -0,0 +1,7 @@
use ExtUtils::MakeMaker;
WriteMakefile(
'NAME' => 'x86disasm',
'LIBS' => ['-ldisasm'],
'OBJECT' => 'x86disasm_wrap.o'
);

View file

@ -0,0 +1,64 @@
ifndef BASE_NAME
BASE_NAME = x86disasm
endif
ifndef SWIG
SWIG = swig # apt-get install swig !
endif
ifndef GCC
GCC = gcc
endif
ifndef CC_FLAGS
CC_FLAGS = -c -fPIC
endif
ifndef LD_FLAGS
LD_FLAGS = -shared -L.. -ldisasm
endif
INTERFACE_FILE = libdisasm_oop.i
SWIG_INTERFACE = ../$(INTERFACE_FILE)
# PYTHON rules
PYTHON_MOD = $(BASE_NAME)-python.so
PYTHON_SHADOW = $(BASE_NAME)_wrap.c
PYTHON_SWIG = $(BASE_NAME).py
PYTHON_OBJ = $(BASE_NAME)_wrap.o
PYTHON_INC = `/bin/echo -e 'import sys\nprint sys.prefix + "/include/python" + sys.version[:3]' | python`
PYTHON_LIB = `/bin/echo -e 'import sys\nprint sys.prefix + "/lib/python" + sys.version[:3]' | python`
PYTHON_DEST = $(PYTHON_LIB)/lib-dynload/_$(BASE_NAME).so
#====================================================
# TARGETS
all: swig-python
dummy: swig-python install uninstall clean
swig-python: $(PYTHON_MOD)
$(PYTHON_MOD): $(PYTHON_OBJ)
$(GCC) $(LD_FLAGS) $(PYTHON_OBJ) -o $@
$(PYTHON_OBJ): $(PYTHON_SHADOW)
$(GCC) $(CC_FLAGS) -I$(PYTHON_INC) -I.. -o $@ $<
$(PYTHON_SHADOW): $(SWIG_INTERFACE)
swig -python -shadow -o $(PYTHON_SHADOW) -outdir . $<
# ==================================================================
install: $(PYTHON_MOD)
sudo cp $(PYTHON_MOD) $(PYTHON_DEST)
sudo cp $(PYTHON_SWIG) $(PYTHON_LIB)
# ==================================================================
uninstall:
# ==================================================================
clean:
rm $(PYTHON_MOD) $(PYTHON_SWIG) $(PYTHON_OBJ)
rm $(PYTHON_SHADOW)

View file

@ -0,0 +1,68 @@
ifndef BASE_NAME
BASE_NAME = x86disasm
endif
ifndef SWIG
SWIG = swig # apt-get install swig !
endif
ifndef GCC
GCC = gcc
endif
ifndef CC_FLAGS
CC_FLAGS = -c -fPIC
endif
ifndef LD_FLAGS
LD_FLAGS = -shared -L../.. -ldisasm
endif
LIBDISASM_DIR = ../..
INTERFACE_FILE = libdisasm_oop.i
SWIG_INTERFACE = ../$(INTERFACE_FILE)
# RUBY rules
RUBY_MAKEFILE = Makefile
RUBY_MOD = $(BASE_NAME).so
RUBY_SHADOW = $(BASE_NAME)_wrap.c
#RUBY_SWIG = $(BASE_NAME).rb
RUBY_OBJ = $(BASE_NAME)_wrap.o
RUBY_INC = `ruby -e 'puts $$:.join("\n")' | tail -2 | head -1`
#RUBY_LIB =
#RUBY_DEST =
#====================================================
# TARGETS
all: swig-ruby
dummy: swig-ruby install uninstall clean
swig-ruby: $(RUBY_MOD)
$(RUBY_MOD): $(RUBY_MAKEFILE)
make
$(RUBY_MAKEFILE): $(RUBY_OBJ)
ruby extconf.rb
$(RUBY_OBJ):$(RUBY_SHADOW)
$(GCC) $(CC_FLAGS) -I$(RUBY_INC) -I.. -o $@ $<
$(RUBY_SHADOW): $(SWIG_INTERFACE)
swig -ruby -o $(RUBY_SHADOW) -outdir . $<
# ==================================================================
install: $(RUBY_MOD)
make install
# ==================================================================
uninstall:
# ==================================================================
clean:
make clean || true
rm $(RUBY_SHADOW) $(RUBY_MAKEFILE) $(RUBY_MOD) $(RUBY_OBJ)

View file

@ -0,0 +1,4 @@
require 'mkmf'
find_library('disasm', 'x86_init', "/usr/local/lib", "../..")
create_makefile('x86disasm')

View file

@ -0,0 +1,63 @@
ifndef BASE_NAME
BASE_NAME = x86disasm
endif
ifndef SWIG
SWIG = swig # apt-get install swig !
endif
ifndef GCC
GCC = gcc
endif
ifndef CC_FLAGS
CC_FLAGS = -c -fPIC
endif
ifndef LD_FLAGS
LD_FLAGS = -shared -L../.. -ldisasm
endif
INTERFACE_FILE = libdisasm.i
SWIG_INTERFACE = ../$(INTERFACE_FILE)
# TCL rules
TCL_VERSION = 8.3
TCL_MOD = $(BASE_NAME)-tcl.so
TCL_SHADOW = $(BASE_NAME)_wrap.c
TCL_OBJ = $(BASE_NAME)_wrap.o
TCL_INC = /usr/include/tcl$(TCL_VERSION)
TCL_LIB = /usr/lib/tcl$(TCL_VERSION)
TCL_DEST = $(TCL_LIB)/$(BASE_NAME).so
#====================================================
# TARGETS
all: swig-tcl
dummy: swig-tcl install uninstall clean
swig-tcl: $(TCL_MOD)
$(TCL_MOD): $(TCL_OBJ)
$(GCC) $(LD_FLAGS) $(TCL_OBJ) -o $@
$(TCL_OBJ): $(TCL_SHADOW)
$(GCC) $(CC_FLAGS) -I$(TCL_INC) -I.. -o $@ $<
$(TCL_SHADOW): $(SWIG_INTERFACE)
swig -tcl -o $(TCL_SHADOW) -outdir . $<
# ==================================================================
install: $(TCL_MOD)
sudo cp $(TCL_MOD) $(TCL_DEST)
# ==================================================================
uninstall:
# ==================================================================
clean:
rm $(TCL_MOD) $(TCL_SWIG) $(TCL_OBJ)
rm $(TCL_SHADOW)

View file

@ -0,0 +1,210 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libdis.h"
#include "ia32_insn.h"
#include "ia32_invariant.h"
#include "x86_operand_list.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#define inline __inline
#endif
unsigned int x86_disasm( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
x86_insn_t *insn ){
int len, size;
unsigned char bytes[MAX_INSTRUCTION_SIZE];
if ( ! buf || ! insn || ! buf_len ) {
/* caller screwed up somehow */
return 0;
}
/* ensure we are all NULLed up */
memset( insn, 0, sizeof(x86_insn_t) );
insn->addr = buf_rva + offset;
insn->offset = offset;
/* default to invalid insn */
insn->type = insn_invalid;
insn->group = insn_none;
if ( offset >= buf_len ) {
/* another caller screwup ;) */
x86_report_error(report_disasm_bounds, (void*)(long)(buf_rva+offset));
return 0;
}
len = buf_len - offset;
/* copy enough bytes for disassembly into buffer : this
* helps prevent buffer overruns at the end of a file */
memset( bytes, 0, MAX_INSTRUCTION_SIZE );
memcpy( bytes, &buf[offset], (len < MAX_INSTRUCTION_SIZE) ? len :
MAX_INSTRUCTION_SIZE );
/* actually do the disassembly */
/* TODO: allow switching when more disassemblers are added */
size = ia32_disasm_addr( bytes, len, insn);
/* check and see if we had an invalid instruction */
if (! size ) {
x86_report_error(report_invalid_insn, (void*)(long)(buf_rva+offset));
return 0;
}
/* check if we overran the end of the buffer */
if ( size > len ) {
x86_report_error( report_insn_bounds, (void*)(long)(buf_rva + offset));
MAKE_INVALID( insn, bytes );
return 0;
}
/* fill bytes field of insn */
memcpy( insn->bytes, bytes, size );
return size;
}
unsigned int x86_disasm_range( unsigned char *buf, uint32_t buf_rva,
unsigned int offset, unsigned int len,
DISASM_CALLBACK func, void *arg ) {
x86_insn_t insn;
unsigned int buf_len, size, count = 0, bytes = 0;
/* buf_len is implied by the arguments */
buf_len = len + offset;
while ( bytes < len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
x86_oplist_free( &insn );
}
return( count );
}
static inline int follow_insn_dest( x86_insn_t *insn ) {
if ( insn->type == insn_jmp || insn->type == insn_jcc ||
insn->type == insn_call || insn->type == insn_callcc ) {
return(1);
}
return(0);
}
static inline int insn_doesnt_return( x86_insn_t *insn ) {
return( (insn->type == insn_jmp || insn->type == insn_return) ? 1: 0 );
}
static int32_t internal_resolver( x86_op_t *op, x86_insn_t *insn ){
int32_t next_addr = -1;
if ( x86_optype_is_address(op->type) ) {
next_addr = op->data.sdword;
} else if ( op->type == op_relative_near ) {
next_addr = insn->addr + insn->size + op->data.relative_near;
} else if ( op->type == op_relative_far ) {
next_addr = insn->addr + insn->size + op->data.relative_far;
}
return( next_addr );
}
unsigned int x86_disasm_forward( unsigned char *buf, unsigned int buf_len,
uint32_t buf_rva, unsigned int offset,
DISASM_CALLBACK func, void *arg,
DISASM_RESOLVER resolver, void *r_arg ){
x86_insn_t insn;
x86_op_t *op;
int32_t next_addr;
uint32_t next_offset;
unsigned int size, count = 0, bytes = 0, cont = 1;
while ( cont && bytes < buf_len ) {
size = x86_disasm( buf, buf_len, buf_rva, offset + bytes,
&insn );
if ( size ) {
/* invoke callback if it exists */
if ( func ) {
(*func)( &insn, arg );
}
bytes += size;
count ++;
} else {
/* error */
bytes++; /* try next byte */
}
if ( follow_insn_dest(&insn) ) {
op = x86_get_dest_operand( &insn );
next_addr = -1;
/* if caller supplied a resolver, use it to determine
* the address to disassemble */
if ( resolver ) {
next_addr = resolver(op, &insn, r_arg);
} else {
next_addr = internal_resolver(op, &insn);
}
if (next_addr != -1 ) {
next_offset = next_addr - buf_rva;
/* if offset is in this buffer... */
if ( (uint32_t)next_addr >= buf_rva &&
next_offset < buf_len ) {
/* go ahead and disassemble */
count += x86_disasm_forward( buf,
buf_len,
buf_rva,
next_offset,
func, arg,
resolver, r_arg );
} else {
/* report unresolved address */
x86_report_error( report_disasm_bounds,
(void*)(long)next_addr );
}
}
} /* end follow_insn */
if ( insn_doesnt_return(&insn) ) {
/* stop disassembling */
cont = 0;
}
x86_oplist_free( &insn );
}
return( count );
}
/* invariant instruction representation */
size_t x86_invariant_disasm( unsigned char *buf, int buf_len,
x86_invariant_t *inv ){
if (! buf || ! buf_len || ! inv ) {
return(0);
}
return ia32_disasm_invariant(buf, buf_len, inv);
}
size_t x86_size_disasm( unsigned char *buf, unsigned int buf_len ) {
if (! buf || ! buf_len ) {
return(0);
}
return ia32_disasm_size(buf, buf_len);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,70 @@
#include "qword.h"
#include "x86_imm.h"
#include <stdio.h>
unsigned int x86_imm_signsized( unsigned char * buf, size_t buf_len,
void *dest, unsigned int size ) {
signed char *cp = (signed char *) dest;
signed short *sp = (signed short *) dest;
int32_t *lp = (int32_t *) dest;
qword_t *qp = (qword_t *) dest;
if ( size > buf_len ) {
return 0;
}
/* Copy 'size' bytes from *buf to *op
* return number of bytes copied */
switch (size) {
case 1: /* BYTE */
*cp = *((signed char *) buf);
break;
case 2: /* WORD */
*sp = *((signed short *) buf);
break;
case 6:
case 8: /* QWORD */
*qp = *((qword_t *) buf);
break;
case 4: /* DWORD */
default:
*lp = *((int32_t *) buf);
break;
}
return (size);
}
unsigned int x86_imm_sized( unsigned char * buf, size_t buf_len, void *dest,
unsigned int size ) {
unsigned char *cp = (unsigned char *) dest;
unsigned short *sp = (unsigned short *) dest;
uint32_t *lp = (uint32_t *) dest;
qword_t *qp = (qword_t *) dest;
if ( size > buf_len ) {
return 0;
}
/* Copy 'size' bytes from *buf to *op
* return number of bytes copied */
switch (size) {
case 1: /* BYTE */
*cp = *((unsigned char *) buf);
break;
case 2: /* WORD */
*sp = *((unsigned short *) buf);
break;
case 6:
case 8: /* QWORD */
*qp = *((qword_t *) buf);
break;
case 4: /* DWORD */
default:
*lp = *((uint32_t *) buf);
break;
}
return (size);
}

View file

@ -0,0 +1,18 @@
#ifndef x86_IMM_H
#define x86_IMM_H
#include "./qword.h"
#include <sys/types.h>
#ifdef WIN32
#include <windows.h>
#endif
/* these are in the global x86 namespace but are not a part of the
* official API */
unsigned int x86_imm_sized( unsigned char *buf, size_t buf_len, void *dest,
unsigned int size );
unsigned int x86_imm_signsized( unsigned char *buf, size_t buf_len, void *dest,
unsigned int size );
#endif

View file

@ -0,0 +1,182 @@
#include <stdio.h>
#include <stdlib.h>
#include "libdis.h"
#ifdef _MSC_VER
#define snprintf _snprintf
#define inline __inline
#endif
int x86_insn_is_valid( x86_insn_t *insn ) {
if ( insn && insn->type != insn_invalid && insn->size > 0 ) {
return 1;
}
return 0;
}
uint32_t x86_get_address( x86_insn_t *insn ) {
x86_oplist_t *op_lst;
if (! insn || ! insn->operands ) {
return 0;
}
for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.type == op_offset ) {
return op_lst->op.data.offset;
} else if ( op_lst->op.type == op_absolute ) {
if ( op_lst->op.datatype == op_descr16 ) {
return (uint32_t)
op_lst->op.data.absolute.offset.off16;
}
return op_lst->op.data.absolute.offset.off32;
}
}
return 0;
}
int32_t x86_get_rel_offset( x86_insn_t *insn ) {
x86_oplist_t *op_lst;
if (! insn || ! insn->operands ) {
return 0;
}
for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.type == op_relative_near ) {
return (int32_t) op_lst->op.data.relative_near;
} else if ( op_lst->op.type == op_relative_far ) {
return op_lst->op.data.relative_far;
}
}
return 0;
}
x86_op_t * x86_get_branch_target( x86_insn_t *insn ) {
x86_oplist_t *op_lst;
if (! insn || ! insn->operands ) {
return NULL;
}
for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.access & op_execute ) {
return &(op_lst->op);
}
}
return NULL;
}
x86_op_t * x86_get_imm( x86_insn_t *insn ) {
x86_oplist_t *op_lst;
if (! insn || ! insn->operands ) {
return NULL;
}
for (op_lst = insn->operands; op_lst; op_lst = op_lst->next ) {
if ( op_lst->op.type == op_immediate ) {
return &(op_lst->op);
}
}
return NULL;
}
#define IS_PROPER_IMM( x ) \
x->op.type == op_immediate && ! (x->op.flags & op_hardcode)
/* if there is an immediate value in the instruction, return a pointer to
* it */
unsigned char * x86_get_raw_imm( x86_insn_t *insn ) {
int size, offset;
x86_op_t *op = NULL;
if (! insn || ! insn->operands ) {
return(NULL);
}
/* a bit inelegant, but oh well... */
if ( IS_PROPER_IMM( insn->operands ) ) {
op = &insn->operands->op;
} else if ( insn->operands->next ) {
if ( IS_PROPER_IMM( insn->operands->next ) ) {
op = &insn->operands->next->op;
} else if ( insn->operands->next->next &&
IS_PROPER_IMM( insn->operands->next->next ) ) {
op = &insn->operands->next->next->op;
}
}
if (! op ) {
return( NULL );
}
/* immediate data is at the end of the insn */
size = x86_operand_size( op );
offset = insn->size - size;
return( &insn->bytes[offset] );
}
unsigned int x86_operand_size( x86_op_t *op ) {
switch (op->datatype ) {
case op_byte: return 1;
case op_word: return 2;
case op_dword: return 4;
case op_qword: return 8;
case op_dqword: return 16;
case op_sreal: return 4;
case op_dreal: return 8;
case op_extreal: return 10;
case op_bcd: return 10;
case op_ssimd: return 16;
case op_dsimd: return 16;
case op_sssimd: return 4;
case op_sdsimd: return 8;
case op_descr32: return 6;
case op_descr16: return 4;
case op_pdescr32: return 6;
case op_pdescr16: return 6;
case op_bounds16: return 4;
case op_bounds32: return 8;
case op_fpuenv16: return 14;
case op_fpuenv32: return 28;
case op_fpustate16: return 94;
case op_fpustate32: return 108;
case op_fpregset: return 512;
case op_fpreg: return 10;
case op_none: return 0;
}
return(4); /* default size */
}
void x86_set_insn_addr( x86_insn_t *insn, uint32_t addr ) {
if ( insn ) insn->addr = addr;
}
void x86_set_insn_offset( x86_insn_t *insn, unsigned int offset ){
if ( insn ) insn->offset = offset;
}
void x86_set_insn_function( x86_insn_t *insn, void * func ){
if ( insn ) insn->function = func;
}
void x86_set_insn_block( x86_insn_t *insn, void * block ){
if ( insn ) insn->block = block;
}
void x86_tag_insn( x86_insn_t *insn ){
if ( insn ) insn->tag = 1;
}
void x86_untag_insn( x86_insn_t *insn ){
if ( insn ) insn->tag = 0;
}
int x86_insn_is_tagged( x86_insn_t *insn ){
return insn->tag;
}

View file

@ -0,0 +1,71 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "libdis.h"
#include "ia32_insn.h"
#include "ia32_reg.h" /* for ia32_reg wrapper */
#include "ia32_settings.h"
extern ia32_settings_t ia32_settings;
#ifdef _MSC_VER
#define snprintf _snprintf
#define inline __inline
#endif
/* =========================================================== INIT/TERM */
static DISASM_REPORTER __x86_reporter_func = NULL;
static void * __x86_reporter_arg = NULL;
int x86_init( enum x86_options options, DISASM_REPORTER reporter, void * arg )
{
ia32_settings.options = options;
__x86_reporter_func = reporter;
__x86_reporter_arg = arg;
return 1;
}
void x86_set_reporter( DISASM_REPORTER reporter, void * arg ) {
__x86_reporter_func = reporter;
__x86_reporter_arg = arg;
}
void x86_set_options( enum x86_options options ){
ia32_settings.options = options;
}
enum x86_options x86_get_options( void ) {
return ia32_settings.options;
}
int x86_cleanup( void )
{
return 1;
}
/* =========================================================== ERRORS */
void x86_report_error( enum x86_report_codes code, void *data ) {
if ( __x86_reporter_func ) {
(*__x86_reporter_func)(code, data, __x86_reporter_arg);
}
}
/* =========================================================== MISC */
unsigned int x86_endian(void) { return ia32_settings.endian; }
unsigned int x86_addr_size(void) { return ia32_settings.sz_addr; }
unsigned int x86_op_size(void) { return ia32_settings.sz_oper; }
unsigned int x86_word_size(void) { return ia32_settings.sz_word; }
unsigned int x86_max_insn_size(void) { return ia32_settings.max_insn; }
unsigned int x86_sp_reg(void) { return ia32_settings.id_sp_reg; }
unsigned int x86_fp_reg(void) { return ia32_settings.id_fp_reg; }
unsigned int x86_ip_reg(void) { return ia32_settings.id_ip_reg; }
unsigned int x86_flag_reg(void) { return ia32_settings.id_flag_reg; }
/* wrapper function to hide the IA32 register fn */
void x86_reg_from_id( unsigned int id, x86_reg_t * reg ) {
ia32_handle_register( reg, id );
return;
}

View file

@ -0,0 +1,191 @@
#include <stdlib.h>
#include "libdis.h"
static void x86_oplist_append( x86_insn_t *insn, x86_oplist_t *op ) {
x86_oplist_t *list;
if (! insn ) {
return;
}
list = insn->operands;
if (! list ) {
insn->operand_count = 1;
/* Note that we have no way of knowing if this is an
* exlicit operand or not, since the caller fills
* the x86_op_t after we return. We increase the
* explicit count automatically, and ia32_insn_implicit_ops
* decrements it */
insn->explicit_count = 1;
insn->operands = op;
return;
}
/* get to end of list */
for ( ; list->next; list = list->next )
;
insn->operand_count = insn->operand_count + 1;
insn->explicit_count = insn->explicit_count + 1;
list->next = op;
return;
}
x86_op_t * x86_operand_new( x86_insn_t *insn ) {
x86_oplist_t *op;
if (! insn ) {
return(NULL);
}
op = calloc( sizeof(x86_oplist_t), 1 );
op->op.insn = insn;
x86_oplist_append( insn, op );
return( &(op->op) );
}
void x86_oplist_free( x86_insn_t *insn ) {
x86_oplist_t *op, *list;
if (! insn ) {
return;
}
for ( list = insn->operands; list; ) {
op = list;
list = list->next;
free(op);
}
insn->operands = NULL;
insn->operand_count = 0;
insn->explicit_count = 0;
return;
}
/* ================================================== LIBDISASM API */
/* these could probably just be #defines, but that means exposing the
enum... yet one more confusing thing in the API */
int x86_operand_foreach( x86_insn_t *insn, x86_operand_fn func, void *arg,
enum x86_op_foreach_type type ){
x86_oplist_t *list;
char explicit = 1, implicit = 1;
if (! insn || ! func ) {
return 0;
}
/* note: explicit and implicit can be ORed together to
* allow an "all" limited by access type, even though the
* user is stupid to do this since it is default behavior :) */
if ( (type & op_explicit) && ! (type & op_implicit) ) {
implicit = 0;
}
if ( (type & op_implicit) && ! (type & op_explicit) ) {
explicit = 0;
}
type = type & 0x0F; /* mask out explicit/implicit operands */
for ( list = insn->operands; list; list = list->next ) {
if (! implicit && (list->op.flags & op_implied) ) {
/* operand is implicit */
continue;
}
if (! explicit && ! (list->op.flags & op_implied) ) {
/* operand is not implicit */
continue;
}
switch ( type ) {
case op_any:
break;
case op_dest:
if (! (list->op.access & op_write) ) {
continue;
}
break;
case op_src:
if (! (list->op.access & op_read) ) {
continue;
}
break;
case op_ro:
if (! (list->op.access & op_read) ||
(list->op.access & op_write ) ) {
continue;
}
break;
case op_wo:
if (! (list->op.access & op_write) ||
(list->op.access & op_read ) ) {
continue;
}
break;
case op_xo:
if (! (list->op.access & op_execute) ) {
continue;
}
break;
case op_rw:
if (! (list->op.access & op_write) ||
! (list->op.access & op_read ) ) {
continue;
}
break;
case op_implicit: case op_explicit: /* make gcc happy */
break;
}
/* any non-continue ends up here: invoke the callback */
(*func)( &list->op, insn, arg );
}
return 1;
}
static void count_operand( x86_op_t *op, x86_insn_t *insn, void *arg ) {
size_t * count = (size_t *) arg;
*count = *count + 1;
}
size_t x86_operand_count( x86_insn_t *insn, enum x86_op_foreach_type type ) {
size_t count = 0;
/* save us a list traversal for common counts... */
if ( type == op_any ) {
return insn->operand_count;
} else if ( type == op_explicit ) {
return insn->explicit_count;
}
x86_operand_foreach( insn, count_operand, &count, type );
return count;
}
/* accessor functions */
x86_op_t * x86_operand_1st( x86_insn_t *insn ) {
if (! insn->explicit_count ) {
return NULL;
}
return &(insn->operands->op);
}
x86_op_t * x86_operand_2nd( x86_insn_t *insn ) {
if ( insn->explicit_count < 2 ) {
return NULL;
}
return &(insn->operands->next->op);
}
x86_op_t * x86_operand_3rd( x86_insn_t *insn ) {
if ( insn->explicit_count < 3 ) {
return NULL;
}
return &(insn->operands->next->next->op);
}

View file

@ -0,0 +1,8 @@
#ifndef X86_OPERAND_LIST_H
#define X86_OPERAND_LIST_H
#include "libdis.h"
x86_op_t * x86_operand_new( x86_insn_t *insn );
#endif

View file

@ -0,0 +1,120 @@
// Copyright 2008 Google LLC
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google LLC nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// ---
// Author: Dave Nicponski
//
// Implement helpful bash-style command line flag completions
//
// ** Functional API:
// HandleCommandLineCompletions() should be called early during
// program startup, but after command line flag code has been
// initialized, such as the beginning of HandleCommandLineHelpFlags().
// It checks the value of the flag --tab_completion_word. If this
// flag is empty, nothing happens here. If it contains a string,
// however, then HandleCommandLineCompletions() will hijack the
// process, attempting to identify the intention behind this
// completion. Regardless of the outcome of this deduction, the
// process will be terminated, similar to --helpshort flag
// handling.
//
// ** Overview of Bash completions:
// Bash can be told to programatically determine completions for the
// current 'cursor word'. It does this by (in this case) invoking a
// command with some additional arguments identifying the command
// being executed, the word being completed, and the previous word
// (if any). Bash then expects a sequence of output lines to be
// printed to stdout. If these lines all contain a common prefix
// longer than the cursor word, bash will replace the cursor word
// with that common prefix, and display nothing. If there isn't such
// a common prefix, bash will display the lines in pages using 'more'.
//
// ** Strategy taken for command line completions:
// If we can deduce either the exact flag intended, or a common flag
// prefix, we'll output exactly that. Otherwise, if information
// must be displayed to the user, we'll take the opportunity to add
// some helpful information beyond just the flag name (specifically,
// we'll include the default flag value and as much of the flag's
// description as can fit on a single terminal line width, as specified
// by the flag --tab_completion_columns). Furthermore, we'll try to
// make bash order the output such that the most useful or relevent
// flags are the most likely to be shown at the top.
//
// ** Additional features:
// To assist in finding that one really useful flag, substring matching
// was implemented. Before pressing a <TAB> to get completion for the
// current word, you can append one or more '?' to the flag to do
// substring matching. Here's the semantics:
// --foo<TAB> Show me all flags with names prefixed by 'foo'
// --foo?<TAB> Show me all flags with 'foo' somewhere in the name
// --foo??<TAB> Same as prior case, but also search in module
// definition path for 'foo'
// --foo???<TAB> Same as prior case, but also search in flag
// descriptions for 'foo'
// Finally, we'll trim the output to a relatively small number of
// flags to keep bash quiet about the verbosity of output. If one
// really wanted to see all possible matches, appending a '+' to the
// search word will force the exhaustive list of matches to be printed.
//
// ** How to have bash accept completions from a binary:
// Bash requires that it be informed about each command that programmatic
// completion should be enabled for. Example addition to a .bashrc
// file would be (your path to gflags_completions.sh file may differ):
/*
$ complete -o bashdefault -o default -o nospace -C \
'/usr/local/bin/gflags_completions.sh --tab_completion_columns $COLUMNS' \
time env binary_name another_binary [...]
*/
// This would allow the following to work:
// $ /path/to/binary_name --vmodule<TAB>
// Or:
// $ ./bin/path/another_binary --gfs_u<TAB>
// (etc)
//
// Sadly, it appears that bash gives no easy way to force this behavior for
// all commands. That's where the "time" in the above example comes in.
// If you haven't specifically added a command to the list of completion
// supported commands, you can still get completions by prefixing the
// entire command with "env".
// $ env /some/brand/new/binary --vmod<TAB>
// Assuming that "binary" is a newly compiled binary, this should still
// produce the expected completion output.
#ifndef GOOGLE_GFLAGS_COMPLETIONS_H_
#define GOOGLE_GFLAGS_COMPLETIONS_H_
namespace google {
void HandleCommandLineCompletions(void);
}
#endif // GOOGLE_GFLAGS_COMPLETIONS_H_

View file

@ -0,0 +1,3 @@
*.o
core

View file

@ -0,0 +1,12 @@
# Metadata information for this directory.
#
# For more information on DIR_METADATA files, see:
# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/README.md
#
# For the schema of this file, see Metadata message:
# https://source.chromium.org/chromium/infra/infra/+/HEAD:go/src/infra/tools/dirmd/proto/dir_metadata.proto
os: LINUX
monorail {
project: "linux-syscall-support"
}

View file

@ -0,0 +1,27 @@
Copyright 2005-2011 Google LLC
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the following disclaimer
in the documentation and/or other materials provided with the
distribution.
Neither the name of Google LLC nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -0,0 +1,2 @@
mseaborn@chromium.org
vapier@chromium.org

View file

@ -0,0 +1,138 @@
# Linux Syscall Support (LSS)
Every so often, projects need to directly embed Linux system calls instead of
calling the implementations in the system runtime library.
This project provides a header file that can be included into your application
whenever you need to make direct system calls.
The goal is to provide an API that generally mirrors the standard C library
while still making direct syscalls. We try to hide some of the differences
between arches when reasonably feasible. e.g. Newer architectures no longer
provide an `open` syscall, but do provide `openat`. We will still expose a
`sys_open` helper by default that calls into `openat` instead.
We explicitly do not expose the raw syscall ABI including all of its historical
warts to the user. We want people to be able to easily make a syscall, not have
to worry that on some arches size args are swapped or they are shifted.
Please be sure to review the Caveats section below however.
## How to include linux\_syscall\_support.h in your project
You can either copy the file into your project, or preferably, you can set up
Git submodules to automatically pull from our source repository.
## Supported targets
The following architectures/ABIs have been tested (at some point) and should
generally work. If you don't see your combo listed here, please double check
the header itself as this list might be out of date.
* x86 32-bit (i.e. i386, i486, i586, i686, Intel, AMD, etc...)
* [x86_64 64-bit](https://en.wikipedia.org/wiki/X86-64) (i.e. x86-64, amd64, etc...)
* [x32 32-bit](https://sites.google.com/site/x32abi/)
* [ARM 32-bit](https://en.wikipedia.org/wiki/ARM_architecture) OABI
* [ARM 32-bit](https://en.wikipedia.org/wiki/ARM_architecture) EABI (i.e. armv6, armv7, etc...)
* AARCH64 64-bit (i.e. arm64, armv8, etc...)
* PowerPC 32-bit (i.e. ppc, ppc32, etc...)
* MIPS 32-bit o32 ABI
* MIPS 32-bit n32 ABI
* MIPS 64-bit n64 ABI
* LOONGARCH 64-bit ABI
## API
By default, you can just add a `sys_` prefix to any function you want to call.
So if you want to call `open(...)`, use `sys_open(...)` instead.
### Knobs
The linux\_syscall\_support.h header provides many knobs for you to control
the exported API. These are all documented in the top of the header in a big
comment block, so refer to that instead.
## Caveats
### ABI differences
Some functions that the standard C library exposes use a different ABI than
what the Linux kernel uses. Care must be taken when making syscalls directly
that you use the right structure and flags. e.g. Most C libraries define a
`struct stat` (commonly in `sys/stat.h` or `bits/stat.h`) that is different
from the `struct stat` the kernel uses (commonly in `asm/stat.h`). If you use
the wrong structure layout, then you can see errors like memory corruption or
weird/shifted values. If you plan on making syscalls directly, you should
focus on headers that are available under the `linux/` and `asm/` namespaces.
Note: LSS provides structs for most of these cases. For `sys_stat()`, it
provides `struct kernel_stat` for you to use.
### Transparent backwards compatibility with older kernels
While some C libraries (notably, glibc) take care to fallback to older syscalls
when running on older kernels, there is no such support in LSS. If you plan on
trying to run on older kernels, you will need to handle errors yourself (e.g.
`ENOSYS` when using a too new syscall).
Remember that this can happen with new flag bits too. e.g. The `O_CLOEXEC`
flag was added to many syscalls, but if you try to run use it on older kernels,
it will fail with `EINVAL`. In that case, you must handle the fallback logic
yourself.
### Variable arguments (varargs)
We do not support vararg type functions. e.g. While the standard `open()`
function can accept 2 or 3 arguments (with the mode field being optional),
the `sys_open()` function always requires 3 arguments.
## Bug reports & feature requests
If you wish to report a problem or request a feature, please file them in our
[bug tracker](https://bugs.chromium.org/p/linux-syscall-support/issues/).
Please do not post patches to the tracker. Instead, see below for how to send
patches to us directly.
While we welcome feature requests, please keep in mind that it is unlikely that
anyone will find time to implement them for you. Sending patches is strongly
preferred and will often move things much faster.
## Projects that use LSS
* [Chromium](https://www.chromium.org/)
* [Breakpad](https://chromium.googlesource.com/breakpad/breakpad)
* [Native Client](https://developer.chrome.com/native-client), in nacl\_bootstrap.c
## How to get an LSS change committed
### Review
You get your change reviewed, you can upload it to
[Gerrit](https://chromium-review.googlesource.com/q/project:linux-syscall-support+status:open)
using `git cl upload` from
[Chromium's depot-tools](https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools_tutorial.html).
### Testing
Tests are found in the [tests/](./tests/) subdirectory. It does not (yet) offer
100% coverage, but should grow over time.
New commits that update/change/add syscall wrappers should include tests for
them too. Consult the [test documentation](./tests/README.md) for more details.
To run, just run `make` inside the tests directory. It will compile & execute
the tests locally.
There is some limited cross-compile coverage available if you run `make cross`.
It only compiles things (does not execute at all).
### Rolling into Chromium
If you commit a change to LSS, please also commit a Chromium change to update
`lss_revision` in
[Chromium's DEPS](https://chromium.googlesource.com/chromium/src/+/HEAD/DEPS)
file.
This ensures that the LSS change gets tested, so that people who commit later
LSS changes don't run into problems with updating `lss_revision`.

View file

@ -0,0 +1,5 @@
# This file is used by git cl to get repository specific information.
CC_LIST: chromium-reviews@chromium.org,mseaborn@chromium.org
CODE_REVIEW_SERVER: codereview.chromium.org
GERRIT_HOST: True
VIEW_VC: https://chromium.googlesource.com/linux-syscall-support/+/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,4 @@
/*_test
# Some tests create temp files.
/tempfile.*

View file

@ -0,0 +1,147 @@
# Copyright 2018 Google LLC
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google LLC nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
top_srcdir ?= ..
DEF_FLAGS = -g -pipe
DEF_WFLAGS = -Wall
CFLAGS ?= $(DEF_FLAGS)
CXXFLAGS ?= $(DEF_FLAGS)
CFLAGS += $(DEF_WFLAGS) -Wstrict-prototypes
CXXFLAGS += $(DEF_WFLAGS)
CPPFLAGS += -I$(top_srcdir)
# We use static linking here so that if people run through qemu/etc... by hand,
# it's a lot easier to run/debug. Same for strace output.
LDFLAGS += -static
TESTS = \
fallocate \
getitimer \
getrandom \
lstat \
setitimer \
sigaction \
sigtimedwait \
stat \
unlink \
all: check
%_test: %.c test_skel.h $(top_srcdir)/linux_syscall_support.h
$(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
# Force building C as C++ code to improve compile-time coverage.
%_cc_test: %.c test_skel.h $(top_srcdir)/linux_syscall_support.h
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
%_test: %.cc test_skel.h $(top_srcdir)/linux_syscall_support.h
$(CXX) $(CXXFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $<
%_run: %_test
@t=$(@:_run=_test); \
echo "./$$t"; \
env -i ./$$t; \
exit_status=$$?; \
if [ $$exit_status = 77 ]; then \
echo "SKIP: $$t"; \
elif [ $$exit_status != 0 ]; then \
echo "FAIL: $$t"; \
env -i strace -f -v ./$$t; \
echo "TRY: gdb -q -ex r -ex bt ./$$t"; \
exit 1; \
fi
ALL_TEST_TARGETS = $(TESTS:=_test) $(TESTS:=_cc_test)
compile_tests: $(ALL_TEST_TARGETS)
ALL_RUN_TARGETS = $(TESTS:=_run) $(TESTS:=_cc_run)
check: $(ALL_RUN_TARGETS)
# The "tempfile" targets are the names we use with temp files.
# Clean them out in case some tests crashed in the middle.
clean:
rm -f *~ *.o tempfile.* a.out core $(ALL_TEST_TARGETS)
.SUFFIXES:
.PHONY: all check clean compile_tests
.SECONDARY: $(ALL_TEST_TARGETS)
# Try to cross-compile the tests for all our supported arches. We test with
# both gcc and clang. We don't support execution (yet?), but just compiling
# & linking helps catch common bugs.
.PHONY: cross compile_cross
cross_compile:
@echo "Running: $(MAKE) $@ CC='$(CC)' CXX='$(CXX)'"; \
if (echo '#include <stdio.h>' | $(CC) -x c -c -o /dev/null -) 2>/dev/null; then \
$(MAKE) -s clean; \
$(MAKE) -k --no-print-directory compile_tests; \
else \
echo "Skipping $(CC) test: not installed"; \
fi; \
echo
# The names here are a best effort. Not easy to probe for.
cross:
@for cc in \
"x86_64-pc-linux-gnu-gcc" \
"i686-pc-linux-gnu-gcc" \
"x86_64-pc-linux-gnu-gcc -mx32" \
"armv7a-unknown-linux-gnueabi-gcc -marm -mhard-float" \
"armv7a-unknown-linux-gnueabi-gcc -mthumb -mhard-float" \
"powerpc-unknown-linux-gnu-gcc" \
"aarch64-unknown-linux-gnu-gcc" \
"mips64-unknown-linux-gnu-gcc -mabi=64" \
"mips64-unknown-linux-gnu-gcc -mabi=32" \
"mips64-unknown-linux-gnu-gcc -mabi=n32" \
"s390-ibm-linux-gnu-gcc" \
"s390x-ibm-linux-gnu-gcc" \
"loongarch64-unknown-linux-gnu-gcc" \
; do \
cxx=`echo "$$cc" | sed 's:-gcc:-g++:'`; \
$(MAKE) --no-print-directory CC="$$cc" CXX="$$cxx" cross_compile; \
\
sysroot=`$$cc --print-sysroot 2>/dev/null`; \
gccdir=`$$cc -print-file-name=libgcc.a 2>/dev/null`; \
gccdir=`dirname "$$gccdir"`; \
: Skip building for clang for mips/o32 and s390/31-bit until it works.; \
case $$cc in \
mips64*-mabi=32) continue;; \
s390-*) continue;; \
esac; \
set -- $$cc; \
tuple=$${1%-gcc}; \
shift; \
cc="clang -target $$tuple $$*"; \
: Assume the build system is x86_64 based, so ignore the sysroot.; \
case $$tuple in \
x86_64*) ;; \
*) cc="$$cc --sysroot $$sysroot -B$$gccdir -L$$gccdir";; \
esac; \
cxx=`echo "$$cc" | sed 's:^clang:clang++:'`; \
$(MAKE) --no-print-directory CC="$$cc" CXX="$$cxx" cross_compile; \
done

View file

@ -0,0 +1,52 @@
# LSS Tests
## Source Layout
The general layout of the tests:
* [test_skel.h]: Test helpers for common checks/etc...
* xxx.c: Unittest for the xxx syscall (e.g. `open.c`).
* [Makefile]: New tests should be registered in the `TESTS` variable.
## Test Guidelines
The unittest itself generally follows the conventions:
* Written in C (unless a very specific language behavior is needed).
* You should only need to `#include "test_skel.h"`. For new system headers, try
to add them here rather than copying to exact unittest (if possible).
It might slow compilation down slightly, but makes the code easier to manage.
Make sure it is included first.
* Use `assert()` on everything to check return values.
* Use `sys_xxx()` to access the syscall via LSS (compared to `xxx()` which tends
to come from the C library).
* If you need a tempfile, use `tempfile.XXXXXX` for templates with helpers like
`mkstemp`. Try to clean them up when you're done with them.
These will be created in the cwd, but that's fine.
* Don't worry about trying to verify the kernel/C library API and various edge
cases. The goal of LSS is to make sure that we pass args along correctly to
the syscall only.
* Make sure to leave comments in the test so it's clear what behavior you're
trying to verify (and how).
Feel free to extend [test_skel.h] with more helpers if they're useful to more
than one test.
If you're looking for a simple example, start with [unlink.c](./unlink.c).
You should be able to copy this over and replace the content of `main()`.
## Running The Tests
Simply run `make`. This will compile & execute all the tests on your local
system. A standard `make clean` will clean up all the objects.
If you need to debug something, then the programs are simply named `xxx_test`
and can easily be thrown into `gdb ./xxx_test`.
We have rudimentary cross-compile testing via gcc and clang. Try running
`make cross` -- for any toolchains you don't have available, it should skip
things automatically. This only verifies the compilation & linking stages
though.
The cross-compilers can be created using <http://crosstool-ng.github.io/>.
[Makefile]: ./Makefile
[test_skel.h]: ./test_skel.h

View file

@ -0,0 +1,69 @@
/* Copyright 2019 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
int fd = 0, mode = 0;
loff_t offset = 0, len = 0;
// Bad file descriptor.
fd = -1;
assert(sys_fallocate(fd, mode, offset, len) == -1);
assert(errno == EBADF);
char filename[] = "tempfile.XXXXXX";
fd = mkstemp(filename);
assert(fd >= 0);
// Invalid len.
assert(sys_fallocate(fd, mode, offset, len) == -1);
assert(errno == EINVAL);
// Small offset and length succeeds.
len = 4096;
assert(sys_fallocate(fd, mode, offset, len) == 0);
// Large offset succeeds and isn't truncated.
offset = 1llu + UINT32_MAX;
assert(sys_fallocate(fd, mode , offset, len) == 0);
#if defined(__NR_fstat64)
struct kernel_stat64 st;
assert(sys_fstat64(fd, &st) == 0);
#else
struct kernel_stat st;
assert(sys_fstat(fd, &st) == 0);
#endif
assert(st.st_size == offset + len);
sys_unlink(filename);
return 0;
}

View file

@ -0,0 +1,84 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not available in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// This should fail with EINVAL.
struct kernel_itimerval curr_itimer;
assert(sys_getitimer(kInvalidTimer, &curr_itimer) == -1);
assert(errno == EINVAL);
// Create a read-only page.
size_t page_size = getpagesize();
void* read_only_page = sys_mmap(NULL, page_size, PROT_READ,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
assert(read_only_page != MAP_FAILED);
// This should fail with EFAULT.
assert(sys_getitimer(ITIMER_REAL,
(struct kernel_itimerval*) read_only_page) == -1);
assert(errno == EFAULT);
// This should complete without an error.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
// Set up a real time timer with very long interval and value so that
// we do not need to handle SIGALARM in test.
struct kernel_itimerval new_itimer;
const time_t kIntervalSec = 60 * 60 * 24 * 365; // One year.
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = kIntervalSec;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_timeval_eq(&curr_itimer.it_interval, &new_itimer.it_interval));
// Disable timer.
struct kernel_itimerval empty_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, NULL) == 0);
// We should read back an empty itimer.
assert(sys_getitimer(ITIMER_REAL, &curr_itimer) == 0);
assert(kernel_itimerval_eq(&curr_itimer, &empty_itimer));
return 0;
}

View file

@ -0,0 +1,59 @@
/* Copyright 2020 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
#define BUFFER_SIZE 256
int main(int argc, char *argv[]) {
char buffer[BUFFER_SIZE];
// Zero it out so we can check later that it's at least not all 0s.
memset(buffer, 0, BUFFER_SIZE);
bool buffer_contains_all_zeros = true;
// Don't bother passing any flags. (If we're using lss, we might not have the
// right header files with the flags defined anyway, and we'd have to copy
// this in here too, and risk getting out of sync in yet another way.)
const ssize_t r = sys_getrandom(buffer, BUFFER_SIZE, 0);
// Make sure it either worked, or that it's just not supported.
assert(r == BUFFER_SIZE || errno == ENOSYS);
if (r == BUFFER_SIZE) {
// If all the bytes are 0, it didn't really work.
for (size_t i = 0; i < BUFFER_SIZE; ++i) {
if (buffer[i] != 0) {
buffer_contains_all_zeros = false;
}
}
assert(!buffer_contains_all_zeros);
}
return 0;
}

View file

@ -0,0 +1,97 @@
/* Copyright 2021 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
int exit_status = 0;
// Get two unique paths to play with.
char foo[] = "tempfile.XXXXXX";
char bar[] = "tempfile.XXXXXX";
int fd_foo = mkstemp(foo);
int fd_bar = mkstemp(bar);
assert(fd_foo != -1);
assert(fd_bar != -1);
// Then delete foo.
assert(sys_unlink(foo) == 0);
// Now make foo a symlink to bar.
assert(symlink(bar, foo) == 0);
// Make sure sys_stat() and sys_lstat() implementation return different
// information.
// We need to check our stat syscalls for EOVERFLOW, as sometimes the integer
// types used in the stat structures are too small to fit the actual value.
// E.g. on some systems st_ino is 32-bit, but some filesystems have 64-bit
// inodes.
struct kernel_stat lstat_info;
int rc = sys_lstat(foo, &lstat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
struct kernel_stat stat_info;
rc = sys_stat(foo, &stat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
struct kernel_stat bar_stat_info;
rc = sys_stat(bar, &bar_stat_info);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
// lstat should produce information about a symlink.
assert((lstat_info.st_mode & S_IFMT) == S_IFLNK);
// stat-ing foo and bar should produce the same inode.
assert(stat_info.st_ino == bar_stat_info.st_ino);
// lstat-ing foo should give a different inode than stat-ing foo.
assert(stat_info.st_ino != lstat_info.st_ino);
cleanup:
sys_unlink(foo);
sys_unlink(bar);
return exit_status;
}

View file

@ -0,0 +1,90 @@
/* Copyright 2022 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// We need an invalid timer value. The assert()'s below should
// be static asserts but it is not avalible in older C versions.
#define kInvalidTimer 9999
assert(kInvalidTimer != ITIMER_REAL);
assert(kInvalidTimer != ITIMER_VIRTUAL);
assert(kInvalidTimer != ITIMER_PROF);
// Invalid timer returns EINVAL.
assert(sys_setitimer(kInvalidTimer, NULL, NULL) == -1);
assert(errno == EINVAL);
const int kSignal = SIGALRM;
const size_t kSigsetSize = sizeof(struct kernel_sigset_t);
// Block SIGALRM.
struct kernel_sigset_t sigalarm_only;
struct kernel_sigset_t old_sigset;
assert(sys_sigemptyset(&sigalarm_only) == 0);
assert(sys_sigaddset(&sigalarm_only, kSignal) == 0);
assert(sys_rt_sigprocmask(SIG_BLOCK, &sigalarm_only, &old_sigset,
kSigsetSize) == 0);
// Set up a real time timer.
struct kernel_itimerval new_itimer = {};
const long kIntervalUSec = 123;
new_itimer.it_interval.tv_sec = 0;
new_itimer.it_interval.tv_usec = kIntervalUSec;
new_itimer.it_value = new_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &new_itimer, NULL) == 0);
// Wait for alarm.
struct timespec timeout;
const unsigned long kNanoSecsPerSec = 1000000000;
const unsigned long kNanoSecsPerMicroSec = 1000;
// Use a timeout 3 times of the timer interval.
unsigned long duration_ns = kIntervalUSec * kNanoSecsPerMicroSec * 3;
timeout.tv_sec = duration_ns / kNanoSecsPerSec ;
timeout.tv_nsec = duration_ns % kNanoSecsPerSec;
int sig;
do {
sig = sys_sigtimedwait(&sigalarm_only, NULL, &timeout);
} while (sig == -1 && errno == EINTR);
assert(sig == kSignal);
// Disable timer, check saving of old timer value.
struct kernel_itimerval empty_itimer = {};
struct kernel_itimerval old_itimer;
empty_itimer.it_interval.tv_sec = 0;
empty_itimer.it_interval.tv_usec = 0;
empty_itimer.it_value = empty_itimer.it_interval;
assert(sys_setitimer(ITIMER_REAL, &empty_itimer, &old_itimer) == 0);
assert(kernel_timeval_eq(&old_itimer.it_interval, &new_itimer.it_interval));
return 0;
}

View file

@ -0,0 +1,54 @@
/* Copyright 2020 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
void test_handler(int sig) {}
int main(int argc, char *argv[]) {
const size_t kSigsetSize = sizeof(struct kernel_sigset_t);
struct kernel_sigaction action = {};
// Invalid signal returns EINVAL.
assert(sys_rt_sigaction(SIGKILL, &action, NULL, kSigsetSize) == -1);
assert(errno == EINVAL);
// Set an action.
action.sa_handler_ = test_handler;
action.sa_flags = SA_SIGINFO;
assert(sys_sigemptyset(&action.sa_mask) == 0);
assert(sys_sigaddset(&action.sa_mask, SIGPIPE) == 0);
assert(sys_rt_sigaction(SIGSEGV, &action, NULL, kSigsetSize) == 0);
// Retrieve the action.
struct kernel_sigaction old_action = {};
assert(sys_rt_sigaction(SIGSEGV, NULL, &old_action, kSigsetSize) == 0);
assert(memcmp(&action, &old_action, sizeof(action)) == 0);
return 0;
}

View file

@ -0,0 +1,58 @@
/* Copyright 2019 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
struct kernel_sigset_t sigset = {};
siginfo_t siginfo = {};
struct timespec timeout = {};
// Invalid timeouts.
timeout.tv_sec = -1;
assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == -1);
assert(errno == EINVAL);
// Expired timeouts.
timeout.tv_sec = 0;
assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == -1);
assert(errno == EAGAIN);
// Success.
const int kTestSignal = SIGCONT;
assert(sys_sigemptyset(&sigset) == 0);
assert(sys_sigaddset(&sigset, kTestSignal) == 0);
assert(sys_sigprocmask(SIG_BLOCK, &sigset, NULL) == 0);
assert(raise(kTestSignal) == 0);
assert(sys_sigtimedwait(&sigset, &siginfo, &timeout) == kTestSignal);
assert(siginfo.si_signo == kTestSignal);
return 0;
}

View file

@ -0,0 +1,67 @@
/* Copyright 2021 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
int exit_status = 0;
// Get two unique paths to play with.
char foo[] = "tempfile.XXXXXX";
int fd_foo = mkstemp(foo);
assert(fd_foo != -1);
// Make sure it exists.
assert(access(foo, F_OK) == 0);
// Make sure sys_stat() and a libc stat() implementation return the same
// information.
struct stat libc_stat;
assert(stat(foo, &libc_stat) == 0);
struct kernel_stat raw_stat;
// We need to check our stat syscall for EOVERFLOW, as sometimes the integer
// types used in the stat structures are too small to fit the actual value.
// E.g. on some systems st_ino is 32-bit, but some filesystems have 64-bit
// inodes.
int rc = sys_stat(foo, &raw_stat);
if (rc < 0 && errno == EOVERFLOW) {
// Bail out since we had an overflow in the stat structure.
exit_status = SKIP_TEST_EXIT_STATUS;
goto cleanup;
}
assert(rc == 0);
assert(libc_stat.st_ino == raw_stat.st_ino);
cleanup:
sys_unlink(foo);
return exit_status;
}

View file

@ -0,0 +1,89 @@
/* Copyright 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* Make sure it's defined before including anything else. A number of syscalls
* are GNU extensions and rely on being exported by glibc.
*/
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
/*
* Make sure the assert checks aren't removed as all the unittests are based
* on them.
*/
#undef NDEBUG
#include <assert.h>
#include <fcntl.h>
#include <sched.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/vfs.h>
#include <sys/wait.h>
#include <unistd.h>
#include <linux/capability.h>
#include "linux_syscall_support.h"
#define SKIP_TEST_EXIT_STATUS 77
void assert_buffers_eq_len(const void *buf1, const void *buf2, size_t len) {
const uint8_t *u8_1 = (const uint8_t *)buf1;
const uint8_t *u8_2 = (const uint8_t *)buf2;
size_t i;
for (i = 0; i < len; ++i) {
if (u8_1[i] != u8_2[i])
printf("offset %zu: %02x != %02x\n", i, u8_1[i], u8_2[i]);
}
}
#define assert_buffers_eq(obj1, obj2) assert_buffers_eq_len(obj1, obj2, sizeof(*obj1))
// Returns true iff pointed timevals are equal.
static inline bool kernel_timeval_eq(const struct kernel_timeval* lhs,
const struct kernel_timeval* rhs) {
return (lhs->tv_sec == rhs->tv_sec) && (lhs->tv_usec == rhs->tv_usec);
}
// Returns true iff pointed itimervals are equal.
static inline bool kernel_itimerval_eq(const struct kernel_itimerval* lhs,
const struct kernel_itimerval* rhs) {
return kernel_timeval_eq(&lhs->it_interval, &rhs->it_interval) &&
kernel_timeval_eq(&lhs->it_value, &rhs->it_value);
}

View file

@ -0,0 +1,48 @@
/* Copyright 2018 Google LLC
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the following disclaimer
* in the documentation and/or other materials provided with the
* distribution.
* * Neither the name of Google LLC nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "test_skel.h"
int main(int argc, char *argv[]) {
// Get a unique path to play with.
char foo[] = "tempfile.XXXXXX";
int fd = mkstemp(foo);
assert(fd != -1);
// Make sure it exists.
assert(access(foo, F_OK) == 0);
// Then delete it.
assert(sys_unlink(foo) == 0);
// Make sure it's gone.
assert(access(foo, F_OK) != 0);
return 0;
}

View file

@ -0,0 +1,25 @@
These headers were copied to enable building the Mac dump_syms code that
processes Mach-O files on Linux.
From xnu-8792.41.9 (https://github.com/apple-oss-distributions/xnu at 5c2921b)
i386/_types.h
arm/_types.h
mach/boolean.h
mach/machine.h
mach/thread_status.h
mach/vm_prot.h
mach/i386/boolean.h
mach/i386/vm_types.h
mach/arm/boolean.h
mach/arm/vm_types.h
mach/machine/boolean.h
mach/machine/vm_types.h
From cctools-986 (https://github.com/apple-oss-distributions/cctools at cbe977a)
mach-o/arch.h
mach-o/fat.h
mach-o/loader.h
mach-o/nlist.h
From architecture-282 (https://github.com/apple-oss-distributions/architecture at fe86900)
architecture/byte_order.h

View file

@ -0,0 +1,39 @@
/*
* Copyright (c) 1999-2008 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
/*
* Copyright (c) 1992 NeXT Computer, Inc.
*
* Byte ordering conversion.
*
*/
#ifndef _ARCHITECTURE_BYTE_ORDER_H_
#define _ARCHITECTURE_BYTE_ORDER_H_
enum NXByteOrder {
NX_UnknownByteOrder,
NX_LittleEndian,
NX_BigEndian
};
#endif /* _ARCHITECTURE_BYTE_ORDER_H_ */

View file

@ -0,0 +1,16 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*/
#ifndef _BSD_ARM__TYPES_H_
#define _BSD_ARM__TYPES_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
typedef long __darwin_intptr_t;
typedef unsigned int __darwin_natural_t;
#endif /* defined (__arm__) || defined (__arm64__) || defined (__aarch64__) */
#endif /* _BSD_ARM__TYPES_H_ */

View file

@ -0,0 +1,38 @@
/*
* Copyright (c) 2000-2003 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef _BSD_I386__TYPES_H_
#define _BSD_I386__TYPES_H_
#if defined (__i386__) || defined (__x86_64__)
typedef long __darwin_intptr_t;
typedef unsigned int __darwin_natural_t;
#endif /* defined (__i386__) || defined (__x86_64__) */
#endif /* _BSD_I386__TYPES_H_ */

View file

@ -0,0 +1,150 @@
/*
* Copyright (c) 1999 Apple Computer, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _MACH_O_ARCH_H_
#define _MACH_O_ARCH_H_
/*
* Copyright (c) 1997 Apple Computer, Inc.
*
* Functions that deal with information about architectures.
*
*/
#include <stdint.h>
#include <mach/machine.h>
#include <architecture/byte_order.h>
/* The NXArchInfo structs contain the architectures symbolic name
* (such as "ppc"), its CPU type and CPU subtype as defined in
* mach/machine.h, the byte order for the architecture, and a
* describing string (such as "PowerPC").
* There will both be entries for specific CPUs (such as ppc604e) as
* well as generic "family" entries (such as ppc).
*/
typedef struct {
const char *name;
cpu_type_t cputype;
cpu_subtype_t cpusubtype;
enum NXByteOrder byteorder;
const char *description;
} NXArchInfo;
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* NXGetAllArchInfos() returns a pointer to an array of all known
* NXArchInfo structures. The last NXArchInfo is marked by a NULL name.
*/
extern const NXArchInfo *NXGetAllArchInfos(void);
/* NXGetLocalArchInfo() returns the NXArchInfo for the local host, or NULL
* if none is known.
*/
extern const NXArchInfo *NXGetLocalArchInfo(void);
/* NXGetArchInfoFromName() and NXGetArchInfoFromCpuType() return the
* NXArchInfo from the architecture's name or cputype/cpusubtype
* combination. A cpusubtype of CPU_SUBTYPE_MULTIPLE can be used
* to request the most general NXArchInfo known for the given cputype.
* NULL is returned if no matching NXArchInfo can be found.
*/
extern const NXArchInfo *NXGetArchInfoFromName(const char *name);
extern const NXArchInfo *NXGetArchInfoFromCpuType(cpu_type_t cputype,
cpu_subtype_t cpusubtype);
/* The above interfaces that return pointers to NXArchInfo structs in normal
* cases returns a pointer from the array returned in NXGetAllArchInfos().
* In some cases when the cputype is CPU_TYPE_I386 or CPU_TYPE_POWERPC it will
* retun malloc(3)'ed NXArchInfo struct which contains a string in the
* description field also a malloc(3)'ed pointer. To allow programs not to
* leak memory they can call NXFreeArchInfo() on pointers returned from the
* above interfaces. Since this is a new API on older systems can use the
* code below. Going forward the above interfaces will only return pointers
* from the array returned in NXGetAllArchInfos().
*/
extern void NXFreeArchInfo(const NXArchInfo *x);
/* The code that can be used for NXFreeArchInfo() when it is not available is:
*
* static void NXFreeArchInfo(
* const NXArchInfo *x)
* {
* const NXArchInfo *p;
*
* p = NXGetAllArchInfos();
* while(p->name != NULL){
* if(x == p)
* return;
* p++;
* }
* free((char *)x->description);
* free((NXArchInfo *)x);
* }
*/
/* NXFindBestFatArch() is passed a cputype and cpusubtype and a set of
* fat_arch structs and selects the best one that matches (if any) and returns
* a pointer to that fat_arch struct (or NULL). The fat_arch structs must be
* in the host byte order and correct such that the fat_archs really points to
* enough memory for nfat_arch structs. It is possible that this routine could
* fail if new cputypes or cpusubtypes are added and an old version of this
* routine is used. But if there is an exact match between the cputype and
* cpusubtype and one of the fat_arch structs this routine will always succeed.
*/
extern struct fat_arch *NXFindBestFatArch(cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch *fat_archs,
uint32_t nfat_archs);
/* NXFindBestFatArch_64() is passed a cputype and cpusubtype and a set of
* fat_arch_64 structs and selects the best one that matches (if any) and
* returns a pointer to that fat_arch_64 struct (or NULL). The fat_arch_64
* structs must be in the host byte order and correct such that the fat_archs64
* really points to enough memory for nfat_arch structs. It is possible that
* this routine could fail if new cputypes or cpusubtypes are added and an old
* version of this routine is used. But if there is an exact match between the
* cputype and cpusubtype and one of the fat_arch_64 structs this routine will
* always succeed.
*/
extern struct fat_arch_64 *NXFindBestFatArch_64(cpu_type_t cputype,
cpu_subtype_t cpusubtype,
struct fat_arch_64 *fat_archs64,
uint32_t nfat_archs);
/* NXCombineCpuSubtypes() returns the resulting cpusubtype when combining two
* different cpusubtypes for the specified cputype. If the two cpusubtypes
* can't be combined (the specific subtypes are mutually exclusive) -1 is
* returned indicating it is an error to combine them. This can also fail and
* return -1 if new cputypes or cpusubtypes are added and an old version of
* this routine is used. But if the cpusubtypes are the same they can always
* be combined and this routine will return the cpusubtype pass in.
*/
extern cpu_subtype_t NXCombineCpuSubtypes(cpu_type_t cputype,
cpu_subtype_t cpusubtype1,
cpu_subtype_t cpusubtype2);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* _MACH_O_ARCH_H_ */

View file

@ -0,0 +1,83 @@
/*
* Copyright (c) 2016 Apple, Inc. All rights reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _MACH_O_FAT_H_
#define _MACH_O_FAT_H_
/*
* This header file describes the structures of the file format for "fat"
* architecture specific file (wrapper design). At the begining of the file
* there is one fat_header structure followed by a number of fat_arch
* structures. For each architecture in the file, specified by a pair of
* cputype and cpusubtype, the fat_header describes the file offset, file
* size and alignment in the file of the architecture specific member.
* The padded bytes in the file to place each member on it's specific alignment
* are defined to be read as zeros and can be left as "holes" if the file system
* can support them as long as they read as zeros.
*
* All structures defined here are always written and read to/from disk
* in big-endian order.
*/
/*
* <mach/machine.h> is needed here for the cpu_type_t and cpu_subtype_t types
* and contains the constants for the possible values of these types.
*/
#include <stdint.h>
#include <mach/machine.h>
#include <architecture/byte_order.h>
#define FAT_MAGIC 0xcafebabe
#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */
struct fat_header {
uint32_t magic; /* FAT_MAGIC or FAT_MAGIC_64 */
uint32_t nfat_arch; /* number of structs that follow */
};
struct fat_arch {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint32_t offset; /* file offset to this object file */
uint32_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
};
/*
* The support for the 64-bit fat file format described here is a work in
* progress and not yet fully supported in all the Apple Developer Tools.
*
* When a slice is greater than 4mb or an offset to a slice is greater than 4mb
* then the 64-bit fat file format is used.
*/
#define FAT_MAGIC_64 0xcafebabf
#define FAT_CIGAM_64 0xbfbafeca /* NXSwapLong(FAT_MAGIC_64) */
struct fat_arch_64 {
cpu_type_t cputype; /* cpu specifier (int) */
cpu_subtype_t cpusubtype; /* machine specifier (int) */
uint64_t offset; /* file offset to this object file */
uint64_t size; /* size of this object file */
uint32_t align; /* alignment as a power of 2 */
uint32_t reserved; /* reserved */
};
#endif /* _MACH_O_FAT_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,324 @@
/*
* Copyright (c) 1999-2003 Apple Computer, Inc. All Rights Reserved.
*
* @APPLE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_LICENSE_HEADER_END@
*/
#ifndef _MACHO_NLIST_H_
#define _MACHO_NLIST_H_
/* $NetBSD: nlist.h,v 1.5 1994/10/26 00:56:11 cgd Exp $ */
/*-
* Copyright (c) 1991, 1993
* The Regents of the University of California. All rights reserved.
* (c) UNIX System Laboratories, Inc.
* All or some portions of this file are derived from material licensed
* to the University of California by American Telephone and Telegraph
* Co. or Unix System Laboratories, Inc. and are reproduced herein with
* the permission of UNIX System Laboratories, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by the University of
* California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* @(#)nlist.h 8.2 (Berkeley) 1/21/94
*/
#include <stdint.h>
/*
* Format of a symbol table entry of a Mach-O file for 32-bit architectures.
* Modified from the BSD format. The modifications from the original format
* were changing n_other (an unused field) to n_sect and the addition of the
* N_SECT type. These modifications are required to support symbols in a larger
* number of sections not just the three sections (text, data and bss) in a BSD
* file.
*/
struct nlist {
union {
#ifndef __LP64__
char *n_name; /* for use when in-core */
#endif
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
int16_t n_desc; /* see <mach-o/stab.h> */
uint32_t n_value; /* value of this symbol (or stab offset) */
};
/*
* This is the symbol table entry structure for 64-bit architectures.
*/
struct nlist_64 {
union {
uint32_t n_strx; /* index into the string table */
} n_un;
uint8_t n_type; /* type flag, see below */
uint8_t n_sect; /* section number or NO_SECT */
uint16_t n_desc; /* see <mach-o/stab.h> */
uint64_t n_value; /* value of this symbol (or stab offset) */
};
/*
* Symbols with a index into the string table of zero (n_un.n_strx == 0) are
* defined to have a null, "", name. Therefore all string indexes to non null
* names must not have a zero string index. This is bit historical information
* that has never been well documented.
*/
/*
* The n_type field really contains four fields:
* unsigned char N_STAB:3,
* N_PEXT:1,
* N_TYPE:3,
* N_EXT:1;
* which are used via the following masks.
*/
#define N_STAB 0xe0 /* if any of these bits set, a symbolic debugging entry */
#define N_PEXT 0x10 /* private external symbol bit */
#define N_TYPE 0x0e /* mask for the type bits */
#define N_EXT 0x01 /* external symbol bit, set for external symbols */
/*
* Only symbolic debugging entries have some of the N_STAB bits set and if any
* of these bits are set then it is a symbolic debugging entry (a stab). In
* which case then the values of the n_type field (the entire field) are given
* in <mach-o/stab.h>
*/
/*
* Values for N_TYPE bits of the n_type field.
*/
#define N_UNDF 0x0 /* undefined, n_sect == NO_SECT */
#define N_ABS 0x2 /* absolute, n_sect == NO_SECT */
#define N_SECT 0xe /* defined in section number n_sect */
#define N_PBUD 0xc /* prebound undefined (defined in a dylib) */
#define N_INDR 0xa /* indirect */
/*
* If the type is N_INDR then the symbol is defined to be the same as another
* symbol. In this case the n_value field is an index into the string table
* of the other symbol's name. When the other symbol is defined then they both
* take on the defined type and value.
*/
/*
* If the type is N_SECT then the n_sect field contains an ordinal of the
* section the symbol is defined in. The sections are numbered from 1 and
* refer to sections in order they appear in the load commands for the file
* they are in. This means the same ordinal may very well refer to different
* sections in different files.
*
* The n_value field for all symbol table entries (including N_STAB's) gets
* updated by the link editor based on the value of it's n_sect field and where
* the section n_sect references gets relocated. If the value of the n_sect
* field is NO_SECT then it's n_value field is not changed by the link editor.
*/
#define NO_SECT 0 /* symbol is not in any section */
#define MAX_SECT 255 /* 1 thru 255 inclusive */
/*
* Common symbols are represented by undefined (N_UNDF) external (N_EXT) types
* who's values (n_value) are non-zero. In which case the value of the n_value
* field is the size (in bytes) of the common symbol. The n_sect field is set
* to NO_SECT. The alignment of a common symbol may be set as a power of 2
* between 2^1 and 2^15 as part of the n_desc field using the macros below. If
* the alignment is not set (a value of zero) then natural alignment based on
* the size is used.
*/
#define GET_COMM_ALIGN(n_desc) (((n_desc) >> 8) & 0x0f)
#define SET_COMM_ALIGN(n_desc,align) \
(n_desc) = (((n_desc) & 0xf0ff) | (((align) & 0x0f) << 8))
/*
* To support the lazy binding of undefined symbols in the dynamic link-editor,
* the undefined symbols in the symbol table (the nlist structures) are marked
* with the indication if the undefined reference is a lazy reference or
* non-lazy reference. If both a non-lazy reference and a lazy reference is
* made to the same symbol the non-lazy reference takes precedence. A reference
* is lazy only when all references to that symbol are made through a symbol
* pointer in a lazy symbol pointer section.
*
* The implementation of marking nlist structures in the symbol table for
* undefined symbols will be to use some of the bits of the n_desc field as a
* reference type. The mask REFERENCE_TYPE will be applied to the n_desc field
* of an nlist structure for an undefined symbol to determine the type of
* undefined reference (lazy or non-lazy).
*
* The constants for the REFERENCE FLAGS are propagated to the reference table
* in a shared library file. In that case the constant for a defined symbol,
* REFERENCE_FLAG_DEFINED, is also used.
*/
/* Reference type bits of the n_desc field of undefined symbols */
#define REFERENCE_TYPE 0x7
/* types of references */
#define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0
#define REFERENCE_FLAG_UNDEFINED_LAZY 1
#define REFERENCE_FLAG_DEFINED 2
#define REFERENCE_FLAG_PRIVATE_DEFINED 3
#define REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY 4
#define REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY 5
/*
* To simplify stripping of objects that use are used with the dynamic link
* editor, the static link editor marks the symbols defined an object that are
* referenced by a dynamicly bound object (dynamic shared libraries, bundles).
* With this marking strip knows not to strip these symbols.
*/
#define REFERENCED_DYNAMICALLY 0x0010
/*
* For images created by the static link editor with the -twolevel_namespace
* option in effect the flags field of the mach header is marked with
* MH_TWOLEVEL. And the binding of the undefined references of the image are
* determined by the static link editor. Which library an undefined symbol is
* bound to is recorded by the static linker in the high 8 bits of the n_desc
* field using the SET_LIBRARY_ORDINAL macro below. The ordinal recorded
* references the libraries listed in the Mach-O's LC_LOAD_DYLIB,
* LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LOAD_UPWARD_DYLIB, and
* LC_LAZY_LOAD_DYLIB, etc. load commands in the order they appear in the
* headers. The library ordinals start from 1.
* For a dynamic library that is built as a two-level namespace image the
* undefined references from module defined in another use the same nlist struct
* an in that case SELF_LIBRARY_ORDINAL is used as the library ordinal. For
* defined symbols in all images they also must have the library ordinal set to
* SELF_LIBRARY_ORDINAL. The EXECUTABLE_ORDINAL refers to the executable
* image for references from plugins that refer to the executable that loads
* them.
*
* The DYNAMIC_LOOKUP_ORDINAL is for undefined symbols in a two-level namespace
* image that are looked up by the dynamic linker with flat namespace semantics.
* This ordinal was added as a feature in Mac OS X 10.3 by reducing the
* value of MAX_LIBRARY_ORDINAL by one. So it is legal for existing binaries
* or binaries built with older tools to have 0xfe (254) dynamic libraries. In
* this case the ordinal value 0xfe (254) must be treated as a library ordinal
* for compatibility.
*/
#define GET_LIBRARY_ORDINAL(n_desc) (((n_desc) >> 8) & 0xff)
#define SET_LIBRARY_ORDINAL(n_desc,ordinal) \
(n_desc) = (((n_desc) & 0x00ff) | (((ordinal) & 0xff) << 8))
#define SELF_LIBRARY_ORDINAL 0x0
#define MAX_LIBRARY_ORDINAL 0xfd
#define DYNAMIC_LOOKUP_ORDINAL 0xfe
#define EXECUTABLE_ORDINAL 0xff
/*
* The bit 0x0020 of the n_desc field is used for two non-overlapping purposes
* and has two different symbolic names, N_NO_DEAD_STRIP and N_DESC_DISCARDED.
*/
/*
* The N_NO_DEAD_STRIP bit of the n_desc field only ever appears in a
* relocatable .o file (MH_OBJECT filetype). And is used to indicate to the
* static link editor it is never to dead strip the symbol.
*/
#define N_NO_DEAD_STRIP 0x0020 /* symbol is not to be dead stripped */
/*
* The N_DESC_DISCARDED bit of the n_desc field never appears in linked image.
* But is used in very rare cases by the dynamic link editor to mark an in
* memory symbol as discared and longer used for linking.
*/
#define N_DESC_DISCARDED 0x0020 /* symbol is discarded */
/*
* The N_WEAK_REF bit of the n_desc field indicates to the dynamic linker that
* the undefined symbol is allowed to be missing and is to have the address of
* zero when missing.
*/
#define N_WEAK_REF 0x0040 /* symbol is weak referenced */
/*
* The N_WEAK_DEF bit of the n_desc field indicates to the static and dynamic
* linkers that the symbol definition is weak, allowing a non-weak symbol to
* also be used which causes the weak definition to be discared. Currently this
* is only supported for symbols in coalesed sections.
*/
#define N_WEAK_DEF 0x0080 /* coalesed symbol is a weak definition */
/*
* The N_REF_TO_WEAK bit of the n_desc field indicates to the dynamic linker
* that the undefined symbol should be resolved using flat namespace searching.
*/
#define N_REF_TO_WEAK 0x0080 /* reference to a weak symbol */
/*
* The N_ARM_THUMB_DEF bit of the n_desc field indicates that the symbol is
* a defintion of a Thumb function.
*/
#define N_ARM_THUMB_DEF 0x0008 /* symbol is a Thumb function (ARM) */
/*
* The N_SYMBOL_RESOLVER bit of the n_desc field indicates that the
* that the function is actually a resolver function and should
* be called to get the address of the real function to use.
* This bit is only available in .o files (MH_OBJECT filetype)
*/
#define N_SYMBOL_RESOLVER 0x0100
/*
* The N_ALT_ENTRY bit of the n_desc field indicates that the
* symbol is pinned to the previous content.
*/
#define N_ALT_ENTRY 0x0200
/*
* The N_COLD_FUNC bit of the n_desc field indicates that the symbol is used
* infrequently and the linker should order it towards the end of the section.
*/
#define N_COLD_FUNC 0x0400
#ifndef __STRICT_BSD__
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* The function nlist(3) from the C library.
*/
extern int nlist (const char *filename, struct nlist *list);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __STRICT_BSD__ */
#endif /* _MACHO_LIST_H_ */

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: boolean.h
*
* Boolean type, for ARM.
*/
#ifndef _MACH_ARM_BOOLEAN_H_
#define _MACH_ARM_BOOLEAN_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
typedef int boolean_t;
#endif /* defined (__arm__) || defined (__arm64__) */
#endif /* _MACH_ARM_BOOLEAN_H_ */

View file

@ -0,0 +1,159 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: vm_types.h
* Author: Avadis Tevanian, Jr.
* Date: 1985
*
* Header file for VM data types. ARM version.
*/
#ifndef _MACH_ARM_VM_TYPES_H_
#define _MACH_ARM_VM_TYPES_H_
#if defined (__arm__) || defined (__arm64__) || defined (__aarch64__)
#ifndef ASSEMBLER
#include <arm/_types.h>
#include <stdint.h>
#include <sys/cdefs.h>
/*
* natural_t and integer_t are Mach's legacy types for machine-
* independent integer types (unsigned, and signed, respectively).
* Their original purpose was to define other types in a machine/
* compiler independent way.
*
* They also had an implicit "same size as pointer" characteristic
* to them (i.e. Mach's traditional types are very ILP32 or ILP64
* centric). We will likely support x86 ABIs that do not follow
* either ofthese models (specifically LP64). Therefore, we had to
* make a choice between making these types scale with pointers or stay
* tied to integers. Because their use is predominantly tied to
* to the size of an integer, we are keeping that association and
* breaking free from pointer size guarantees.
*
* New use of these types is discouraged.
*/
typedef __darwin_natural_t natural_t;
typedef int integer_t;
/*
* A vm_offset_t is a type-neutral pointer,
* e.g. an offset into a virtual memory space.
*/
#ifdef __LP64__
typedef uintptr_t vm_offset_t ;
typedef uintptr_t vm_size_t;
typedef uint64_t mach_vm_address_t ;
typedef uint64_t mach_vm_offset_t ;
typedef uint64_t mach_vm_size_t;
typedef uint64_t vm_map_offset_t ;
typedef uint64_t vm_map_address_t ;
typedef uint64_t vm_map_size_t;
#else
typedef natural_t vm_offset_t ;
/*
* A vm_size_t is the proper type for e.g.
* expressing the difference between two
* vm_offset_t entities.
*/
typedef natural_t vm_size_t;
/*
* This new type is independent of a particular vm map's
* implementation size - and represents appropriate types
* for all possible maps. This is used for interfaces
* where the size of the map is not known - or we don't
* want to have to distinguish.
*/
typedef uint64_t mach_vm_address_t ;
typedef uint64_t mach_vm_offset_t ;
typedef uint64_t mach_vm_size_t;
typedef uint32_t vm_map_offset_t ;
typedef uint32_t vm_map_address_t ;
typedef uint32_t vm_map_size_t;
#endif /* __LP64__ */
typedef uint32_t vm32_offset_t;
typedef uint32_t vm32_address_t;
typedef uint32_t vm32_size_t;
typedef vm_offset_t mach_port_context_t;
#ifdef MACH_KERNEL_PRIVATE
typedef vm32_offset_t mach_port_context32_t;
typedef mach_vm_offset_t mach_port_context64_t;
#endif
#endif /* ASSEMBLER */
/*
* If composing messages by hand (please do not)
*/
#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32
#endif /* defined (__arm__) || defined (__arm64__) || defined (__aarch64__) */
#endif /* _MACH_ARM_VM_TYPES_H_ */

View file

@ -0,0 +1,88 @@
/*
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: mach/boolean.h
*
* Boolean data type.
*
*/
#ifndef _MACH_BOOLEAN_H_
#define _MACH_BOOLEAN_H_
/*
* Pick up "boolean_t" type definition
*/
#ifndef ASSEMBLER
#include <mach/machine/boolean.h>
#endif /* ASSEMBLER */
/*
* Define TRUE and FALSE if not defined.
*/
#ifndef TRUE
#define TRUE 1
#endif /* TRUE */
#ifndef FALSE
#define FALSE 0
#endif /* FALSE */
#endif /* _MACH_BOOLEAN_H_ */

View file

@ -0,0 +1,78 @@
/*
* Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: boolean.h
*
* Boolean type, for I386.
*/
#ifndef _MACH_I386_BOOLEAN_H_
#define _MACH_I386_BOOLEAN_H_
#if defined (__i386__) || defined (__x86_64__)
#if defined(__x86_64__) && !defined(KERNEL)
typedef unsigned int boolean_t;
#else
typedef int boolean_t;
#endif
#endif /* defined (__i386__) || defined (__x86_64__) */
#endif /* _MACH_I386_BOOLEAN_H_ */

View file

@ -0,0 +1,157 @@
/*
* Copyright (c) 2000-2016 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: vm_types.h
* Author: Avadis Tevanian, Jr.
* Date: 1985
*
* Header file for VM data types. I386 version.
*/
#ifndef _MACH_I386_VM_TYPES_H_
#define _MACH_I386_VM_TYPES_H_
#if defined (__i386__) || defined (__x86_64__)
#ifndef ASSEMBLER
#include <i386/_types.h>
#include <stdint.h>
#include <sys/cdefs.h>
/*
* natural_t and integer_t are Mach's legacy types for machine-
* independent integer types (unsigned, and signed, respectively).
* Their original purpose was to define other types in a machine/
* compiler independent way.
*
* They also had an implicit "same size as pointer" characteristic
* to them (i.e. Mach's traditional types are very ILP32 or ILP64
* centric). We support x86 ABIs that do not follow either of
* these models (specifically LP64). Therefore, we had to make a
* choice between making these types scale with pointers or stay
* tied to integers. Because their use is predominantly tied to
* to the size of an integer, we are keeping that association and
* breaking free from pointer size guarantees.
*
* New use of these types is discouraged.
*/
typedef __darwin_natural_t natural_t;
typedef int integer_t;
/*
* A vm_offset_t is a type-neutral pointer,
* e.g. an offset into a virtual memory space.
*/
#ifdef __LP64__
typedef uintptr_t vm_offset_t ;
#else /* __LP64__ */
typedef natural_t vm_offset_t ;
#endif /* __LP64__ */
/*
* A vm_size_t is the proper type for e.g.
* expressing the difference between two
* vm_offset_t entities.
*/
#ifdef __LP64__
typedef uintptr_t vm_size_t;
#else /* __LP64__ */
typedef natural_t vm_size_t;
#endif /* __LP64__ */
/*
* This new type is independent of a particular vm map's
* implementation size - and represents appropriate types
* for all possible maps. This is used for interfaces
* where the size of the map is not known - or we don't
* want to have to distinguish.
*/
typedef uint64_t mach_vm_address_t ;
typedef uint64_t mach_vm_offset_t ;
typedef uint64_t mach_vm_size_t;
typedef uint64_t vm_map_offset_t ;
typedef uint64_t vm_map_address_t ;
typedef uint64_t vm_map_size_t;
typedef mach_vm_address_t mach_port_context_t;
#ifdef MACH_KERNEL_PRIVATE
/*
* These are types used internal to Mach to implement the
* legacy 32-bit VM APIs published by the kernel.
*/
typedef uint32_t vm32_address_t;
typedef uint32_t vm32_offset_t;
typedef uint32_t vm32_size_t;
#endif /* MACH_KERNEL_PRIVATE */
#endif /* ASSEMBLER */
/*
* If composing messages by hand (please do not)
*/
#define MACH_MSG_TYPE_INTEGER_T MACH_MSG_TYPE_INTEGER_32
#endif /* defined (__i386__) || defined (__x86_64__) */
#endif /* _MACH_I386_VM_TYPES_H_ */

View file

@ -0,0 +1,461 @@
/*
* Copyright (c) 2007-2016 Apple, Inc. All rights reserved.
* Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/* File: machine.h
* Author: Avadis Tevanian, Jr.
* Date: 1986
*
* Machine independent machine abstraction.
*/
#ifndef _MACH_MACHINE_H_
#define _MACH_MACHINE_H_
#ifndef __ASSEMBLER__
#include <stdint.h>
#include <mach/machine/vm_types.h>
#include <mach/boolean.h>
typedef integer_t cpu_type_t;
typedef integer_t cpu_subtype_t;
typedef integer_t cpu_threadtype_t;
#define CPU_STATE_MAX 4
#define CPU_STATE_USER 0
#define CPU_STATE_SYSTEM 1
#define CPU_STATE_IDLE 2
#define CPU_STATE_NICE 3
#ifdef KERNEL_PRIVATE
#include <sys/cdefs.h>
__BEGIN_DECLS
cpu_type_t cpu_type(void);
cpu_subtype_t cpu_subtype(void);
cpu_threadtype_t cpu_threadtype(void);
__END_DECLS
#ifdef MACH_KERNEL_PRIVATE
struct machine_info {
integer_t major_version; /* kernel major version id */
integer_t minor_version; /* kernel minor version id */
integer_t max_cpus; /* max number of CPUs possible */
uint32_t memory_size; /* size of memory in bytes, capped at 2 GB */
uint64_t max_mem; /* actual size of physical memory */
uint32_t physical_cpu; /* number of physical CPUs now available */
integer_t physical_cpu_max; /* max number of physical CPUs possible */
uint32_t logical_cpu; /* number of logical cpu now available */
integer_t logical_cpu_max; /* max number of physical CPUs possible */
};
typedef struct machine_info *machine_info_t;
typedef struct machine_info machine_info_data_t;
extern struct machine_info machine_info;
__BEGIN_DECLS
cpu_type_t slot_type(
int slot_num);
cpu_subtype_t slot_subtype(
int slot_num);
cpu_threadtype_t slot_threadtype(
int slot_num);
__END_DECLS
#endif /* MACH_KERNEL_PRIVATE */
#endif /* KERNEL_PRIVATE */
/*
* Capability bits used in the definition of cpu_type.
*/
#define CPU_ARCH_MASK 0xff000000 /* mask for architecture bits */
#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */
#define CPU_ARCH_ABI64_32 0x02000000 /* ABI for 64-bit hardware with 32-bit types; LP32 */
/*
* Machine types known by all.
*/
#define CPU_TYPE_ANY ((cpu_type_t) -1)
#define CPU_TYPE_VAX ((cpu_type_t) 1)
/* skip ((cpu_type_t) 2) */
/* skip ((cpu_type_t) 3) */
/* skip ((cpu_type_t) 4) */
/* skip ((cpu_type_t) 5) */
#define CPU_TYPE_MC680x0 ((cpu_type_t) 6)
#define CPU_TYPE_X86 ((cpu_type_t) 7)
#define CPU_TYPE_I386 CPU_TYPE_X86 /* compatibility */
#define CPU_TYPE_X86_64 (CPU_TYPE_X86 | CPU_ARCH_ABI64)
/* skip CPU_TYPE_MIPS ((cpu_type_t) 8) */
/* skip ((cpu_type_t) 9) */
#define CPU_TYPE_MC98000 ((cpu_type_t) 10)
#define CPU_TYPE_HPPA ((cpu_type_t) 11)
#define CPU_TYPE_ARM ((cpu_type_t) 12)
#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64)
#define CPU_TYPE_ARM64_32 (CPU_TYPE_ARM | CPU_ARCH_ABI64_32)
#define CPU_TYPE_MC88000 ((cpu_type_t) 13)
#define CPU_TYPE_SPARC ((cpu_type_t) 14)
#define CPU_TYPE_I860 ((cpu_type_t) 15)
/* skip CPU_TYPE_ALPHA ((cpu_type_t) 16) */
/* skip ((cpu_type_t) 17) */
#define CPU_TYPE_POWERPC ((cpu_type_t) 18)
#define CPU_TYPE_POWERPC64 (CPU_TYPE_POWERPC | CPU_ARCH_ABI64)
/* skip ((cpu_type_t) 19) */
/* skip ((cpu_type_t) 20 */
/* skip ((cpu_type_t) 21 */
/* skip ((cpu_type_t) 22 */
/* skip ((cpu_type_t) 23 */
/*
* Machine subtypes (these are defined here, instead of in a machine
* dependent directory, so that any program can get all definitions
* regardless of where is it compiled).
*/
/*
* Capability bits used in the definition of cpu_subtype.
*/
#define CPU_SUBTYPE_MASK 0xff000000 /* mask for feature flags */
#define CPU_SUBTYPE_LIB64 0x80000000 /* 64 bit libraries */
#define CPU_SUBTYPE_PTRAUTH_ABI 0x80000000 /* pointer authentication with versioned ABI */
/*
* When selecting a slice, ANY will pick the slice with the best
* grading for the selected cpu_type_t, unlike the "ALL" subtypes,
* which are the slices that can run on any hardware for that cpu type.
*/
#define CPU_SUBTYPE_ANY ((cpu_subtype_t) -1)
/*
* Object files that are hand-crafted to run on any
* implementation of an architecture are tagged with
* CPU_SUBTYPE_MULTIPLE. This functions essentially the same as
* the "ALL" subtype of an architecture except that it allows us
* to easily find object files that may need to be modified
* whenever a new implementation of an architecture comes out.
*
* It is the responsibility of the implementor to make sure the
* software handles unsupported implementations elegantly.
*/
#define CPU_SUBTYPE_MULTIPLE ((cpu_subtype_t) -1)
#define CPU_SUBTYPE_LITTLE_ENDIAN ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_BIG_ENDIAN ((cpu_subtype_t) 1)
/*
* Machine threadtypes.
* This is none - not defined - for most machine types/subtypes.
*/
#define CPU_THREADTYPE_NONE ((cpu_threadtype_t) 0)
/*
* VAX subtypes (these do *not* necessary conform to the actual cpu
* ID assigned by DEC available via the SID register).
*/
#define CPU_SUBTYPE_VAX_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_VAX780 ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_VAX785 ((cpu_subtype_t) 2)
#define CPU_SUBTYPE_VAX750 ((cpu_subtype_t) 3)
#define CPU_SUBTYPE_VAX730 ((cpu_subtype_t) 4)
#define CPU_SUBTYPE_UVAXI ((cpu_subtype_t) 5)
#define CPU_SUBTYPE_UVAXII ((cpu_subtype_t) 6)
#define CPU_SUBTYPE_VAX8200 ((cpu_subtype_t) 7)
#define CPU_SUBTYPE_VAX8500 ((cpu_subtype_t) 8)
#define CPU_SUBTYPE_VAX8600 ((cpu_subtype_t) 9)
#define CPU_SUBTYPE_VAX8650 ((cpu_subtype_t) 10)
#define CPU_SUBTYPE_VAX8800 ((cpu_subtype_t) 11)
#define CPU_SUBTYPE_UVAXIII ((cpu_subtype_t) 12)
/*
* 680x0 subtypes
*
* The subtype definitions here are unusual for historical reasons.
* NeXT used to consider 68030 code as generic 68000 code. For
* backwards compatability:
*
* CPU_SUBTYPE_MC68030 symbol has been preserved for source code
* compatability.
*
* CPU_SUBTYPE_MC680x0_ALL has been defined to be the same
* subtype as CPU_SUBTYPE_MC68030 for binary comatability.
*
* CPU_SUBTYPE_MC68030_ONLY has been added to allow new object
* files to be tagged as containing 68030-specific instructions.
*/
#define CPU_SUBTYPE_MC680x0_ALL ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_MC68030 ((cpu_subtype_t) 1) /* compat */
#define CPU_SUBTYPE_MC68040 ((cpu_subtype_t) 2)
#define CPU_SUBTYPE_MC68030_ONLY ((cpu_subtype_t) 3)
/*
* I386 subtypes
*/
#define CPU_SUBTYPE_INTEL(f, m) ((cpu_subtype_t) (f) + ((m) << 4))
#define CPU_SUBTYPE_I386_ALL CPU_SUBTYPE_INTEL(3, 0)
#define CPU_SUBTYPE_386 CPU_SUBTYPE_INTEL(3, 0)
#define CPU_SUBTYPE_486 CPU_SUBTYPE_INTEL(4, 0)
#define CPU_SUBTYPE_486SX CPU_SUBTYPE_INTEL(4, 8) // 8 << 4 = 128
#define CPU_SUBTYPE_586 CPU_SUBTYPE_INTEL(5, 0)
#define CPU_SUBTYPE_PENT CPU_SUBTYPE_INTEL(5, 0)
#define CPU_SUBTYPE_PENTPRO CPU_SUBTYPE_INTEL(6, 1)
#define CPU_SUBTYPE_PENTII_M3 CPU_SUBTYPE_INTEL(6, 3)
#define CPU_SUBTYPE_PENTII_M5 CPU_SUBTYPE_INTEL(6, 5)
#define CPU_SUBTYPE_CELERON CPU_SUBTYPE_INTEL(7, 6)
#define CPU_SUBTYPE_CELERON_MOBILE CPU_SUBTYPE_INTEL(7, 7)
#define CPU_SUBTYPE_PENTIUM_3 CPU_SUBTYPE_INTEL(8, 0)
#define CPU_SUBTYPE_PENTIUM_3_M CPU_SUBTYPE_INTEL(8, 1)
#define CPU_SUBTYPE_PENTIUM_3_XEON CPU_SUBTYPE_INTEL(8, 2)
#define CPU_SUBTYPE_PENTIUM_M CPU_SUBTYPE_INTEL(9, 0)
#define CPU_SUBTYPE_PENTIUM_4 CPU_SUBTYPE_INTEL(10, 0)
#define CPU_SUBTYPE_PENTIUM_4_M CPU_SUBTYPE_INTEL(10, 1)
#define CPU_SUBTYPE_ITANIUM CPU_SUBTYPE_INTEL(11, 0)
#define CPU_SUBTYPE_ITANIUM_2 CPU_SUBTYPE_INTEL(11, 1)
#define CPU_SUBTYPE_XEON CPU_SUBTYPE_INTEL(12, 0)
#define CPU_SUBTYPE_XEON_MP CPU_SUBTYPE_INTEL(12, 1)
#define CPU_SUBTYPE_INTEL_FAMILY(x) ((x) & 15)
#define CPU_SUBTYPE_INTEL_FAMILY_MAX 15
#define CPU_SUBTYPE_INTEL_MODEL(x) ((x) >> 4)
#define CPU_SUBTYPE_INTEL_MODEL_ALL 0
/*
* X86 subtypes.
*/
#define CPU_SUBTYPE_X86_ALL ((cpu_subtype_t)3)
#define CPU_SUBTYPE_X86_64_ALL ((cpu_subtype_t)3)
#define CPU_SUBTYPE_X86_ARCH1 ((cpu_subtype_t)4)
#define CPU_SUBTYPE_X86_64_H ((cpu_subtype_t)8) /* Haswell feature subset */
#define CPU_THREADTYPE_INTEL_HTT ((cpu_threadtype_t) 1)
/*
* Mips subtypes.
*/
#define CPU_SUBTYPE_MIPS_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_MIPS_R2300 ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_MIPS_R2600 ((cpu_subtype_t) 2)
#define CPU_SUBTYPE_MIPS_R2800 ((cpu_subtype_t) 3)
#define CPU_SUBTYPE_MIPS_R2000a ((cpu_subtype_t) 4) /* pmax */
#define CPU_SUBTYPE_MIPS_R2000 ((cpu_subtype_t) 5)
#define CPU_SUBTYPE_MIPS_R3000a ((cpu_subtype_t) 6) /* 3max */
#define CPU_SUBTYPE_MIPS_R3000 ((cpu_subtype_t) 7)
/*
* MC98000 (PowerPC) subtypes
*/
#define CPU_SUBTYPE_MC98000_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_MC98601 ((cpu_subtype_t) 1)
/*
* HPPA subtypes for Hewlett-Packard HP-PA family of
* risc processors. Port by NeXT to 700 series.
*/
#define CPU_SUBTYPE_HPPA_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_HPPA_7100 ((cpu_subtype_t) 0) /* compat */
#define CPU_SUBTYPE_HPPA_7100LC ((cpu_subtype_t) 1)
/*
* MC88000 subtypes.
*/
#define CPU_SUBTYPE_MC88000_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_MC88100 ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_MC88110 ((cpu_subtype_t) 2)
/*
* SPARC subtypes
*/
#define CPU_SUBTYPE_SPARC_ALL ((cpu_subtype_t) 0)
/*
* I860 subtypes
*/
#define CPU_SUBTYPE_I860_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_I860_860 ((cpu_subtype_t) 1)
/*
* PowerPC subtypes
*/
#define CPU_SUBTYPE_POWERPC_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_POWERPC_601 ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_POWERPC_602 ((cpu_subtype_t) 2)
#define CPU_SUBTYPE_POWERPC_603 ((cpu_subtype_t) 3)
#define CPU_SUBTYPE_POWERPC_603e ((cpu_subtype_t) 4)
#define CPU_SUBTYPE_POWERPC_603ev ((cpu_subtype_t) 5)
#define CPU_SUBTYPE_POWERPC_604 ((cpu_subtype_t) 6)
#define CPU_SUBTYPE_POWERPC_604e ((cpu_subtype_t) 7)
#define CPU_SUBTYPE_POWERPC_620 ((cpu_subtype_t) 8)
#define CPU_SUBTYPE_POWERPC_750 ((cpu_subtype_t) 9)
#define CPU_SUBTYPE_POWERPC_7400 ((cpu_subtype_t) 10)
#define CPU_SUBTYPE_POWERPC_7450 ((cpu_subtype_t) 11)
#define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
/*
* ARM subtypes
*/
#define CPU_SUBTYPE_ARM_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_ARM_V4T ((cpu_subtype_t) 5)
#define CPU_SUBTYPE_ARM_V6 ((cpu_subtype_t) 6)
#define CPU_SUBTYPE_ARM_V5TEJ ((cpu_subtype_t) 7)
#define CPU_SUBTYPE_ARM_XSCALE ((cpu_subtype_t) 8)
#define CPU_SUBTYPE_ARM_V7 ((cpu_subtype_t) 9) /* ARMv7-A and ARMv7-R */
#define CPU_SUBTYPE_ARM_V7F ((cpu_subtype_t) 10) /* Cortex A9 */
#define CPU_SUBTYPE_ARM_V7S ((cpu_subtype_t) 11) /* Swift */
#define CPU_SUBTYPE_ARM_V7K ((cpu_subtype_t) 12)
#define CPU_SUBTYPE_ARM_V8 ((cpu_subtype_t) 13)
#define CPU_SUBTYPE_ARM_V6M ((cpu_subtype_t) 14) /* Not meant to be run under xnu */
#define CPU_SUBTYPE_ARM_V7M ((cpu_subtype_t) 15) /* Not meant to be run under xnu */
#define CPU_SUBTYPE_ARM_V7EM ((cpu_subtype_t) 16) /* Not meant to be run under xnu */
#define CPU_SUBTYPE_ARM_V8M ((cpu_subtype_t) 17) /* Not meant to be run under xnu */
/*
* ARM64 subtypes
*/
#define CPU_SUBTYPE_ARM64_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_ARM64_V8 ((cpu_subtype_t) 1)
#define CPU_SUBTYPE_ARM64E ((cpu_subtype_t) 2)
/* CPU subtype feature flags for ptrauth on arm64e platforms */
#define CPU_SUBTYPE_ARM64_PTR_AUTH_MASK 0x0f000000
#define CPU_SUBTYPE_ARM64_PTR_AUTH_VERSION(x) (((x) & CPU_SUBTYPE_ARM64_PTR_AUTH_MASK) >> 24)
#ifdef PRIVATE
#define CPU_SUBTYPE_ARM64_PTR_AUTH_CURRENT_VERSION 0
#endif /* PRIVATE */
/*
* ARM64_32 subtypes
*/
#define CPU_SUBTYPE_ARM64_32_ALL ((cpu_subtype_t) 0)
#define CPU_SUBTYPE_ARM64_32_V8 ((cpu_subtype_t) 1)
#endif /* !__ASSEMBLER__ */
/*
* CPU families (sysctl hw.cpufamily)
*
* These are meant to identify the CPU's marketing name - an
* application can map these to (possibly) localized strings.
* NB: the encodings of the CPU families are intentionally arbitrary.
* There is no ordering, and you should never try to deduce whether
* or not some feature is available based on the family.
* Use feature flags (eg, hw.optional.altivec) to test for optional
* functionality.
*/
#define CPUFAMILY_UNKNOWN 0
#define CPUFAMILY_POWERPC_G3 0xcee41549
#define CPUFAMILY_POWERPC_G4 0x77c184ae
#define CPUFAMILY_POWERPC_G5 0xed76d8aa
#define CPUFAMILY_INTEL_6_13 0xaa33392b
#define CPUFAMILY_INTEL_PENRYN 0x78ea4fbc
#define CPUFAMILY_INTEL_NEHALEM 0x6b5a4cd2
#define CPUFAMILY_INTEL_WESTMERE 0x573b5eec
#define CPUFAMILY_INTEL_SANDYBRIDGE 0x5490b78c
#define CPUFAMILY_INTEL_IVYBRIDGE 0x1f65e835
#define CPUFAMILY_INTEL_HASWELL 0x10b282dc
#define CPUFAMILY_INTEL_BROADWELL 0x582ed09c
#define CPUFAMILY_INTEL_SKYLAKE 0x37fc219f
#define CPUFAMILY_INTEL_KABYLAKE 0x0f817246
#define CPUFAMILY_INTEL_ICELAKE 0x38435547
#define CPUFAMILY_ARM_9 0xe73283ae
#define CPUFAMILY_ARM_11 0x8ff620d8
#define CPUFAMILY_ARM_XSCALE 0x53b005f5
#define CPUFAMILY_ARM_12 0xbd1b0ae9
#define CPUFAMILY_ARM_13 0x0cc90e64
#define CPUFAMILY_ARM_14 0x96077ef1
#define CPUFAMILY_ARM_15 0xa8511bca
#define CPUFAMILY_ARM_SWIFT 0x1e2d6381
#define CPUFAMILY_ARM_CYCLONE 0x37a09642
#define CPUFAMILY_ARM_TYPHOON 0x2c91a47e
#define CPUFAMILY_ARM_TWISTER 0x92fb37c8
#define CPUFAMILY_ARM_HURRICANE 0x67ceee93
#define CPUFAMILY_ARM_MONSOON_MISTRAL 0xe81e7ef6
#define CPUFAMILY_ARM_VORTEX_TEMPEST 0x07d34b9f
#define CPUFAMILY_ARM_LIGHTNING_THUNDER 0x462504d2
#ifndef RC_HIDE_XNU_FIRESTORM
#define CPUFAMILY_ARM_FIRESTORM_ICESTORM 0x1b588bb3
#endif /* !RC_HIDE_XNU_FIRESTORM */
/* Described in rdar://64125549 */
#define CPUSUBFAMILY_UNKNOWN 0
#define CPUSUBFAMILY_ARM_HP 1
#define CPUSUBFAMILY_ARM_HG 2
#define CPUSUBFAMILY_ARM_M 3
#ifndef RC_HIDE_XNU_FIRESTORM
#define CPUSUBFAMILY_ARM_HS 4
#define CPUSUBFAMILY_ARM_HC_HD 5
#endif /* !RC_HIDE_XNU_FIRESTORM */
/* The following synonyms are deprecated: */
#define CPUFAMILY_INTEL_6_23 CPUFAMILY_INTEL_PENRYN
#define CPUFAMILY_INTEL_6_26 CPUFAMILY_INTEL_NEHALEM
#endif /* _MACH_MACHINE_H_ */

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef _MACH_MACHINE_BOOLEAN_H_
#define _MACH_MACHINE_BOOLEAN_H_
#if defined (__i386__) || defined(__x86_64__)
#include "mach/i386/boolean.h"
#elif defined (__arm__) || defined (__arm64__) || defined(__aarch64__)
#include "mach/arm/boolean.h"
#else
#error architecture not supported
#endif
#endif /* _MACH_MACHINE_BOOLEAN_H_ */

View file

@ -0,0 +1,9 @@
/*
* This file is a stub with the bare minimum needed to make things work.
*/
#ifndef _MACH_MACHINE_THREAD_STATE_H_
#define _MACH_MACHINE_THREAD_STATE_H_
#define THREAD_STATE_MAX 1
#endif /* _MACH_MACHINE_THREAD_STATE_H_ */

View file

@ -0,0 +1 @@
/* This file intentionally left blank */

View file

@ -0,0 +1,40 @@
/*
* Copyright (c) 2000-2007 Apple Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
#ifndef _MACH_MACHINE_VM_TYPES_H_
#define _MACH_MACHINE_VM_TYPES_H_
#if defined (__i386__) || defined(__x86_64__)
#include "mach/i386/vm_types.h"
#elif defined (__arm__) || defined (__arm64__) || defined(__aarch64__)
#include "mach/arm/vm_types.h"
#else
#error architecture not supported
#endif
#endif /* _MACH_MACHINE_VM_TYPES_H_ */

View file

@ -0,0 +1,100 @@
/*
* Copyright (c) 2000-2002 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: mach/thread_status.h
* Author: Avadis Tevanian, Jr.
*
* This file contains the structure definitions for the user-visible
* thread state. This thread state is examined with the thread_get_state
* kernel call and may be changed with the thread_set_state kernel call.
*
*/
#ifndef _MACH_THREAD_STATUS_H_
#define _MACH_THREAD_STATUS_H_
/*
* The actual structure that comprises the thread state is defined
* in the machine dependent module.
*/
#include <mach/machine/vm_types.h>
#include <mach/machine/thread_status.h>
#include <mach/machine/thread_state.h>
/*
* Generic definition for machine-dependent thread status.
*/
typedef natural_t *thread_state_t; /* Variable-length array */
/* THREAD_STATE_MAX is now defined in <mach/machine/thread_state.h> */
typedef natural_t thread_state_data_t[THREAD_STATE_MAX];
#define THREAD_STATE_FLAVOR_LIST 0 /* List of valid flavors */
#define THREAD_STATE_FLAVOR_LIST_NEW 128
#define THREAD_STATE_FLAVOR_LIST_10_9 129
#define THREAD_STATE_FLAVOR_LIST_10_13 130
#define THREAD_STATE_FLAVOR_LIST_10_15 131
typedef int thread_state_flavor_t;
typedef thread_state_flavor_t *thread_state_flavor_array_t;
#define THREAD_CONVERT_THREAD_STATE_TO_SELF 1
#define THREAD_CONVERT_THREAD_STATE_FROM_SELF 2
#endif /* _MACH_THREAD_STATUS_H_ */

View file

@ -0,0 +1,193 @@
/*
* Copyright (c) 2000-2021 Apple Computer, Inc. All rights reserved.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apple Public Source License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. The rights granted to you under the License
* may not be used to create, or enable the creation or redistribution of,
* unlawful or unlicensed copies of an Apple operating system, or to
* circumvent, violate, or enable the circumvention or violation of, any
* terms of an Apple operating system software license agreement.
*
* Please obtain a copy of the License at
* http://www.opensource.apple.com/apsl/ and read it before using this file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPLE_OSREFERENCE_LICENSE_HEADER_END@
*/
/*
* @OSF_COPYRIGHT@
*/
/*
* Mach Operating System
* Copyright (c) 1991,1990,1989,1988,1987 Carnegie Mellon University
* All Rights Reserved.
*
* Permission to use, copy, modify and distribute this software and its
* documentation is hereby granted, provided that both the copyright
* notice and this permission notice appear in all copies of the
* software, derivative works or modified versions, and any portions
* thereof, and that both notices appear in supporting documentation.
*
* CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
*
* Carnegie Mellon requests users of this software to return to
*
* Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
* School of Computer Science
* Carnegie Mellon University
* Pittsburgh PA 15213-3890
*
* any improvements or extensions that they make and grant Carnegie Mellon
* the rights to redistribute these changes.
*/
/*
*/
/*
* File: mach/vm_prot.h
* Author: Avadis Tevanian, Jr., Michael Wayne Young
*
* Virtual memory protection definitions.
*
*/
#ifndef _MACH_VM_PROT_H_
#define _MACH_VM_PROT_H_
/*
* Types defined:
*
* vm_prot_t VM protection values.
*/
typedef int vm_prot_t;
/*
* Protection values, defined as bits within the vm_prot_t type
*/
#define VM_PROT_NONE ((vm_prot_t) 0x00)
#define VM_PROT_READ ((vm_prot_t) 0x01) /* read permission */
#define VM_PROT_WRITE ((vm_prot_t) 0x02) /* write permission */
#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) /* execute permission */
/*
* The default protection for newly-created virtual memory
*/
#define VM_PROT_DEFAULT (VM_PROT_READ|VM_PROT_WRITE)
/*
* The maximum privileges possible, for parameter checking.
*/
#define VM_PROT_ALL (VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE)
/*
* This is an alias to VM_PROT_EXECUTE to identify callers that
* want to allocate an hardware assisted Read-only/read-write
* trusted path in userland.
*/
#define VM_PROT_RORW_TP (VM_PROT_EXECUTE)
/*
* An invalid protection value.
* Used only by memory_object_lock_request to indicate no change
* to page locks. Using -1 here is a bad idea because it
* looks like VM_PROT_ALL and then some.
*/
#define VM_PROT_NO_CHANGE_LEGACY ((vm_prot_t) 0x08)
#define VM_PROT_NO_CHANGE ((vm_prot_t) 0x01000000)
/*
* When a caller finds that he cannot obtain write permission on a
* mapped entry, the following flag can be used. The entry will
* be made "needs copy" effectively copying the object (using COW),
* and write permission will be added to the maximum protections
* for the associated entry.
*/
#define VM_PROT_COPY ((vm_prot_t) 0x10)
/*
* Another invalid protection value.
* Used only by memory_object_data_request upon an object
* which has specified a copy_call copy strategy. It is used
* when the kernel wants a page belonging to a copy of the
* object, and is only asking the object as a result of
* following a shadow chain. This solves the race between pages
* being pushed up by the memory manager and the kernel
* walking down the shadow chain.
*/
#define VM_PROT_WANTS_COPY ((vm_prot_t) 0x10)
#ifdef PRIVATE
/*
* The caller wants this memory region treated as if it had a valid
* code signature.
*/
#define VM_PROT_TRUSTED ((vm_prot_t) 0x20)
#endif /* PRIVATE */
/*
* Another invalid protection value.
* Indicates that the other protection bits are to be applied as a mask
* against the actual protection bits of the map entry.
*/
#define VM_PROT_IS_MASK ((vm_prot_t) 0x40)
/*
* Another invalid protection value to support execute-only protection.
* VM_PROT_STRIP_READ is a special marker that tells mprotect to not
* set VM_PROT_READ. We have to do it this way because existing code
* expects the system to set VM_PROT_READ if VM_PROT_EXECUTE is set.
* VM_PROT_EXECUTE_ONLY is just a convenience value to indicate that
* the memory should be executable and explicitly not readable. It will
* be ignored on platforms that do not support this type of protection.
*/
#define VM_PROT_STRIP_READ ((vm_prot_t) 0x80)
#define VM_PROT_EXECUTE_ONLY (VM_PROT_EXECUTE|VM_PROT_STRIP_READ)
#ifdef PRIVATE
/*
* When using VM_PROT_COPY, fail instead of copying an executable mapping,
* since that could cause code-signing violations.
*/
#define VM_PROT_COPY_FAIL_IF_EXECUTABLE ((vm_prot_t)0x100)
#endif /* PRIVATE */
#if defined(__x86_64__)
/*
* Another invalid protection value to support specifying different
* execute permissions for user- and supervisor- modes. When
* MBE is enabled in a VM, VM_PROT_EXECUTE is used to indicate
* supervisor-mode execute permission, and VM_PROT_UEXEC specifies
* user-mode execute permission. Currently only used by the
* x86 Hypervisor kext.
*/
#define VM_PROT_UEXEC ((vm_prot_t) 0x8) /* User-mode Execute Permission */
#define VM_PROT_ALLEXEC (VM_PROT_EXECUTE | VM_PROT_UEXEC)
#else
#define VM_PROT_ALLEXEC (VM_PROT_EXECUTE)
#endif /* defined(__x86_64__) */
#endif /* _MACH_VM_PROT_H_ */

View file

@ -0,0 +1,163 @@
musl as a whole is licensed under the following standard MIT license:
----------------------------------------------------------------------
Copyright © 2005-2014 Rich Felker, et al.
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
----------------------------------------------------------------------
Authors/contributors include:
Alex Dowad
Alexander Monakov
Anthony G. Basile
Arvid Picciani
Bobby Bingham
Boris Brezillon
Brent Cook
Chris Spiegel
Clément Vasseur
Daniel Micay
Denys Vlasenko
Emil Renner Berthing
Felix Fietkau
Felix Janda
Gianluca Anzolin
Hauke Mehrtens
Hiltjo Posthuma
Isaac Dunham
Jaydeep Patil
Jens Gustedt
Jeremy Huntwork
Jo-Philipp Wich
Joakim Sindholt
John Spencer
Josiah Worcester
Justin Cormack
Khem Raj
Kylie McClain
Luca Barbato
Luka Perkov
M Farkas-Dyck (Strake)
Mahesh Bodapati
Michael Forney
Natanael Copa
Nicholas J. Kain
orc
Pascal Cuoq
Petr Hosek
Pierre Carrier
Rich Felker
Richard Pennington
Shiz
sin
Solar Designer
Stefan Kristiansson
Szabolcs Nagy
Timo Teräs
Trutz Behn
Valentin Ochs
William Haddon
Portions of this software are derived from third-party works licensed
under terms compatible with the above MIT license:
The TRE regular expression implementation (src/regex/reg* and
src/regex/tre*) is Copyright © 2001-2008 Ville Laurikari and licensed
under a 2-clause BSD license (license text in the source files). The
included version has been heavily modified by Rich Felker in 2012, in
the interests of size, simplicity, and namespace cleanliness.
Much of the math library code (src/math/* and src/complex/*) is
Copyright © 1993,2004 Sun Microsystems or
Copyright © 2003-2011 David Schultz or
Copyright © 2003-2009 Steven G. Kargl or
Copyright © 2003-2009 Bruce D. Evans or
Copyright © 2008 Stephen L. Moshier
and labelled as such in comments in the individual source files. All
have been licensed under extremely permissive terms.
The ARM memcpy code (src/string/arm/memcpy_el.S) is Copyright © 2008
The Android Open Source Project and is licensed under a two-clause BSD
license. It was taken from Bionic libc, used on Android.
The implementation of DES for crypt (src/crypt/crypt_des.c) is
Copyright © 1994 David Burren. It is licensed under a BSD license.
The implementation of blowfish crypt (src/crypt/crypt_blowfish.c) was
originally written by Solar Designer and placed into the public
domain. The code also comes with a fallback permissive license for use
in jurisdictions that may not recognize the public domain.
The smoothsort implementation (src/stdlib/qsort.c) is Copyright © 2011
Valentin Ochs and is licensed under an MIT-style license.
The BSD PRNG implementation (src/prng/random.c) and XSI search API
(src/search/*.c) functions are Copyright © 2011 Szabolcs Nagy and
licensed under following terms: "Permission to use, copy, modify,
and/or distribute this code for any purpose with or without fee is
hereby granted. There is no warranty."
The x86_64 port was written by Nicholas J. Kain and is licensed under
the standard MIT terms.
The mips and microblaze ports were originally written by Richard
Pennington for use in the ellcc project. The original code was adapted
by Rich Felker for build system and code conventions during upstream
integration. It is licensed under the standard MIT terms.
The mips64 port was contributed by Imagination Technologies and is
licensed under the standard MIT terms.
The powerpc port was also originally written by Richard Pennington,
and later supplemented and integrated by John Spencer. It is licensed
under the standard MIT terms.
All other files which have no copyright comments are original works
produced specifically for use as part of this library, written either
by Rich Felker, the main author of the library, or by one or more
contibutors listed above. Details on authorship of individual files
can be found in the git version control history of the project. The
omission of copyright and license comments in each file is in the
interest of source tree size.
In addition, permission is hereby granted for all public header files
(include/* and arch/*/bits/*) and crt files intended to be linked into
applications (crt/*, ldso/dlstart.c, and arch/*/crt_arch.h) to omit
the copyright notice and permission notice otherwise required by the
license, and to use these files without any requirement of
attribution. These files include substantial contributions from:
Bobby Bingham
John Spencer
Nicholas J. Kain
Rich Felker
Richard Pennington
Stefan Kristiansson
Szabolcs Nagy
all of whom have explicitly granted such permission.
This file previously contained text expressing a belief that most of
the files covered by the above exception were sufficiently trivial not
to be subject to copyright, resulting in confusion over whether it
negated the permissions granted in the license. In the spirit of
permissive licensing, and of not having licensing issues being an
obstacle to adoption, that text has been removed.

View file

@ -0,0 +1,23 @@
musl libc
musl, pronounced like the word "mussel", is an MIT-licensed
implementation of the standard C library targetting the Linux syscall
API, suitable for use in a wide range of deployment environments. musl
offers efficient static and dynamic linking support, lightweight code
and low runtime overhead, strong fail-safe guarantees under correct
usage, and correctness in the sense of standards conformance and
safety. musl is built on the principle that these goals are best
achieved through simple code that is easy to understand and maintain.
The 1.1 release series for musl features coverage for all interfaces
defined in ISO C99 and POSIX 2008 base, along with a number of
non-standardized interfaces for compatibility with Linux, BSD, and
glibc functionality.
For basic installation instructions, see the included INSTALL file.
Information on full musl-targeted compiler toolchains, system
bootstrapping, and Linux distributions built on musl can be found on
the project website:
http://www.musl-libc.org/

View file

@ -0,0 +1,3 @@
This directory contains the elf header from
https://git.musl-libc.org/cgit/musl/tree/
that is required to get ELF working in dump_syms on Mac OS X.

View file

@ -0,0 +1 @@
1.1.14

File diff suppressed because it is too large Load diff