diff options
| -rw-r--r-- | adb/commandline.c | 5 | ||||
| -rw-r--r-- | include/arch/freebsd-x86/AndroidConfig.h | 317 | ||||
| -rw-r--r-- | include/cutils/tztime.h | 7 | ||||
| -rw-r--r-- | init/builtins.c | 66 | ||||
| -rw-r--r-- | init/devices.c | 6 | ||||
| -rw-r--r-- | init/init.c | 4 | ||||
| -rw-r--r-- | libacc/FEATURES | 65 | ||||
| -rw-r--r-- | libacc/acc.cpp | 1004 | ||||
| -rwxr-xr-x | libacc/test | 2 | ||||
| -rw-r--r-- | libacc/tests/.gitignore | 2 | ||||
| -rw-r--r-- | libacc/tests/bellard.otccex.c | 126 | ||||
| -rw-r--r-- | libacc/tests/expr.c | 60 | ||||
| -rw-r--r-- | libacc/tests/hello.c | 3 | ||||
| -rw-r--r-- | libacc/tests/hello.out-orig | bin | 0 -> 40 bytes | |||
| -rw-r--r-- | libacc/tests/missing-main.c | 4 | ||||
| -rw-r--r-- | libacc/tests/otcc.c | 446 | ||||
| -rw-r--r-- | libacc/tests/otcc.out-orig | bin | 0 -> 8591 bytes | |||
| -rw-r--r-- | libcutils/Android.mk | 13 | ||||
| -rw-r--r-- | libcutils/strdup16to8.c | 108 | ||||
| -rw-r--r-- | liblog/logprint.c | 1 | ||||
| -rw-r--r-- | libpixelflinger/Android.mk | 2 | ||||
| -rw-r--r-- | toolbox/ls.c | 11 | ||||
| -rw-r--r-- | toolbox/mkdosfs.c | 2 | ||||
| -rw-r--r-- | toolbox/mount.c | 7 | ||||
| -rw-r--r-- | toolbox/smd.c | 1 | ||||
| -rw-r--r-- | vold/mmc.c | 2 |
26 files changed, 2222 insertions, 42 deletions
diff --git a/adb/commandline.c b/adb/commandline.c index 7410dce..41b340a 100644 --- a/adb/commandline.c +++ b/adb/commandline.c @@ -96,7 +96,8 @@ void help() " -e - directs command to the only running emulator.\n" " returns an error if more than one emulator is running.\n" " -s <serial number> - directs command to the USB device or emulator with\n" - " the given serial number\n" + " the given serial number. Overrides ANDROID_SERIAL\n" + " envivornment variable.\n" " -p <product name or path> - simple product name like 'sooner', or\n" " a relative/absolute path to a product\n" " out directory like 'out/target/product/sooner'.\n" @@ -766,6 +767,8 @@ int adb_commandline(int argc, char **argv) } // TODO: also try TARGET_PRODUCT/TARGET_DEVICE as a hint + serial = getenv("ANDROID_SERIAL"); + /* modifiers and flags */ while(argc > 0) { if(!strcmp(argv[0],"nodaemon")) { diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h new file mode 100644 index 0000000..cc118f4 --- /dev/null +++ b/include/arch/freebsd-x86/AndroidConfig.h @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2005 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +/* + * Android config -- "FreeBSD". Used for desktop x86 FreeBSD. + */ +#ifndef _ANDROID_CONFIG_H +#define _ANDROID_CONFIG_H + +/* + * make sure we are building for FreeBSD + */ +#ifndef OS_FREEBSD +#define OS_FREEBSD +#endif +/* + * =========================================================================== + * !!! IMPORTANT !!! + * =========================================================================== + * + * This file is included by ALL C/C++ source files. Don't put anything in + * here unless you are absolutely certain it can't go anywhere else. + * + * Any C++ stuff must be wrapped with "#ifdef __cplusplus". Do not use "//" + * comments. + */ + +/* + * Threading model. Choose one: + * + * HAVE_PTHREADS - use the pthreads library. + * HAVE_WIN32_THREADS - use Win32 thread primitives. + * -- combine HAVE_CREATETHREAD, HAVE_CREATEMUTEX, and HAVE__BEGINTHREADEX + */ +#define HAVE_PTHREADS + +/* + * Do we have the futex syscall? + */ +/* #define HAVE_FUTEX */ + +/* + * Process creation model. Choose one: + * + * HAVE_FORKEXEC - use fork() and exec() + * HAVE_WIN32_PROC - use CreateProcess() + */ +#define HAVE_FORKEXEC + +/* + * Process out-of-memory adjustment. Set if running on Linux, + * where we can write to /proc/<pid>/oom_adj to modify the out-of-memory + * badness adjustment. + */ +/* #define HAVE_OOM_ADJ */ + +/* + * IPC model. Choose one: + * + * HAVE_SYSV_IPC - use the classic SysV IPC mechanisms (semget, shmget). + * HAVE_MACOSX_IPC - use Macintosh IPC mechanisms (sem_open, mmap). + * HAVE_WIN32_IPC - use Win32 IPC (CreateSemaphore, CreateFileMapping). + * HAVE_ANDROID_IPC - use Android versions (?, mmap). + */ +#define HAVE_SYSV_IPC + +/* + * Memory-mapping model. Choose one: + * + * HAVE_POSIX_FILEMAP - use the Posix sys/mmap.h + * HAVE_WIN32_FILEMAP - use Win32 filemaps + */ +#define HAVE_POSIX_FILEMAP + +/* + * Define this if you have <termio.h> + */ +/* #define HAVE_TERMIO_H */ + +/* + * Define this if you build against MSVCRT.DLL + */ +/* #define HAVE_MS_C_RUNTIME */ + +/* + * Define this if you have sys/uio.h + */ +#define HAVE_SYS_UIO_H + +/* + * Define this if your platforms implements symbolic links + * in its filesystems + */ +#define HAVE_SYMLINKS + +/* + * Define this if we have localtime_r(). + */ +#define HAVE_LOCALTIME_R + +/* + * Define this if we have gethostbyname_r(). + */ +/* #define HAVE_GETHOSTBYNAME_R */ + +/* + * Define this if we have ioctl(). + */ +#define HAVE_IOCTL + +/* + * Define this if we want to use WinSock. + */ +/* #define HAVE_WINSOCK */ + +/* + * Define this if have clock_gettime() and friends + * + * Desktop Linux has this in librt, but it's broken in goobuntu, yielding + * mildly or wildly inaccurate results. + */ +#define HAVE_POSIX_CLOCKS + +/* + * Define this if we have pthread_cond_timedwait_monotonic() and + * clock_gettime(CLOCK_MONOTONIC). + */ +/* #define HAVE_TIMEDWAIT_MONOTONIC */ + +/* + * Define this if we have linux style epoll() + */ +/* #define HAVE_EPOLL */ + +/* + * Endianness of the target machine. Choose one: + * + * HAVE_ENDIAN_H -- have endian.h header we can include. + * HAVE_LITTLE_ENDIAN -- we are little endian. + * HAVE_BIG_ENDIAN -- we are big endian. + */ +/* #define HAVE_ENDIAN_H */ +#define HAVE_LITTLE_ENDIAN + +/* + * Define this if you have sys/endian.h + * NOTE: mutually exclusive with HAVE_ENDIAN_H + */ +#define HAVE_SYS_ENDIAN_H + +/* + * We need to choose between 32-bit and 64-bit off_t. All of our code should + * agree on the same size. For desktop systems, use 64-bit values, + * because some of our libraries (e.g. wxWidgets) expect to be built that way. + */ +#define _FILE_OFFSET_BITS 64 +#define _LARGEFILE_SOURCE 1 + +/* + * Defined if we have the backtrace() call for retrieving a stack trace. + * Needed for CallStack to operate; if not defined, CallStack is + * non-functional. + */ +#define HAVE_BACKTRACE 0 + +/* + * Defined if we have the dladdr() call for retrieving the symbol associated + * with a memory address. If not defined, stack crawls will not have symbolic + * information. + */ +#define HAVE_DLADDR 1 + +/* + * Defined if we have the cxxabi.h header for demangling C++ symbols. If + * not defined, stack crawls will be displayed with raw mangled symbols + */ +#define HAVE_CXXABI 0 + +/* + * Defined if we have the gettid() system call. + */ +/* #define HAVE_GETTID */ + +/* + * Defined if we have the sched_setscheduler() call + */ +#define HAVE_SCHED_SETSCHEDULER + +/* + * Add any extra platform-specific defines here. + */ + +/* + * Define if we have <malloc.h> header + */ +#define HAVE_MALLOC_H + +/* + * Define if we have Linux-style non-filesystem Unix Domain Sockets + */ + +/* + * What CPU architecture does this platform use? + */ +#define ARCH_X86 + + +/* + * Define if we have Linux's inotify in <sys/inotify.h>. + */ +/*#define HAVE_INOTIFY 1*/ + +/* + * Define if we have madvise() in <sys/mman.h> + */ +#define HAVE_MADVISE 1 + +/* + * Define if tm struct has tm_gmtoff field + */ +#define HAVE_TM_GMTOFF 1 + +/* + * Define if dirent struct has d_type field + */ +#define HAVE_DIRENT_D_TYPE 1 + +/* + * Define if libc includes Android system properties implementation. + */ +/* #define HAVE_LIBC_SYSTEM_PROPERTIES */ + +/* + * Define if system provides a system property server (should be + * mutually exclusive with HAVE_LIBC_SYSTEM_PROPERTIES). + */ +#define HAVE_SYSTEM_PROPERTY_SERVER + +/* + * sprintf() format string for shared library naming. + */ +#define OS_SHARED_LIB_FORMAT_STR "lib%s.so" + +/* + * type for the third argument to mincore(). + */ +#define MINCORE_POINTER_TYPE char * + +/* + * Do we have the sigaction flag SA_NOCLDWAIT? + */ +#define HAVE_SA_NOCLDWAIT + +/* + * Define if we include <sys/mount.h> for statfs() + */ +#define INCLUDE_SYS_MOUNT_FOR_STATFS 1 + +/* + * The default path separator for the platform + */ +#define OS_PATH_SEPARATOR '/' + +/* + * Is the filesystem case sensitive? + */ +#define OS_CASE_SENSITIVE + +/* + * Define if <sys/socket.h> exists. + */ +#define HAVE_SYS_SOCKET_H 1 + +/* + * Define if the strlcpy() function exists on the system. + */ +#define HAVE_STRLCPY 1 + +/* + * Define if prctl() exists + */ +/* #define HAVE_PRCTL 1 */ + +/* + * Define if writev() exists + */ +#define HAVE_WRITEV 1 + +/* + * Define if <alloca.h> does not exist + * NOTE: <alloca.h> defines alloca() which + * on FreeBSD is defined in <stdlib.h> + */ +#define HAVE_NO_ALLOCA_H + +/* + * Defines CLOCK_PROCESS_CPUTIME_ID for clock_gettime() + * XXX: CLOCK_PROF seems to be commonly used replacement + */ +#ifndef CLOCK_PROCESS_CPUTIME_ID +#define CLOCK_PROCESS_CPUTIME_ID CLOCK_PROF +#endif + +#endif /*_ANDROID_CONFIG_H*/ diff --git a/include/cutils/tztime.h b/include/cutils/tztime.h index 9b3ece8..4af2ce4 100644 --- a/include/cutils/tztime.h +++ b/include/cutils/tztime.h @@ -17,6 +17,8 @@ #ifndef _CUTILS_TZTIME_H #define _CUTILS_TZTIME_H +#include <time.h> + #ifdef __cplusplus extern "C" { #endif @@ -24,6 +26,9 @@ extern "C" { time_t mktime_tz(struct tm * const tmp, char const * tz); void localtime_tz(const time_t * const timep, struct tm * tmp, const char* tz); +#ifndef HAVE_ANDROID_OS +/* the following is defined in <time.h> in Bionic */ + struct strftime_locale { const char *mon[12]; /* short names */ const char *month[12]; /* long names */ @@ -39,6 +44,8 @@ struct strftime_locale { size_t strftime_tz(char *s, size_t max, const char *format, const struct tm *tm, const struct strftime_locale *locale); +#endif /* !HAVE_ANDROID_OS */ + #ifdef __cplusplus } #endif diff --git a/init/builtins.c b/init/builtins.c index 95fb223..bcdfee1 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -29,6 +29,7 @@ #include <stdlib.h> #include <sys/mount.h> #include <sys/resource.h> +#include <linux/loop.h> #include "init.h" #include "keywords.h" @@ -257,7 +258,7 @@ static struct { int do_mount(int nargs, char **args) { char tmp[64]; - char *source; + char *source, *target, *system; char *options = NULL; unsigned flags = 0; int n, i; @@ -275,15 +276,70 @@ int do_mount(int nargs, char **args) options = args[n]; } + system = args[1]; source = args[2]; + target = args[3]; + if (!strncmp(source, "mtd@", 4)) { n = mtd_name_to_number(source + 4); - if (n >= 0) { - sprintf(tmp, "/dev/block/mtdblock%d", n); - source = tmp; + if (n < 0) { + return -1; + } + + sprintf(tmp, "/dev/block/mtdblock%d", n); + + if (mount(tmp, target, system, flags, options) < 0) { + return -1; + } + + return 0; + } else if (!strncmp(source, "loop@", 5)) { + int mode, loop, fd; + struct loop_info info; + + mode = (flags & MS_RDONLY) ? O_RDONLY : O_RDWR; + fd = open(source + 5, mode); + if (fd < 0) { + return -1; } + + for (n = 0; ; n++) { + sprintf(tmp, "/dev/block/loop%d", n); + loop = open(tmp, mode); + if (loop < 0) { + return -1; + } + + /* if it is a blank loop device */ + if (ioctl(loop, LOOP_GET_STATUS, &info) < 0 && errno == ENXIO) { + /* if it becomes our loop device */ + if (ioctl(loop, LOOP_SET_FD, fd) >= 0) { + close(fd); + + if (mount(tmp, target, system, flags, options) < 0) { + ioctl(loop, LOOP_CLR_FD, 0); + close(loop); + return -1; + } + + close(loop); + return 0; + } + } + + close(loop); + } + + close(fd); + ERROR("out of loopback devices"); + return -1; + } else { + if (mount(source, target, system, flags, options) < 0) { + return -1; + } + + return 0; } - return mount(source, args[3], args[1], flags, options); } int do_setkey(int nargs, char **args) diff --git a/init/devices.c b/init/devices.c index b914c53..8aea772 100644 --- a/init/devices.c +++ b/init/devices.c @@ -131,6 +131,9 @@ static struct perms_ devperms[] = { { "/dev/qmi0", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi1", 0640, AID_RADIO, AID_RADIO, 0 }, { "/dev/qmi2", 0640, AID_RADIO, AID_RADIO, 0 }, + + /* CDMA radio interface MUX */ + { "/dev/ts0710mux", 0640, AID_RADIO, AID_RADIO, 1 }, { NULL, 0, 0, 0, 0 }, }; @@ -387,6 +390,9 @@ static void handle_device_event(struct uevent *uevent) } else if(!strncmp(uevent->subsystem, "mtd", 3)) { base = "/dev/mtd/"; mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "sound", 5)) { + base = "/dev/snd/"; + mkdir(base, 0755); } else if(!strncmp(uevent->subsystem, "misc", 4) && !strncmp(name, "log_", 4)) { base = "/dev/log/"; diff --git a/init/init.c b/init/init.c index a748ec3..283608c 100644 --- a/init/init.c +++ b/init/init.c @@ -248,7 +248,9 @@ void service_start(struct service *svc) setuid(svc->uid); } - execve(svc->args[0], (char**) svc->args, (char**) ENV); + if (execve(svc->args[0], (char**) svc->args, (char**) ENV) < 0) { + ERROR("cannot execve('%s'): %s\n", svc->args[0], strerror(errno)); + } _exit(127); } diff --git a/libacc/FEATURES b/libacc/FEATURES new file mode 100644 index 0000000..3e80890 --- /dev/null +++ b/libacc/FEATURES @@ -0,0 +1,65 @@ + +Supported C language subset (read joint example 'otccex.c' to have + an introduction to OTCC dialect): + + - Expressions: + + * binary operators, by decreasing priority order: '*' '/' '%', + '+' '-', '>>' '<<', '<' '<=' '>' '>=', '==' '!=', '&', + '^', '|', '=', '&&', '||'. + + * '&&' and '||' have the same semantics as C : left to right + evaluation and early exit. + + * Parenthesis are supported. + + * Unary operators: '&', '*' (pointer indirection), '-' + (negation), '+', '!', '~', post fixed '++' and '--'. + + * Pointer indirection ('*') only works with explicit cast to + 'char *', 'int *' or 'int (*)()' (function pointer). + + * '++', '--', and unary '&' can only be used with variable + lvalue (left value). + + * '=' can only be used with variable or '*' (pointer + indirection) lvalue. + + * Function calls are supported with standard i386 calling + convention. Function pointers are supported with explicit + cast. Functions can be used before being declared. + + - Types: only signed integer ('int') variables and functions can + be declared. Variables cannot be initialized in + declarations. Only old K&R function declarations are parsed + (implicit integer return value and no types on arguments). + + - Any function or variable from the libc can be used because OTCC + uses the libc dynamic linker to resolve undefined symbols. + + - Instructions: blocks ('{' '}') are supported as in C. 'if' and + 'else' can be used for tests. The 'while' and 'for' C constructs + are supported for loops. 'break' can be used to exit + loops. 'return' is used for the return value of a function. + + - Identifiers are parsed the same way as C. Local variables are + handled, but there is no local name space (not a problem if + different names are used for local and global variables). + + - Numbers can be entered in decimal, hexadecimal ('0x' or '0X' + prefix), or octal ('0' prefix). + + - '#define' is supported without function like arguments. No macro + recursion is tolerated. Other preprocessor directives are + ignored. + + - C Strings and C character constants are supported. Only '\n', + '\"', '\'' and '\\' escapes are recognized. + + - C Comments can be used (but no C++ comments). + + - No error is displayed if an incorrect program is given. + + - Memory: the code, data, and symbol sizes are limited to 100KB + (it can be changed in the source code). + diff --git a/libacc/acc.cpp b/libacc/acc.cpp new file mode 100644 index 0000000..0f8e606 --- /dev/null +++ b/libacc/acc.cpp @@ -0,0 +1,1004 @@ +/* + Obfuscated Tiny C Compiler + + Copyright (C) 2001-2003 Fabrice Bellard + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product and its documentation + *is* required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + */ + +#include <ctype.h> +#include <dlfcn.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +namespace acc { + +class compiler { + + class CodeBuf { + char* ind; + char* pProgramBase; + + void release() { + if (pProgramBase != 0) { + free(pProgramBase); + pProgramBase = 0; + } + } + + public: + CodeBuf() { + pProgramBase = 0; + ind = 0; + } + + ~CodeBuf() { + release(); + } + + void init(int size) { + release(); + pProgramBase = (char*) calloc(1, size); + ind = pProgramBase; + } + + void o(int n) { + /* cannot use unsigned, so we must do a hack */ + while (n && n != -1) { + *ind++ = n; + n = n >> 8; + } + } + + /* + * Output a byte. Handles all values, 0..ff. + */ + void ob(int n) { + *ind++ = n; + } + + /* output a symbol and patch all calls to it */ + void gsym(int t) { + int n; + while (t) { + n = *(int *) t; /* next value */ + *(int *) t = ((int) ind) - t - 4; + t = n; + } + } + + /* psym is used to put an instruction with a data field which is a + reference to a symbol. It is in fact the same as oad ! */ + int psym(int n, int t) { + return oad(n, t); + } + + /* instruction + address */ + int oad(int n, int t) { + o(n); + *(int *) ind = t; + t = (int) ind; + ind = ind + 4; + return t; + } + + inline void* getBase() { + return (void*) pProgramBase; + } + + int getSize() { + return ind - pProgramBase; + } + + int getPC() { + return (int) ind; + } + }; + + class CodeGenerator { + public: + CodeGenerator() {} + virtual ~CodeGenerator() {} + + void init(CodeBuf* pCodeBuf) { + this->pCodeBuf = pCodeBuf; + } + + /* output a symbol and patch all calls to it */ + void gsym(int t) { + pCodeBuf->gsym(t); + } + + protected: + void o(int n) { + pCodeBuf->o(n); + } + + /* + * Output a byte. Handles all values, 0..ff. + */ + void ob(int n) { + pCodeBuf->ob(n); + } + + /* psym is used to put an instruction with a data field which is a + reference to a symbol. It is in fact the same as oad ! */ + int psym(int n, int t) { + return oad(n, t); + } + + /* instruction + address */ + int oad(int n, int t) { + return pCodeBuf->oad(n,t); + } + + int getPC() { + return pCodeBuf->getPC(); + } + + private: + CodeBuf* pCodeBuf; + }; + + class X86CodeGenerator : public CodeGenerator { + public: + X86CodeGenerator() {} + virtual ~X86CodeGenerator() {} + + /* returns address to patch with local variable size + */ + int functionEntry() { + o(0xe58955); /* push %ebp, mov %esp, %ebp */ + return oad(0xec81, 0); /* sub $xxx, %esp */ + } + + void functionExit() { + o(0xc3c9); /* leave, ret */ + } + + /* load immediate value */ + int li(int t) { + oad(0xb8, t); /* mov $xx, %eax */ + } + + int gjmp(int t) { + return psym(0xe9, t); + } + + /* l = 0: je, l == 1: jne */ + int gtst(int l, int t) { + o(0x0fc085); /* test %eax, %eax, je/jne xxx */ + return psym(0x84 + l, t); + } + + int gcmp(int op) { + int t = decodeOp(op); + o(0xc139); /* cmp %eax,%ecx */ + li(0); + o(0x0f); /* setxx %al */ + o(t + 0x90); + o(0xc0); + } + + int genOp(int op) { + o(decodeOp(op)); + if (op == OP_MOD) + o(0x92); /* xchg %edx, %eax */ + } + + void clearECX() { + oad(0xb9, 0); /* movl $0, %ecx */ + } + + void pushEAX() { + o(0x50); /* push %eax */ + } + + void popECX() { + o(0x59); /* pop %ecx */ + } + + void storeEAXToAddressECX(bool isInt) { + o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */ + } + + void loadEAXIndirect(bool isInt) { + if (isInt) + o(0x8b); /* mov (%eax), %eax */ + else + o(0xbe0f); /* movsbl (%eax), %eax */ + ob(0); /* add zero in code */ + } + + void leaEAX(int ea) { + gmov(10, ea); /* leal EA, %eax */ + } + + void storeEAX(int ea) { + gmov(6, ea); /* mov %eax, EA */ + } + + void loadEAX(int ea) { + gmov(8, ea); /* mov EA, %eax */ + } + + void postIncrementOrDecrement(int n, int op) { + /* Implement post-increment or post decrement. + */ + gmov(0, n); /* 83 ADD */ + o(decodeOp(op)); + } + + int allocStackSpaceForArgs() { + return oad(0xec81, 0); /* sub $xxx, %esp */ + } + + void storeEAToArg(int l) { + oad(0x248489, l); /* movl %eax, xxx(%esp) */ + } + + int callForward(int symbol) { + return psym(0xe8, symbol); /* call xxx */ + } + + void callRelative(int t) { + psym(0xe8, t); /* call xxx */ + } + + void callIndirect(int l) { + oad(0x2494ff, l); /* call *xxx(%esp) */ + } + + void adjustStackAfterCall(int l) { + oad(0xc481, l); /* add $xxx, %esp */ + } + + private: + static const int operatorHelper[]; + + int decodeOp(int op) { + if (op < 0 || op > OP_COUNT) { + fprintf(stderr, "Out-of-range operator: %d\n", op); + exit(1); + } + return operatorHelper[op]; + } + + int gmov(int l, int t) { + o(l + 0x83); + oad((t < LOCAL) << 7 | 5, t); + } + }; + + /* vars: value of variables + loc : local variable index + glo : global variable index + ind : output code ptr + rsym: return symbol + prog: output code + dstk: define stack + dptr, dch: macro state + */ + int tok, tokc, tokl, ch, vars, rsym, loc, glo, sym_stk, dstk, + dptr, dch, last_id; + void* pSymbolBase; + void* pGlobalBase; + void* pVarsBase; + FILE* file; + + CodeBuf codeBuf; + X86CodeGenerator* pGen; + + static const int ALLOC_SIZE = 99999; + + /* depends on the init string */ + static const int TOK_STR_SIZE = 48; + static const int TOK_IDENT = 0x100; + static const int TOK_INT = 0x100; + static const int TOK_IF = 0x120; + static const int TOK_ELSE = 0x138; + static const int TOK_WHILE = 0x160; + static const int TOK_BREAK = 0x190; + static const int TOK_RETURN = 0x1c0; + static const int TOK_FOR = 0x1f8; + static const int TOK_DEFINE = 0x218; + static const int TOK_MAIN = 0x250; + + static const int TOK_DUMMY = 1; + static const int TOK_NUM = 2; + + static const int LOCAL = 0x200; + + static const int SYM_FORWARD = 0; + static const int SYM_DEFINE = 1; + + /* tokens in string heap */ + static const int TAG_TOK = ' '; + static const int TAG_MACRO = 2; + + static const int OP_INCREMENT = 0; + static const int OP_DECREMENT = 1; + static const int OP_MUL = 2; + static const int OP_DIV = 3; + static const int OP_MOD = 4; + static const int OP_PLUS = 5; + static const int OP_MINUS = 6; + static const int OP_SHIFT_LEFT = 7; + static const int OP_SHIFT_RIGHT = 8; + static const int OP_LESS_EQUAL = 9; + static const int OP_GREATER_EQUAL = 10; + static const int OP_LESS = 11; + static const int OP_GREATER = 12; + static const int OP_EQUALS = 13; + static const int OP_NOT_EQUALS = 14; + static const int OP_LOGICAL_AND = 15; + static const int OP_LOGICAL_OR = 16; + static const int OP_BIT_AND = 17; + static const int OP_BIT_XOR = 18; + static const int OP_BIT_OR = 19; + static const int OP_BIT_NOT = 20; + static const int OP_LOGICAL_NOT = 21; + static const int OP_COUNT = 22; + + /* Operators are searched from front, the two-character operators appear + * before the single-character operators with the same first character. + * @ is used to pad out single-character operators. + */ + static const char* operatorChars; + static const char operatorLevel[]; + + void pdef(int t) { + *(char *) dstk++ = t; + } + + void inp() { + if (dptr) { + ch = *(char *) dptr++; + if (ch == TAG_MACRO) { + dptr = 0; + ch = dch; + } + } else + ch = fgetc(file); + /* printf("ch=%c 0x%x\n", ch, ch); */ + } + + int isid() { + return isalnum(ch) | ch == '_'; + } + + /* read a character constant */ + void getq() { + if (ch == '\\') { + inp(); + if (ch == 'n') + ch = '\n'; + } + } + + void next() { + int l, a; + + while (isspace(ch) | ch == '#') { + if (ch == '#') { + inp(); + next(); + if (tok == TOK_DEFINE) { + next(); + pdef(TAG_TOK); /* fill last ident tag */ + *(int *) tok = SYM_DEFINE; + *(int *) (tok + 4) = dstk; /* define stack */ + } + /* well we always save the values ! */ + while (ch != '\n') { + pdef(ch); + inp(); + } + pdef(ch); + pdef(TAG_MACRO); + } + inp(); + } + tokl = 0; + tok = ch; + /* encode identifiers & numbers */ + if (isid()) { + pdef(TAG_TOK); + last_id = dstk; + while (isid()) { + pdef(ch); + inp(); + } + if (isdigit(tok)) { + tokc = strtol((char*) last_id, 0, 0); + tok = TOK_NUM; + } else { + *(char *) dstk = TAG_TOK; /* no need to mark end of string (we + suppose data is initialized to zero by calloc) */ + tok = (int) (strstr((char*) sym_stk, (char*) (last_id - 1)) + - sym_stk); + *(char *) dstk = 0; /* mark real end of ident for dlsym() */ + tok = tok * 8 + TOK_IDENT; + if (tok > TOK_DEFINE) { + tok = vars + tok; + /* printf("tok=%s %x\n", last_id, tok); */ + /* define handling */ + if (*(int *) tok == SYM_DEFINE) { + dptr = *(int *) (tok + 4); + dch = ch; + inp(); + next(); + } + } + } + } else { + inp(); + if (tok == '\'') { + tok = TOK_NUM; + getq(); + tokc = ch; + inp(); + inp(); + } else if (tok == '/' & ch == '*') { + inp(); + while (ch) { + while (ch != '*') + inp(); + inp(); + if (ch == '/') + ch = 0; + } + inp(); + next(); + } else { + const char* t = operatorChars; + int opIndex = 0; + while (l = *t++) { + a = *t++; + tokl = operatorLevel[opIndex]; + tokc = opIndex; + if (l == tok & (a == ch | a == '@')) { +#if 0 + printf("%c%c -> tokl=%d tokc=0x%x\n", + l, a, tokl, tokc); +#endif + if (a == ch) { + inp(); + tok = TOK_DUMMY; /* dummy token for double tokens */ + } + break; + } + opIndex++; + } + if (l == 0) { + tokl = 0; + tokc = 0; + } + } + } +#if 0 + { + int p; + + printf("tok=0x%x ", tok); + if (tok >= TOK_IDENT) { + printf("'"); + if (tok> TOK_DEFINE) + p = sym_stk + 1 + (tok - vars - TOK_IDENT) / 8; + else + p = sym_stk + 1 + (tok - TOK_IDENT) / 8; + while (*(char *)p != TAG_TOK && *(char *)p) + printf("%c", *(char *)p++); + printf("'\n"); + } else if (tok == TOK_NUM) { + printf("%d\n", tokc); + } else { + printf("'%c'\n", tok); + } + } +#endif + } + + void error(const char *fmt, ...) { + va_list ap; + + va_start(ap, fmt); + fprintf(stderr, "%ld: ", ftell((FILE *) file)); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + exit(1); + } + + void skip(int c) { + if (tok != c) { + error("'%c' expected", c); + } + next(); + } + + /* l is one if '=' parsing wanted (quick hack) */ + void unary(int l) { + int n, t, a, c; + + n = 1; /* type of expression 0 = forward, 1 = value, other = + lvalue */ + if (tok == '\"') { + pGen->li(glo); + while (ch != '\"') { + getq(); + *(char *) glo++ = ch; + inp(); + } + *(char *) glo = 0; + glo = glo + 4 & -4; /* align heap */ + inp(); + next(); + } else { + c = tokl; + a = tokc; + t = tok; + next(); + if (t == TOK_NUM) { + pGen->li(a); + } else if (c == 2) { + /* -, +, !, ~ */ + unary(0); + pGen->clearECX(); + if (t == '!') + pGen->gcmp(a); + else + pGen->genOp(a); + } else if (t == '(') { + expr(); + skip(')'); + } else if (t == '*') { + /* parse cast */ + skip('('); + t = tok; /* get type */ + next(); /* skip int/char/void */ + next(); /* skip '*' or '(' */ + if (tok == '*') { + /* function type */ + skip('*'); + skip(')'); + skip('('); + skip(')'); + t = 0; + } + skip(')'); + unary(0); + if (tok == '=') { + next(); + pGen->pushEAX(); + expr(); + pGen->popECX(); + pGen->storeEAXToAddressECX(t == TOK_INT); + } else if (t) { + pGen->loadEAXIndirect(t == TOK_INT); + } + } else if (t == '&') { + pGen->leaEAX(*(int *) tok); + next(); + } else { + n = *(int *) t; + /* forward reference: try dlsym */ + if (!n) + n = (int) dlsym(0, (char*) last_id); + if (tok == '=' & l) { + /* assignment */ + next(); + expr(); + pGen->storeEAX(n); + } else if (tok != '(') { + /* variable */ + pGen->loadEAX(n); + if (tokl == 11) { + pGen->postIncrementOrDecrement(n, tokc); + next(); + } + } + } + } + + /* function call */ + if (tok == '(') { + if (n == 1) + pGen->pushEAX(); + + /* push args and invert order */ + a = pGen->allocStackSpaceForArgs(); + next(); + l = 0; + while (tok != ')') { + expr(); + pGen->storeEAToArg(l); + if (tok == ',') + next(); + l = l + 4; + } + *(int *) a = l; + next(); + if (!n) { + /* forward reference */ + t = t + 4; + *(int *) t = pGen->callForward(*(int *) t); + } else if (n == 1) { + pGen->callIndirect(l); + l = l + 4; + } else { + pGen->callRelative(n - codeBuf.getPC() - 5); /* call xxx */ + } + if (l) + pGen->adjustStackAfterCall(l); + } + } + + void sum(int l) { + int t, n, a; + + if (l-- == 1) + unary(1); + else { + sum(l); + a = 0; + while (l == tokl) { + n = tok; + t = tokc; + next(); + + if (l > 8) { + a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ + sum(l); + } else { + pGen->pushEAX(); + sum(l); + pGen->popECX(); + + if (l == 4 | l == 5) { + pGen->gcmp(t); + } else { + pGen->genOp(t); + } + } + } + /* && and || output code generation */ + if (a && l > 8) { + a = pGen->gtst(t == OP_LOGICAL_OR, a); + pGen->li(t != OP_LOGICAL_OR); + pGen->gjmp(5); /* jmp $ + 5 */ + pGen->gsym(a); + pGen->li(t == OP_LOGICAL_OR); + } + } + } + + void expr() { + sum(11); + } + + int test_expr() { + expr(); + return pGen->gtst(0, 0); + } + + void block(int l) { + int a, n, t; + + if (tok == TOK_IF) { + next(); + skip('('); + a = test_expr(); + skip(')'); + block(l); + if (tok == TOK_ELSE) { + next(); + n = pGen->gjmp(0); /* jmp */ + pGen->gsym(a); + block(l); + pGen->gsym(n); /* patch else jmp */ + } else { + pGen->gsym(a); /* patch if test */ + } + } else if (tok == TOK_WHILE | tok == TOK_FOR) { + t = tok; + next(); + skip('('); + if (t == TOK_WHILE) { + n = codeBuf.getPC(); + a = test_expr(); + } else { + if (tok != ';') + expr(); + skip(';'); + n = codeBuf.getPC(); + a = 0; + if (tok != ';') + a = test_expr(); + skip(';'); + if (tok != ')') { + t = pGen->gjmp(0); + expr(); + pGen->gjmp(n - codeBuf.getPC() - 5); + pGen->gsym(t); + n = t + 4; + } + } + skip(')'); + block((int) &a); + pGen->gjmp(n - codeBuf.getPC() - 5); /* jmp */ + pGen->gsym(a); + } else if (tok == '{') { + next(); + /* declarations */ + decl(1); + while (tok != '}') + block(l); + next(); + } else { + if (tok == TOK_RETURN) { + next(); + if (tok != ';') + expr(); + rsym = pGen->gjmp(rsym); /* jmp */ + } else if (tok == TOK_BREAK) { + next(); + *(int *) l = pGen->gjmp(*(int *) l); + } else if (tok != ';') + expr(); + skip(';'); + } + } + + /* 'l' is true if local declarations */ + void decl(int l) { + int a; + + while (tok == TOK_INT | tok != -1 & !l) { + if (tok == TOK_INT) { + next(); + while (tok != ';') { + if (l) { + loc = loc + 4; + *(int *) tok = -loc; + } else { + *(int *) tok = glo; + glo = glo + 4; + } + next(); + if (tok == ',') + next(); + } + skip(';'); + } else { + /* patch forward references (XXX: do not work for function + pointers) */ + pGen->gsym(*(int *) (tok + 4)); + /* put function address */ + *(int *) tok = codeBuf.getPC(); + next(); + skip('('); + a = 8; + while (tok != ')') { + /* read param name and compute offset */ + *(int *) tok = a; + a = a + 4; + next(); + if (tok == ',') + next(); + } + next(); /* skip ')' */ + rsym = loc = 0; + a = pGen->functionEntry(); + block(0); + pGen->gsym(rsym); + pGen->functionExit(); + *(int *) a = loc; /* save local variables */ + } + } + } + + void cleanup() { + if (sym_stk != 0) { + free((void*) sym_stk); + sym_stk = 0; + } + if (pGlobalBase != 0) { + free((void*) pGlobalBase); + pGlobalBase = 0; + } + if (pVarsBase != 0) { + free(pVarsBase); + pVarsBase = 0; + } + if (pGen) { + delete pGen; + pGen = 0; + } + } + + void clear() { + tok = 0; + tokc = 0; + tokl = 0; + ch = 0; + vars = 0; + rsym = 0; + loc = 0; + glo = 0; + sym_stk = 0; + dstk = 0; + dptr = 0; + dch = 0; + last_id = 0; + file = 0; + pGlobalBase = 0; + pVarsBase = 0; + pGen = 0; + } + +public: + compiler() { + clear(); + } + + ~compiler() { + cleanup(); + } + + int compile(FILE* in) { + cleanup(); + clear(); + codeBuf.init(ALLOC_SIZE); + pGen = new X86CodeGenerator(); + pGen->init(&codeBuf); + file = in; + sym_stk = (int) calloc(1, ALLOC_SIZE); + dstk = (int) strcpy((char*) sym_stk, + " int if else while break return for define main ") + + TOK_STR_SIZE; + pGlobalBase = calloc(1, ALLOC_SIZE); + glo = (int) pGlobalBase; + pVarsBase = calloc(1, ALLOC_SIZE); + vars = (int) pVarsBase; + inp(); + next(); + decl(0); + return 0; + } + + int run(int argc, char** argv) { + typedef int (*mainPtr)(int argc, char** argv); + mainPtr aMain = (mainPtr) *(int*) (vars + TOK_MAIN); + if (!aMain) { + fprintf(stderr, "Could not find function \"main\".\n"); + return -1; + } + return aMain(argc, argv); + } + + int dump(FILE* out) { + fwrite(codeBuf.getBase(), 1, codeBuf.getSize(), out); + return 0; + } + +}; + +const char* compiler::operatorChars = + "++--*@/@%@+@-@<<>><=>=<@>@==!=&&||&@^@|@~@!@"; + +const char compiler::operatorLevel[] = + {11, 11, 1, 1, 1, 2, 2, 3, 3, 4, 4, 4, 4, + 5, 5, /* ==, != */ + 9, 10, /* &&, || */ + 6, 7, 8, /* & ^ | */ + 2, 2 /* ~ ! */ + }; + +const int compiler::X86CodeGenerator::operatorHelper[] = { + 0x1, // ++ + 0xff, // -- + 0xc1af0f, // * + 0xf9f79991, // / + 0xf9f79991, // % (With manual assist to swap results) + 0xc801, // + + 0xd8f7c829, // - + 0xe0d391, // << + 0xf8d391, // >> + 0xe, // <= + 0xd, // >= + 0xc, // < + 0xf, // > + 0x4, // == + 0x5, // != + 0x0, // && + 0x1, // || + 0xc821, // & + 0xc831, // ^ + 0xc809, // | + 0xd0f7, // ~ + 0x4 // ! +}; + +} // namespace acc + +int main(int argc, char** argv) { + bool doTest = false; + const char* inFile = NULL; + const char* outFile = NULL; + int i; + for (i = 1; i < argc; i++) { + char* arg = argv[i]; + if (arg[0] == '-') { + switch (arg[1]) { + case 'T': + if (i + 1 >= argc) { + fprintf(stderr, "Expected filename after -T\n"); + return 2; + } + doTest = true; + outFile = argv[i + 1]; + i += 1; + break; + default: + fprintf(stderr, "Unrecognized flag %s\n", arg); + return 3; + } + } else if (inFile == NULL) { + inFile = arg; + } else { + break; + } + } + + FILE* in = stdin; + if (inFile) { + in = fopen(inFile, "r"); + if (!in) { + fprintf(stderr, "Could not open input file %s\n", inFile); + return 1; + } + } + acc::compiler compiler; + int compileResult = compiler.compile(in); + if (in != stdin) { + fclose(in); + } + if (compileResult) { + fprintf(stderr, "Compile failed: %d\n", compileResult); + return 6; + } + if (doTest) { + FILE* save = fopen(outFile, "w"); + if (!save) { + fprintf(stderr, "Could not open output file %s\n", outFile); + return 5; + } + compiler.dump(save); + fclose(save); + } else { + fprintf(stderr, "Executing compiled code:\n"); + int codeArgc = argc - i + 1; + char** codeArgv = argv + i - 1; + codeArgv[0] = (char*) (inFile ? inFile : "stdin"); + return compiler.run(codeArgc, codeArgv); + } + + return 0; +} diff --git a/libacc/test b/libacc/test new file mode 100755 index 0000000..17d7b55 --- /dev/null +++ b/libacc/test @@ -0,0 +1,2 @@ +#!/bin/sh +g++ acc.cpp -ldl -o tests/acc && tests/acc tests/otcc.c -T tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore new file mode 100644 index 0000000..9974532 --- /dev/null +++ b/libacc/tests/.gitignore @@ -0,0 +1,2 @@ +acc +*.out diff --git a/libacc/tests/bellard.otccex.c b/libacc/tests/bellard.otccex.c new file mode 100644 index 0000000..e8f0989 --- /dev/null +++ b/libacc/tests/bellard.otccex.c @@ -0,0 +1,126 @@ +/* #!/usr/local/bin/otcc */ +/* + * Sample OTCC C example. You can uncomment the first line and install + * otcc in /usr/local/bin to make otcc scripts ! + */ + +/* Any preprocessor directive except #define are ignored. We put this + include so that a standard C compiler can compile this code too. */ +#include <stdio.h> + +/* defines are handled, but macro arguments cannot be given. No + recursive defines are tolerated */ +#define DEFAULT_BASE 10 + +/* + * Only old style K&R prototypes are parsed. Only int arguments are + * allowed (implicit types). + * + * By benchmarking the execution time of this function (for example + * for fib(35)), you'll notice that OTCC is quite fast because it + * generates native i386 machine code. + */ +fib(n) +{ + if (n <= 2) + return 1; + else + return fib(n-1) + fib(n-2); +} + +/* Identifiers are parsed the same way as C: begins with letter or + '_', and then letters, '_' or digits */ +fact(n) +{ + /* local variables can be declared. Only 'int' type is supported */ + int i, r; + r = 1; + /* 'while' and 'for' loops are supported */ + for(i=2;i<=n;i++) + r = r * i; + return r; +} + +/* Well, we could use printf, but it would be too easy */ +print_num(n, b) +{ + int tab, p, c; + /* Numbers can be entered in decimal, hexadecimal ('0x' prefix) and + octal ('0' prefix) */ + /* more complex programs use malloc */ + tab = malloc(0x100); + p = tab; + while (1) { + c = n % b; + /* Character constants can be used */ + if (c >= 10) + c = c + 'a' - 10; + else + c = c + '0'; + *(char *)p = c; + p++; + n = n / b; + /* 'break' is supported */ + if (n == 0) + break; + } + while (p != tab) { + p--; + printf("%c", *(char *)p); + } + free(tab); +} + +/* 'main' takes standard 'argc' and 'argv' parameters */ +main(argc, argv) +{ + /* no local name space is supported, but local variables ARE + supported. As long as you do not use a globally defined + variable name as local variable (which is a bad habbit), you + won't have any problem */ + int s, n, f, base; + + /* && and || operator have the same semantics as C (left to right + evaluation and early exit) */ + if (argc != 2 && argc != 3) { + /* '*' operator is supported with explicit casting to 'int *', + 'char *' or 'int (*)()' (function pointer). Of course, 'int' + are supposed to be used as pointers too. */ + s = *(int *)argv; + help(s); + return 1; + } + /* Any libc function can be used because OTCC uses dynamic linking */ + n = atoi(*(int *)(argv + 4)); + base = DEFAULT_BASE; + if (argc >= 3) { + base = atoi(*(int *)(argv + 8)); + if (base < 2 || base > 36) { + /* external variables can be used too (here: 'stderr') */ + fprintf(stderr, "Invalid base\n"); + return 1; + } + } + printf("fib(%d) = ", n); + print_num(fib(n), base); + printf("\n"); + + printf("fact(%d) = ", n); + if (n > 12) { + printf("Overflow"); + } else { + /* why not using a function pointer ? */ + f = &fact; + print_num((*(int (*)())f)(n), base); + } + printf("\n"); + return 0; +} + +/* functions can be used before being defined */ +help(name) +{ + printf("usage: %s n [base]\n", name); + printf("Compute fib(n) and fact(n) and output the result in base 'base'\n"); +} + diff --git a/libacc/tests/expr.c b/libacc/tests/expr.c new file mode 100644 index 0000000..4f2d2e7 --- /dev/null +++ b/libacc/tests/expr.c @@ -0,0 +1,60 @@ +/* Test operators */ + +testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); } +testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); } +testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); } +testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); } +testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); } +testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); } +testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); } +testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); } +testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); } +testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); } +testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); } +testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); } +testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); } +testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); } +testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); } +testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); } +testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); } +testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); } +testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); } +testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); } +testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); } +testAddressOf(){ int a; printf("&a is %d\n", &a); } +testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d = %d =?= %d\n", a, * (int*) a, b); } +testNegation(){ printf("-%d = %d\n", 10, -10); } +testUnaryPlus(){ printf("+%d = %d\n", 10, +10); } +testUnaryNot(){ printf("!%d = %d\n", 10, !10); } +testBitNot(){ printf("~%d = %d\n", 10, ~10); } + +main(a,b) { + testInc(); + testDec(); + testTimes(); + testDiv(); + testMod(); + testPlus(); + testMinus(); + testShiftLeft(); + testShiftRight(); + testLess(); + testLesEqual(); + testGreater(); + testGreaterEqual(); + testEqualTo(); + testNotEqualTo(); + testBitAnd(); + testBinXor(); + testBitOr(); + testAssignment(); + testLogicalAnd(); + testLogicalOr(); + testAddressOf(); + testPointerIndirection(); + testNegation(); + testUnaryPlus(); + testUnaryNot(); + testBitNot(); + return 0; +}
\ No newline at end of file diff --git a/libacc/tests/hello.c b/libacc/tests/hello.c new file mode 100644 index 0000000..585ce6c --- /dev/null +++ b/libacc/tests/hello.c @@ -0,0 +1,3 @@ +main(a,b) { + printf("Hello, world\n"); +} diff --git a/libacc/tests/hello.out-orig b/libacc/tests/hello.out-orig Binary files differnew file mode 100644 index 0000000..1fb7bf5 --- /dev/null +++ b/libacc/tests/hello.out-orig diff --git a/libacc/tests/missing-main.c b/libacc/tests/missing-main.c new file mode 100644 index 0000000..e73eec4 --- /dev/null +++ b/libacc/tests/missing-main.c @@ -0,0 +1,4 @@ +/* No main. */ + +a() { +}
\ No newline at end of file diff --git a/libacc/tests/otcc.c b/libacc/tests/otcc.c new file mode 100644 index 0000000..577fcf3 --- /dev/null +++ b/libacc/tests/otcc.c @@ -0,0 +1,446 @@ +#include <stdio.h> +#define k *(int*) +#define a if( +#define c ad() +#define i else +#define p while( +#define x *(char*) +#define b == +#define V =calloc(1,99999) +#define f () +#define J return +#define l ae( +#define n e) +#define u d!= +#define F int +#define y (j) +#define r m= +#define t +4 +F d,z,C,h,P,K,ac,q,G,v,Q,R,D,L,W,M; +E(n{ +x D++=e; +} +o f{ +a L){ +h=x L++; +a h b 2){ +L=0; +h=W; +} +} +i h=fgetc(Q); +} +X f{ +J isalnum(h)|h b 95; +} +Y f{ +a h b 92){ +o f; +a h b 110)h=10; +} +} +c{ +F e,j,m; +p isspace(h)|h b 35){ +a h b 35){ +o f; +c; +a d b 536){ +c; +E(32); +k d=1; +k(d t)=D; +} +p h!=10){ +E(h); +o f; +} +E(h); +E(2); +} +o f; +} +C=0; +d=h; +a X f){ +E(32); +M=D; +p X f){ +E(h); +o f; +} +a isdigit(d)){ +z=strtol(M,0,0); +d=2; +} +i{ +x D=32; +d=strstr(R,M-1)-R; +x D=0; +d=d*8+256; +a d>536){ +d=P+d; +a k d b 1){ +L=k(d t); +W=h; +o f; +c; +} +} +} +} +i{ +o f; +a d b 39){ +d=2; +Y f; +z=h; +o f; +o f; +} +i a d b 47&h b 42){ +o f; +p h){ +p h!=42)o f; +o f; +a h b 47)h=0; +} +o f; +c; +} +i{ +e="++#m--%am*@R<^1c/@%[_[H3c%@%[_[H3c+@.B#d-@%:_^BKd<<Z/03e>>`/03e<=0f>=/f<@.f>@1f==&g!='g&&k||#l&@.BCh^@.BSi|@.B+j~@/%Yd!@&d*@b"; +p j=x e++){ +r x e++; +z=0; +p(C=x e++-98)<0)z=z*64+C+64; +a j b d&(m b h|m b 64)){ +a m b h){ +o f; +d=1; +} +break; +} +} +} +} +} +l g){ +p g&&g!=-1){ +x q++=g; +g=g>>8; +} +} +A(n{ +F g; +p n{ +g=k e; +k e=q-e-4; +e=g; +} +} +s(g,n{ +l g); +k q=e; +e=q; +q=q t; +J e; +} +H(n{ +s(184,n; +} +B(n{ +J s(233,n; +} +S(j,n{ +l 1032325); +J s(132+j,n; +} +Z(n{ +l 49465); +H(0); +l 15); +l e+144); +l 192); +} +N(j,n{ +l j+131); +s((e<512)<<7|5,n; +} +T y{ +F g,e,m,aa; +g=1; +a d b 34){ +H(v); +p h!=34){ +Y f; +x v++=h; +o f; +} +x v=0; +v=v t&-4; +o f; +c; +} +i{ +aa=C; +r z; +e=d; +c; +a e b 2){ +H(m); +} +i a aa b 2){ +T(0); +s(185,0); +a e b 33)Z(m); +i l m); +} +i a e b 40){ +w f; +c; +} +i a e b 42){ +c; +e=d; +c; +c; +a d b 42){ +c; +c; +c; +c; +e=0; +} +c; +T(0); +a d b 61){ +c; +l 80); +w f; +l 89); +l 392+(e b 256)); +} +i a n{ +a e b 256)l 139); +i l 48655); +q++; +} +} +i a e b 38){ +N(10,k d); +c; +} +i{ +g=k e; +a!g)g=dlsym(0,M); +a d b 61&j){ +c; +w f; +N(6,g); +} +i a u 40){ +N(8,g); +a C b 11){ +N(0,g); +l z); +c; +} +} +} +} +a d b 40){ +a g b 1)l 80); +r s(60545,0); +c; +j=0; +p u 41){ +w f; +s(2393225,j); +a d b 44)c; +j=j t; +} +k r j; +c; +a!g){ +e=e t; +k e=s(232,k n; +} +i a g b 1){ +s(2397439,j); +j=j t; +} +i{ +s(232,g-q-5); +} +a j)s(50305,j); +} +} +O y{ +F e,g,m; +a j--b 1)T(1); +i{ +O y; +r 0; +p j b C){ +g=d; +e=z; +c; +a j>8){ +r S(e,m); +O y; +} +i{ +l 80); +O y; +l 89); +a j b 4|j b 5){ +Z(n; +} +i{ +l n; +a g b 37)l 146); +} +} +} +a m&&j>8){ +r S(e,m); +H(e^1); +B(5); +A(m); +H(n; +} +} +} +w f{ +O(11); +} +U f{ +w f; +J S(0,0); +} +I y{ +F m,g,e; +a d b 288){ +c; +c; +r U f; +c; +I y; +a d b 312){ +c; +g=B(0); +A(m); +I y; +A(g); +} +i{ +A(m); +} +} +i a d b 352|d b 504){ +e=d; +c; +c; +a e b 352){ +g=q; +r U f; +} +i{ +a u 59)w f; +c; +g=q; +r 0; +a u 59)r U f; +c; +a u 41){ +e=B(0); +w f; +B(g-q-5); +A(n; +g=e t; +} +} +c; +I(&m); +B(g-q-5); +A(m); +} +i a d b 123){ +c; +ab(1); +p u 125)I y; +c; +} +i{ +a d b 448){ +c; +a u 59)w f; +K=B(K); +} +i a d b 400){ +c; +k j=B(k j); +} +i a u 59)w f; +c; +} +} +ab y{ +F m; +p d b 256|u-1&!j){ +a d b 256){ +c; +p u 59){ +a j){ +G=G t; +k d=-G; +} +i{ +k d=v; +v=v t; +} +c; +a d b 44)c; +} +c; +} +i{ +A(k(d t)); +k d=q; +c; +c; +r 8; +p u 41){ +k d=m; +r m t; +c; +a d b 44)c; +} +c; +K=G=0; +l 15042901); +r s(60545,0); +I(0); +A(K); +l 50121); +k r G; +} +} +} +main(g,n{ +Q=stdin; +a g-->1){ +e=e t; +Q=fopen(k e,"r"); +} +D=strcpy(R V," int if else while break return for define main ")+48; +v V; +q=ac V; +P V; +o f; +c; +ab(0); +J(*(int(*)f)k(P+592))(g,n; +} + diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig Binary files differnew file mode 100644 index 0000000..3bf7e1f --- /dev/null +++ b/libacc/tests/otcc.out-orig diff --git a/libcutils/Android.mk b/libcutils/Android.mk index a43f7e3..b6d806e 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -37,6 +37,9 @@ commonSources := \ properties.c \ threads.c +commonHostSources := \ + ashmem-host.c + # some files must not be compiled when building against Mingw # they correspond to features not used by our host development tools # which are also hard or even impossible to port to native Win32 @@ -60,16 +63,18 @@ else selector.c \ fdevent.c \ tztime.c \ - tzstrftime.c \ adb_networking.c \ - zygote.c + zygote.c + + commonHostSources += \ + tzstrftime.c endif # Static library for host # ======================================================== LOCAL_MODULE := libcutils -LOCAL_SRC_FILES := $(commonSources) ashmem-host.c +LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) LOCAL_LDLIBS := -lpthread LOCAL_STATIC_LIBRARIES := liblog include $(BUILD_HOST_STATIC_LIBRARY) @@ -81,7 +86,7 @@ ifeq ($(TARGET_SIMULATOR),true) # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE := libcutils -LOCAL_SRC_FILES := $(commonSources) memory.c dlmalloc_stubs.c ashmem-host.c +LOCAL_SRC_FILES := $(commonSources) $(commonHostSources) memory.c dlmalloc_stubs.c LOCAL_LDLIBS := -lpthread LOCAL_SHARED_LIBRARIES := liblog include $(BUILD_SHARED_LIBRARY) diff --git a/libcutils/strdup16to8.c b/libcutils/strdup16to8.c index fadaabe..1a8ba86 100644 --- a/libcutils/strdup16to8.c +++ b/libcutils/strdup16to8.c @@ -15,6 +15,8 @@ ** limitations under the License. */ +#include <limits.h> /* for SIZE_MAX */ + #include <cutils/jstring.h> #include <assert.h> #include <stdlib.h> @@ -26,19 +28,67 @@ */ extern size_t strnlen16to8(const char16_t* utf16Str, size_t len) { - size_t utf8Len = 0; - - while (len--) { - unsigned int uic = *utf16Str++; - - if (uic > 0x07ff) - utf8Len += 3; - else if (uic > 0x7f || uic == 0) - utf8Len += 2; - else - utf8Len++; - } - return utf8Len; + size_t utf8Len = 0; + + /* A small note on integer overflow. The result can + * potentially be as big as 3*len, which will overflow + * for len > SIZE_MAX/3. + * + * Moreover, the result of a strnlen16to8 is typically used + * to allocate a destination buffer to strncpy16to8 which + * requires one more byte to terminate the UTF-8 copy, and + * this is generally done by careless users by incrementing + * the result without checking for integer overflows, e.g.: + * + * dst = malloc(strnlen16to8(utf16,len)+1) + * + * Due to this, the following code will try to detect + * overflows, and never return more than (SIZE_MAX-1) + * when it detects one. A careless user will try to malloc + * SIZE_MAX bytes, which will return NULL which can at least + * be detected appropriately. + * + * As far as I know, this function is only used by strndup16(), + * but better be safe than sorry. + */ + + /* Fast path for the usual case where 3*len is < SIZE_MAX-1. + */ + if (len < (SIZE_MAX-1)/3) { + while (len--) { + unsigned int uic = *utf16Str++; + + if (uic > 0x07ff) + utf8Len += 3; + else if (uic > 0x7f || uic == 0) + utf8Len += 2; + else + utf8Len++; + } + return utf8Len; + } + + /* The slower but paranoid version */ + while (len--) { + unsigned int uic = *utf16Str++; + size_t utf8Cur = utf8Len; + + if (uic > 0x07ff) + utf8Len += 3; + else if (uic > 0x7f || uic == 0) + utf8Len += 2; + else + utf8Len++; + + if (utf8Len < utf8Cur) /* overflow detected */ + return SIZE_MAX-1; + } + + /* don't return SIZE_MAX to avoid common user bug */ + if (utf8Len == SIZE_MAX) + utf8Len = SIZE_MAX-1; + + return utf8Len; } @@ -50,7 +100,7 @@ extern size_t strnlen16to8(const char16_t* utf16Str, size_t len) * * Make sure you allocate "utf8Str" with the result of strlen16to8() + 1, * not just "len". - * + * * Please note, a terminated \0 is always added, so your result will always * be "strlen16to8() + 1" bytes long. */ @@ -58,6 +108,10 @@ extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len) { char* utf8cur = utf8Str; + /* Note on overflows: We assume the user did check the result of + * strnlen16to8() properly or at a minimum checked the result of + * its malloc(SIZE_MAX) in case of overflow. + */ while (len--) { unsigned int uic = *utf16Str++; @@ -73,8 +127,8 @@ extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len) if (uic == 0) { break; - } - } + } + } } *utf8cur = '\0'; @@ -85,20 +139,30 @@ extern char* strncpy16to8(char* utf8Str, const char16_t* utf16Str, size_t len) /** * Convert a UTF-16 string to UTF-8. * - * Make sure you allocate "dest" with the result of strblen16to8(), - * not just "strlen16()". */ char * strndup16to8 (const char16_t* s, size_t n) { - char *ret; + char* ret; + size_t len; if (s == NULL) { return NULL; } - ret = malloc(strnlen16to8(s, n) + 1); + len = strnlen16to8(s, n); + + /* We are paranoid, and we check for SIZE_MAX-1 + * too since it is an overflow value for our + * strnlen16to8 implementation. + */ + if (len >= SIZE_MAX-1) + return NULL; + + ret = malloc(len + 1); + if (ret == NULL) + return NULL; strncpy16to8 (ret, s, n); - - return ret; + + return ret; } diff --git a/liblog/logprint.c b/liblog/logprint.c index 2cf1254..080f9e3 100644 --- a/liblog/logprint.c +++ b/liblog/logprint.c @@ -23,7 +23,6 @@ #include <stdlib.h> #include <stdint.h> #include <string.h> -#include <alloca.h> #include <assert.h> #include <arpa/inet.h> diff --git a/libpixelflinger/Android.mk b/libpixelflinger/Android.mk index 50eb5f5..0cc85d9 100644 --- a/libpixelflinger/Android.mk +++ b/libpixelflinger/Android.mk @@ -64,12 +64,14 @@ endif LOCAL_MODULE:= libpixelflinger LOCAL_SRC_FILES := $(PIXELFLINGER_SRC_FILES) LOCAL_CFLAGS := $(PIXELFLINGER_CFLAGS) + ifneq ($(BUILD_TINY_ANDROID),true) # Really this should go away entirely or at least not depend on # libhardware, but this at least gets us built. LOCAL_SHARED_LIBRARIES += libhardware_legacy LOCAL_CFLAGS += -DWITH_LIB_HARDWARE endif + ifeq ($(TARGET_ARCH),arm) LOCAL_WHOLE_STATIC_LIBRARIES := libpixelflinger_armv6 endif diff --git a/toolbox/ls.c b/toolbox/ls.c index f609df2..087e4d5 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -15,9 +15,10 @@ #include <linux/kdev_t.h> // bits for flags argument -#define LIST_LONG (1 << 0) -#define LIST_ALL (1 << 1) -#define LIST_RECURSIVE (1 << 2) +#define LIST_LONG (1 << 0) +#define LIST_ALL (1 << 1) +#define LIST_RECURSIVE (1 << 2) +#define LIST_DIRECTORIES (1 << 3) // fwd static int listpath(const char *name, int flags); @@ -238,7 +239,7 @@ static int listpath(const char *name, int flags) return -1; } - if (S_ISDIR(s.st_mode)) { + if ((flags & LIST_DIRECTORIES) == 0 && S_ISDIR(s.st_mode)) { if (flags & LIST_RECURSIVE) printf("\n%s:\n", name); return listdir(name, flags); @@ -269,6 +270,8 @@ int ls_main(int argc, char **argv) flags |= LIST_ALL; } else if (!strcmp(argv[i], "-R")) { flags |= LIST_RECURSIVE; + } else if (!strcmp(argv[i], "-d")) { + flags |= LIST_DIRECTORIES; } else { listed++; if(listpath(argv[i], flags) != 0) { diff --git a/toolbox/mkdosfs.c b/toolbox/mkdosfs.c index 744aad1..66e720b 100644 --- a/toolbox/mkdosfs.c +++ b/toolbox/mkdosfs.c @@ -393,7 +393,7 @@ mkdosfs_main(int argc, char *argv[]) bpb.bsec = length / bpb.bps; bpb.spt = bpb.bsec; // use FAT32 for 2 gig or greater - if (length >= 2 *1024 *1024 *1024) { + if (length >= 2LL *1024 *1024 *1024) { fat = 32; } else { fat = 16; diff --git a/toolbox/mount.c b/toolbox/mount.c index ef13e1f..395c943 100644 --- a/toolbox/mount.c +++ b/toolbox/mount.c @@ -138,14 +138,17 @@ do_mount(char *dev, char *dir, char *type, unsigned long rwflag, void *data, int if (loop) { int file_fd, device_fd; + int flags; + + flags = (rwflag & MS_RDONLY) ? O_RDONLY : O_RDWR; // FIXME - only one loop mount supported at a time - file_fd = open(dev, O_RDWR); + file_fd = open(dev, flags); if (file_fd < -1) { perror("open backing file failed"); return 1; } - device_fd = open(LOOP_DEVICE, O_RDWR); + device_fd = open(LOOP_DEVICE, flags); if (device_fd < -1) { perror("open loop device failed"); close(file_fd); diff --git a/toolbox/smd.c b/toolbox/smd.c index 65ff994..91e495c 100644 --- a/toolbox/smd.c +++ b/toolbox/smd.c @@ -1,4 +1,5 @@ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <fcntl.h> #include <errno.h> @@ -250,7 +250,7 @@ static int mmc_bootstrap_mmcblk_partition(char *devpath) char filename[255]; char *uevent_buffer; ssize_t sz; - char *uevent_params[4]; + char *uevent_params[5]; char tmp[255]; FILE *fp; char line[255]; |
