diff options
author | Mathias Agopian <mathias@google.com> | 2009-05-27 14:25:54 -0700 |
---|---|---|
committer | Mathias Agopian <mathias@google.com> | 2009-05-27 14:25:54 -0700 |
commit | 1edfd382ba69ff96ebd0220b05b134a90b910ea7 (patch) | |
tree | 90758d57be56f4c9730ee96b80767920772b8971 | |
parent | 67667115c51693ac27338be2aa7004789b15ff81 (diff) | |
parent | 09555c7a18342390556132f7d050a410d02206ef (diff) | |
download | system_core-1edfd382ba69ff96ebd0220b05b134a90b910ea7.zip system_core-1edfd382ba69ff96ebd0220b05b134a90b910ea7.tar.gz system_core-1edfd382ba69ff96ebd0220b05b134a90b910ea7.tar.bz2 |
Merge commit 'goog/master' into merge_master
48 files changed, 1122 insertions, 538 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b25c15b --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*~ @@ -23,6 +23,7 @@ #include <errno.h> #include <string.h> #include <time.h> +#include <sys/time.h> #include "sysdeps.h" #include "adb.h" @@ -657,10 +658,25 @@ void start_logging(void) void start_device_log(void) { int fd; - char path[100]; + char path[PATH_MAX]; + struct tm now; + time_t t; + char value[PROPERTY_VALUE_MAX]; - snprintf(path, sizeof path, "/data/adb_%ld.txt", (long)time(NULL)); - fd = unix_open(path, O_WRONLY | O_CREAT | O_APPEND, 0640); + // read the trace mask from persistent property persist.adb.trace_mask + // give up if the property is not set or cannot be parsed + property_get("persist.adb.trace_mask", value, ""); + if (sscanf(value, "%x", &adb_trace_mask) != 1) + return; + + adb_mkdir("/data/adb", 0775); + tzset(); + time(&t); + localtime_r(&t, &now); + strftime(path, sizeof(path), + "/data/adb/adb-%Y-%m-%d-%H-%M-%S.txt", + &now); + fd = unix_open(path, O_WRONLY | O_CREAT | O_TRUNC, 0640); if (fd < 0) return; @@ -671,11 +687,6 @@ void start_device_log(void) fd = unix_open("/dev/null", O_RDONLY); dup2(fd, 0); - - // log everything - adb_trace_mask = ~0; - // except TRACE_RWX is a bit too verbose - adb_trace_mask &= ~TRACE_RWX; } #endif @@ -875,9 +886,10 @@ int adb_main(int is_daemon) ** AID_INET to diagnose network issues (netcfg, ping) ** AID_GRAPHICS to access the frame buffer ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump) + ** AID_SDCARD_RW to allow writing to the SD card */ gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS, - AID_NET_BT, AID_NET_BT_ADMIN }; + AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW }; setgroups(sizeof(groups)/sizeof(groups[0]), groups); /* then switch user and group to "shell" */ @@ -919,9 +931,6 @@ int adb_main(int is_daemon) fdevent_loop(); usb_cleanup(); -#if ADB_HOST - usb_vendors_cleanup(); -#endif return 0; } @@ -1081,9 +1090,8 @@ int main(int argc, char **argv) adb_device_banner = "recovery"; recovery_mode = 1; } -#if ADB_DEVICE_LOG + start_device_log(); -#endif return adb_main(0); #endif } @@ -345,11 +345,6 @@ typedef enum { #endif -/* set this to log to /data/adb/adb_<time>.txt on the device. - * has no effect if the /data/adb/ directory does not exist. - */ -#define ADB_DEVICE_LOG 0 - #if !TRACE_PACKETS #define print_packet(tag,p) do {} while (0) #endif @@ -357,11 +352,10 @@ typedef enum { #define ADB_PORT 5037 #define ADB_LOCAL_TRANSPORT_PORT 5555 -// Google's USB Vendor ID -#define VENDOR_ID_GOOGLE 0x18d1 +#define ADB_CLASS 0xff +#define ADB_SUBCLASS 0x42 +#define ADB_PROTOCOL 0x1 -// HTC's USB Vendor ID -#define VENDOR_ID_HTC 0x0bb4 void local_init(); int local_connect(int port); diff --git a/adb/adb_client.c b/adb/adb_client.c index 5868744..243f0fa 100644 --- a/adb/adb_client.c +++ b/adb/adb_client.c @@ -213,7 +213,7 @@ int adb_connect(const char *service) fprintf(stdout,"* daemon started successfully *\n"); } /* give the server some time to start properly and detect devices */ - adb_sleep_ms(2000); + adb_sleep_ms(3000); // fall through to _adb_connect } else { // if server was running, check its version to make sure it is not out of date diff --git a/adb/transport_usb.c b/adb/transport_usb.c index 50ebff7..3737c5c 100644 --- a/adb/transport_usb.c +++ b/adb/transport_usb.c @@ -135,11 +135,9 @@ int is_adb_interface(int vid, int pid, int usb_class, int usb_subclass, int usb_ unsigned i; for (i = 0; i < vendorIdCount; i++) { if (vid == vendorIds[i]) { - /* class:vendor (0xff) subclass:android (0x42) proto:adb (0x01) */ - if(usb_class == 0xff) { - if((usb_subclass == 0x42) && (usb_protocol == 0x01)) { - return 1; - } + if (usb_class == ADB_CLASS && usb_subclass == ADB_SUBCLASS && + usb_protocol == ADB_PROTOCOL) { + return 1; } return 0; diff --git a/adb/usb_osx.c b/adb/usb_osx.c index 171a9fc..4892c38 100644 --- a/adb/usb_osx.c +++ b/adb/usb_osx.c @@ -32,9 +32,6 @@ #define DBG D -#define ADB_SUBCLASS 0x42 -#define ADB_PROTOCOL 0x1 - static IONotificationPortRef notificationPort = 0; static io_iterator_t* notificationIterators; diff --git a/adb/usb_vendors.c b/adb/usb_vendors.c index f949249..9a15146 100644 --- a/adb/usb_vendors.c +++ b/adb/usb_vendors.c @@ -16,25 +16,119 @@ #include "usb_vendors.h" -#include "sysdeps.h" #include <stdio.h> + +#ifdef _WIN32 +# define WIN32_LEAN_AND_MEAN +# include "windows.h" +# include "shlobj.h" +#else +# include <unistd.h> +# include <sys/stat.h> +#endif + +#include "sysdeps.h" #include "adb.h" -int* vendorIds = NULL; +#define ANDROID_PATH ".android" +#define ANDROID_ADB_INI "adb_usb.ini" + +#define TRACE_TAG TRACE_USB + +// Google's USB Vendor ID +#define VENDOR_ID_GOOGLE 0x18d1 +// HTC's USB Vendor ID +#define VENDOR_ID_HTC 0x0bb4 + +/** built-in vendor list */ +int builtInVendorIds[] = { + VENDOR_ID_GOOGLE, + VENDOR_ID_HTC, +}; + +#define BUILT_IN_VENDOR_COUNT (sizeof(builtInVendorIds)/sizeof(builtInVendorIds[0])) + +/* max number of supported vendor ids (built-in + 3rd party). increase as needed */ +#define VENDOR_COUNT_MAX 128 + +int vendorIds[VENDOR_COUNT_MAX]; unsigned vendorIdCount = 0; -void usb_vendors_init(void) { - /* for now, only put the built-in VENDOR_ID_* */ - vendorIdCount = 2; - vendorIds = (int*)malloc(vendorIdCount * sizeof(int)); - vendorIds[0] = VENDOR_ID_GOOGLE; - vendorIds[1] = VENDOR_ID_HTC; +int get_adb_usb_ini(char* buff, size_t len); + +void usb_vendors_init(void) +{ + if (VENDOR_COUNT_MAX < BUILT_IN_VENDOR_COUNT) { + fprintf(stderr, "VENDOR_COUNT_MAX not big enough for built-in vendor list.\n"); + exit(2); + } + + /* add the built-in vendors at the beginning of the array */ + memcpy(vendorIds, builtInVendorIds, sizeof(builtInVendorIds)); + + /* default array size is the number of built-in vendors */ + vendorIdCount = BUILT_IN_VENDOR_COUNT; + + if (VENDOR_COUNT_MAX == BUILT_IN_VENDOR_COUNT) + return; + + char temp[PATH_MAX]; + if (get_adb_usb_ini(temp, sizeof(temp)) == 0) { + FILE * f = fopen(temp, "rt"); + + if (f != NULL) { + /* The vendor id file is pretty basic. 1 vendor id per line. + Lines starting with # are comments */ + while (fgets(temp, sizeof(temp), f) != NULL) { + if (temp[0] == '#') + continue; + + long value = strtol(temp, NULL, 0); + if (errno == EINVAL || errno == ERANGE || value > INT_MAX || value < 0) { + fprintf(stderr, "Invalid content in %s. Quitting.\n", ANDROID_ADB_INI); + exit(2); + } + + vendorIds[vendorIdCount++] = (int)value; + + /* make sure we don't go beyond the array */ + if (vendorIdCount == VENDOR_COUNT_MAX) { + break; + } + } + } + } } -void usb_vendors_cleanup(void) { - if (vendorIds != NULL) { - free(vendorIds); - vendorIds = NULL; - vendorIdCount = 0; +/* Utils methods */ + +/* builds the path to the adb vendor id file. returns 0 if success */ +int build_path(char* buff, size_t len, const char* format, const char* home) +{ + if (snprintf(buff, len, format, home, ANDROID_PATH, ANDROID_ADB_INI) >= len) { + return 1; + } + + return 0; +} + +/* fills buff with the path to the adb vendor id file. returns 0 if success */ +int get_adb_usb_ini(char* buff, size_t len) +{ +#ifdef _WIN32 + const char* home = getenv("ANDROID_SDK_HOME"); + if (home != NULL) { + return build_path(buff, len, "%s\\%s\\%s", home); + } else { + char path[MAX_PATH]; + SHGetFolderPath( NULL, CSIDL_PROFILE, NULL, 0, path); + return build_path(buff, len, "%s\\%s\\%s", path); } +#else + const char* home = getenv("HOME"); + if (home == NULL) + home = "/tmp"; + + return build_path(buff, len, "%s/%s/%s", home); +#endif } diff --git a/adb/usb_vendors.h b/adb/usb_vendors.h index 43e5f99..43790b9 100644 --- a/adb/usb_vendors.h +++ b/adb/usb_vendors.h @@ -17,10 +17,9 @@ #ifndef __USB_VENDORS_H #define __USB_VENDORS_H -extern int* vendorIds; +extern int vendorIds[]; extern unsigned vendorIdCount; void usb_vendors_init(void); -void usb_vendors_cleanup(void); #endif
\ No newline at end of file diff --git a/include/acc/acc.h b/include/acc/acc.h new file mode 100644 index 0000000..054d6a0 --- /dev/null +++ b/include/acc/acc.h @@ -0,0 +1,78 @@ +/* + * Copyright (C) 2009 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. + */ + +#ifndef ANDROID_ACC_ACC_H +#define ANDROID_ACC_ACC_H + +#include <stdint.h> +#include <sys/types.h> + +typedef char ACCchar; +typedef int32_t ACCint; +typedef uint32_t ACCuint; +typedef ssize_t ACCsizei; +typedef unsigned int ACCenum; +typedef void ACCvoid; +typedef struct ACCscript ACCscript; + +#define ACC_NO_ERROR 0x0000 +#define ACC_INVALID_ENUM 0x0500 +#define ACC_INVALID_OPERATION 0x0502 +#define ACC_INVALID_VALUE 0x0501 +#define ACC_OUT_OF_MEMORY 0x0505 + +#define ACC_COMPILE_STATUS 0x8B81 +#define ACC_INFO_LOG_LENGTH 0x8B84 + + +// ---------------------------------------------------------------------------- + +#ifdef __cplusplus +extern "C" { +#endif + +ACCscript* accCreateScript(); + +void accDeleteScript(ACCscript* script); + +ACCenum accGetError( ACCscript* script ); + +void accScriptSource(ACCscript* script, + ACCsizei count, + const ACCchar** string, + const ACCint* length); + +void accCompileScript(ACCscript* script); + +void accGetScriptiv(ACCscript* script, + ACCenum pname, + ACCint* params); + +void accGetScriptInfoLog(ACCscript* script, + ACCsizei maxLength, + ACCsizei* length, + ACCchar* infoLog); + +void accGetScriptLabel(ACCscript* script, const ACCchar * name, + ACCvoid** address); + +#ifdef __cplusplus +}; +#endif + +// ---------------------------------------------------------------------------- + +#endif diff --git a/init/devices.c b/init/devices.c index 300faab..04ada63 100644 --- a/init/devices.c +++ b/init/devices.c @@ -115,6 +115,7 @@ static struct perms_ devperms[] = { { "/dev/oncrpc/", 0660, AID_ROOT, AID_SYSTEM, 1 }, { "/dev/adsp/", 0660, AID_SYSTEM, AID_AUDIO, 1 }, { "/dev/mt9t013", 0660, AID_SYSTEM, AID_SYSTEM, 0 }, + { "/dev/msm_camera/", 0660, AID_SYSTEM, AID_SYSTEM, 1 }, { "/dev/akm8976_daemon",0640, AID_COMPASS, AID_SYSTEM, 0 }, { "/dev/akm8976_aot", 0640, AID_COMPASS, AID_SYSTEM, 0 }, { "/dev/akm8976_pffd", 0640, AID_COMPASS, AID_SYSTEM, 0 }, @@ -384,7 +385,10 @@ static void handle_device_event(struct uevent *uevent) } else if (!strncmp(uevent->subsystem, "adsp", 4)) { base = "/dev/adsp/"; mkdir(base, 0755); - } else if(!strncmp(uevent->subsystem, "input", 5)) { + } else if (!strncmp(uevent->subsystem, "msm_camera", 10)) { + base = "/dev/msm_camera/"; + mkdir(base, 0755); + } else if(!strncmp(uevent->subsystem, "input", 5)) { base = "/dev/input/"; mkdir(base, 0755); } else if(!strncmp(uevent->subsystem, "mtd", 3)) { diff --git a/libacc/Android.mk b/libacc/Android.mk index c3207cc..77c71c6 100644 --- a/libacc/Android.mk +++ b/libacc/Android.mk @@ -5,8 +5,15 @@ include $(CLEAR_VARS) # Shared library # -LOCAL_MODULE:= acc -LOCAL_SRC_FILES := acc.cpp disassem.cpp -LOCAL_MODULE_TAGS := tests +LOCAL_MODULE:= libacc +LOCAL_SRC_FILES := acc.cpp -include $(BUILD_EXECUTABLE) +ifeq ($(TARGET_ARCH),arm) +LOCAL_SRC_FILES += disassem.cpp +endif + +LOCAL_SHARED_LIBRARIES := libdl + +include $(BUILD_SHARED_LIBRARY) + +include $(call all-makefiles-under,$(LOCAL_PATH))
\ No newline at end of file diff --git a/libacc/LICENSE b/libacc/LICENSE new file mode 100644 index 0000000..aea41e0 --- /dev/null +++ b/libacc/LICENSE @@ -0,0 +1,21 @@ + 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. + + diff --git a/libacc/acc.cpp b/libacc/acc.cpp index 04d45d5..b7e4594 100644 --- a/libacc/acc.cpp +++ b/libacc/acc.cpp @@ -4,33 +4,10 @@ * in scripting environments where speed and memory footprint are important. * * This code is based upon the "unobfuscated" version of the - * Obfuscated Tiny C compiler, and retains the - * original copyright notice and license from that compiler, see below. + * Obfuscated Tiny C compiler, see the file LICENSE for details. * */ -/* - 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> @@ -59,6 +36,13 @@ #include "disassem.h" #endif +#include <acc/acc.h> + +#define LOG_API(...) do {} while(0) +// #define LOG_API(...) fprintf (stderr, __VA_ARGS__) + +// #define ENABLE_ARM_DISASSEMBLY + namespace acc { class Compiler { @@ -116,6 +100,27 @@ class Compiler { } }; + /** + * A code generator creates an in-memory program, generating the code on + * the fly. There is one code generator implementation for each supported + * architecture. + * + * The code generator implements the following abstract machine: + * R0 - the main accumulator. + * R1 - the secondary accumulator. + * FP - a frame pointer for accessing function arguments and local + * variables. + * SP - a stack pointer for storing intermediate results while evaluating + * expressions. The stack pointer grows downwards. + * + * The function calling convention is that all arguments are placed on the + * stack such that the first argument has the lowest address. + * After the call, the result is in R0. The caller is responsible for + * removing the arguments from the stack. + * The R0 and R1 registers are not saved across function calls. The + * FP and SP registers are saved. + */ + class CodeGenerator { public: CodeGenerator() {} @@ -125,70 +130,170 @@ class Compiler { this->pCodeBuf = pCodeBuf; } - /* returns address to patch with local variable size + /* Emit a function prolog. + * argCount is the number of arguments. + * Save the old value of the FP. + * Set the new value of the FP. + * Convert from the native platform calling convention to + * our stack-based calling convention. This may require + * pushing arguments from registers to the stack. + * Allocate "N" bytes of stack space. N isn't known yet, so + * just emit the instructions for adjusting the stack, and return + * the address to patch up. The patching will be done in + * functionExit(). + * returns address to patch with local variable size. */ virtual int functionEntry(int argCount) = 0; - virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) = 0; + /* Emit a function epilog. + * Restore the old SP and FP register values. + * Return to the calling function. + * argCount - the number of arguments to the function. + * localVariableAddress - returned from functionEntry() + * localVariableSize - the size in bytes of the local variables. + */ + virtual void functionExit(int argCount, int localVariableAddress, + int localVariableSize) = 0; - /* load immediate value */ + /* load immediate value to R0 */ virtual void li(int t) = 0; + /* Jump to a target, and return the address of the word that + * holds the target data, in case it needs to be fixed up later. + */ virtual int gjmp(int t) = 0; - /* l = 0: je, l == 1: jne */ + /* Test R0 and jump to a target if the test succeeds. + * l = 0: je, l == 1: jne + * Return the address of the word that holds the targed data, in + * case it needs to be fixed up later. + */ virtual int gtst(bool l, int t) = 0; + /* Compare R1 against R0, and store the boolean result in R0. + * op specifies the comparison. + */ virtual void gcmp(int op) = 0; + /* Perform the arithmetic op specified by op. R1 is the + * left argument, R0 is the right argument. + */ virtual void genOp(int op) = 0; - virtual void clearECX() = 0; - - virtual void pushEAX() = 0; + /* Set R1 to 0. + */ + virtual void clearR1() = 0; - virtual void popECX() = 0; + /* Push R0 onto the stack. + */ + virtual void pushR0() = 0; - virtual void storeEAXToAddressECX(bool isInt) = 0; + /* Pop R1 off of the stack. + */ + virtual void popR1() = 0; - virtual void loadEAXIndirect(bool isInt) = 0; + /* Store R0 to the address stored in R1. + * isInt is true if a whole 4-byte integer value + * should be stored, otherwise a 1-byte character + * value should be stored. + */ + virtual void storeR0ToR1(bool isInt) = 0; - virtual void leaEAX(int ea) = 0; + /* Load R0 from the address stored in R0. + * isInt is true if a whole 4-byte integer value + * should be loaded, otherwise a 1-byte character + * value should be loaded. + */ + virtual void loadR0FromR0(bool isInt) = 0; - virtual void storeEAX(int ea) = 0; + /* Load the absolute address of a variable to R0. + * If ea <= LOCAL, then this is a local variable, or an + * argument, addressed relative to FP. + * else it is an absolute global address. + */ + virtual void leaR0(int ea) = 0; - virtual void loadEAX(int ea, bool isIncDec, int op) = 0; + /* Store R0 to a variable. + * If ea <= LOCAL, then this is a local variable, or an + * argument, addressed relative to FP. + * else it is an absolute global address. + */ + virtual void storeR0(int ea) = 0; + + /* load R0 from a variable. + * If ea <= LOCAL, then this is a local variable, or an + * argument, addressed relative to FP. + * else it is an absolute global address. + * If isIncDec is true, then the stored variable's value + * should be post-incremented or post-decremented, based + * on the value of op. + */ + virtual void loadR0(int ea, bool isIncDec, int op) = 0; + /* Emit code to adjust the stack for a function call. Return the + * label for the address of the instruction that adjusts the + * stack size. This will be passed as argument "a" to + * endFunctionCallArguments. + */ virtual int beginFunctionCallArguments() = 0; - virtual void storeEAToArg(int l) = 0; - + /* Emit code to store R0 to the stack at byte offset l. + */ + virtual void storeR0ToArg(int l) = 0; + + /* Patch the function call preamble. + * a is the address returned from beginFunctionCallArguments + * l is the number of bytes the arguments took on the stack. + * Typically you would also emit code to convert the argument + * list into whatever the native function calling convention is. + * On ARM for example you would pop the first 5 arguments into + * R0..R4 + */ virtual void endFunctionCallArguments(int a, int l) = 0; - + /* Emit a call to an unknown function. The argument "symbol" needs to + * be stored in the location where the address should go. It forms + * a chain. The address will be patched later. + * Return the address of the word that has to be patched. + */ virtual int callForward(int symbol) = 0; + /* Call a function using PC-relative addressing. t is the PC-relative + * address of the function. It has already been adjusted for the + * architectural jump offset, so just store it as-is. + */ virtual void callRelative(int t) = 0; + /* Call a function pointer. L is the number of bytes the arguments + * take on the stack. The address of the function is stored at + * location SP + l. + */ virtual void callIndirect(int l) = 0; + /* Adjust SP after returning from a function call. l is the + * number of bytes of arguments stored on the stack. isIndirect + * is true if this was an indirect call. (In which case the + * address of the function is stored at location SP + l.) + */ virtual void adjustStackAfterCall(int l, bool isIndirect) = 0; + /* Print a disassembly of the assembled code to out. Return + * non-zero if there is an error. + */ virtual int disassemble(FILE* out) = 0; - /* output a symbol and patch all calls to it */ + /* Generate a symbol at the current PC. t is the head of a + * linked list of addresses to patch. + */ virtual void gsym(int t) = 0; - virtual int finishCompile() { -#if defined(__arm__) - const long base = long(pCodeBuf->getBase()); - const long curr = base + long(pCodeBuf->getSize()); - int err = cacheflush(base, curr, 0); - return err; -#else - return 0; -#endif - } + /* + * Do any cleanup work required at the end of a compile. + * For example, an instruction cache might need to be + * invalidated. + * Return non-zero if there is an error. + */ + virtual int finishCompile() = 0; /** * Adjust relative branches by this amount. @@ -214,6 +319,10 @@ class Compiler { intptr_t getPC() { return pCodeBuf->getPC(); } + + intptr_t getSize() { + return pCodeBuf->getSize(); + } private: CodeBuf* pCodeBuf; }; @@ -228,7 +337,7 @@ class Compiler { /* returns address to patch with local variable size */ virtual int functionEntry(int argCount) { - fprintf(stderr, "functionEntry(%d);\n", argCount); + LOG_API(stderr, "functionEntry(%d);\n", argCount); // sp -> arg4 arg5 ... // Push our register-based arguments back on the stack if (argCount > 0) { @@ -243,7 +352,7 @@ class Compiler { } virtual void functionExit(int argCount, int localVariableAddress, int localVariableSize) { - fprintf(stderr, "functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); + LOG_API("functionExit(%d, %d, %d);\n", argCount, localVariableAddress, localVariableSize); // Patch local variable allocation code: if (localVariableSize < 0 || localVariableSize > 255) { error("localVariables out of range: %d", localVariableSize); @@ -270,7 +379,7 @@ class Compiler { /* load immediate value */ virtual void li(int t) { - fprintf(stderr, "li(%d);\n", t); + LOG_API("li(%d);\n", t); if (t >= 0 && t < 255) { o4(0xE3A00000 + t); // mov r0, #0 } else if (t >= -256 && t < 0) { @@ -285,20 +394,20 @@ class Compiler { } virtual int gjmp(int t) { - fprintf(stderr, "gjmp(%d);\n", t); + LOG_API("gjmp(%d);\n", t); return o4(0xEA000000 | encodeAddress(t)); // b .L33 } /* l = 0: je, l == 1: jne */ virtual int gtst(bool l, int t) { - fprintf(stderr, "gtst(%d, %d);\n", l, t); + LOG_API("gtst(%d, %d);\n", l, t); o4(0xE3500000); // cmp r0,#0 int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq return o4(branch | encodeAddress(t)); } virtual void gcmp(int op) { - fprintf(stderr, "gcmp(%d);\n", op); + LOG_API("gcmp(%d);\n", op); o4(0xE1510000); // cmp r1, r1 switch(op) { case OP_EQUALS: @@ -332,7 +441,7 @@ class Compiler { } virtual void genOp(int op) { - fprintf(stderr, "genOp(%d);\n", op); + LOG_API("genOp(%d);\n", op); switch(op) { case OP_MUL: o4(0x0E0000091); // mul r0,r1,r0 @@ -378,23 +487,23 @@ class Compiler { #endif } - virtual void clearECX() { - fprintf(stderr, "clearECX();\n"); + virtual void clearR1() { + LOG_API("clearR1();\n"); o4(0xE3A01000); // mov r1, #0 } - virtual void pushEAX() { - fprintf(stderr, "pushEAX();\n"); + virtual void pushR0() { + LOG_API("pushR0();\n"); o4(0xE92D0001); // stmfd sp!,{r0} } - virtual void popECX() { - fprintf(stderr, "popECX();\n"); + virtual void popR1() { + LOG_API("popR1();\n"); o4(0xE8BD0002); // ldmfd sp!,{r1} } - virtual void storeEAXToAddressECX(bool isInt) { - fprintf(stderr, "storeEAXToAddressECX(%d);\n", isInt); + virtual void storeR0ToR1(bool isInt) { + LOG_API("storeR0ToR1(%d);\n", isInt); if (isInt) { o4(0xE5810000); // str r0, [r1] } else { @@ -402,16 +511,16 @@ class Compiler { } } - virtual void loadEAXIndirect(bool isInt) { - fprintf(stderr, "loadEAXIndirect(%d);\n", isInt); + virtual void loadR0FromR0(bool isInt) { + LOG_API("loadR0FromR0(%d);\n", isInt); if (isInt) o4(0xE5900000); // ldr r0, [r0] else o4(0xE5D00000); // ldrb r0, [r0] } - virtual void leaEAX(int ea) { - fprintf(stderr, "leaEAX(%d);\n", ea); + virtual void leaR0(int ea) { + LOG_API("leaR0(%d);\n", ea); if (ea < LOCAL) { // Local, fp relative if (ea < -1023 || ea > 1023 || ((ea & 3) != 0)) { @@ -431,8 +540,8 @@ class Compiler { } } - virtual void storeEAX(int ea) { - fprintf(stderr, "storeEAX(%d);\n", ea); + virtual void storeR0(int ea) { + LOG_API("storeR0(%d);\n", ea); if (ea < LOCAL) { // Local, fp relative if (ea < -4095 || ea > 4095) { @@ -452,8 +561,8 @@ class Compiler { } } - virtual void loadEAX(int ea, bool isIncDec, int op) { - fprintf(stderr, "loadEAX(%d, %d, %d);\n", ea, isIncDec, op); + virtual void loadR0(int ea, bool isIncDec, int op) { + LOG_API("loadR0(%d, %d, %d);\n", ea, isIncDec, op); if (ea < LOCAL) { // Local, fp relative if (ea < -4095 || ea > 4095) { @@ -500,12 +609,12 @@ class Compiler { } virtual int beginFunctionCallArguments() { - fprintf(stderr, "beginFunctionCallArguments();\n"); + LOG_API("beginFunctionCallArguments();\n"); return o4(0xE24DDF00); // Placeholder } - virtual void storeEAToArg(int l) { - fprintf(stderr, "storeEAToArg(%d);\n", l); + virtual void storeR0ToArg(int l) { + LOG_API("storeR0ToArg(%d);\n", l); if (l < 0 || l > 4096-4) { error("l out of range for stack offset: 0x%08x", l); } @@ -513,7 +622,7 @@ class Compiler { } virtual void endFunctionCallArguments(int a, int l) { - fprintf(stderr, "endFunctionCallArguments(0x%08x, %d);\n", a, l); + LOG_API("endFunctionCallArguments(0x%08x, %d);\n", a, l); if (l < 0 || l > 0x3FC) { error("L out of range for stack adjustment: 0x%08x", l); } @@ -526,13 +635,13 @@ class Compiler { } virtual int callForward(int symbol) { - fprintf(stderr, "callForward(%d);\n", symbol); + LOG_API("callForward(%d);\n", symbol); // Forward calls are always short (local) return o4(0xEB000000 | encodeAddress(symbol)); } virtual void callRelative(int t) { - fprintf(stderr, "callRelative(%d);\n", t); + LOG_API("callRelative(%d);\n", t); int abs = t + getPC() + jumpOffset(); fprintf(stderr, "abs=%d (0x%08x)\n", abs, abs); if (t >= - (1 << 25) && t < (1 << 25)) { @@ -548,7 +657,7 @@ class Compiler { } virtual void callIndirect(int l) { - fprintf(stderr, "callIndirect(%d);\n", l); + LOG_API("callIndirect(%d);\n", l); int argCount = l >> 2; int poppedArgs = argCount > 4 ? 4 : argCount; int adjustedL = l - (poppedArgs << 2); @@ -560,7 +669,7 @@ class Compiler { } virtual void adjustStackAfterCall(int l, bool isIndirect) { - fprintf(stderr, "adjustStackAfterCall(%d, %d);\n", l, isIndirect); + LOG_API("adjustStackAfterCall(%d, %d);\n", l, isIndirect); int argCount = l >> 2; int stackArgs = argCount > 4 ? argCount - 4 : 0; int stackUse = stackArgs + (isIndirect ? 1 : 0); @@ -578,11 +687,11 @@ class Compiler { /* output a symbol and patch all calls to it */ virtual void gsym(int t) { - fprintf(stderr, "gsym(0x%x)\n", t); + LOG_API("gsym(0x%x)\n", t); int n; int base = getBase(); int pc = getPC(); - fprintf(stderr, "pc = 0x%x\n", pc); + LOG_API("pc = 0x%x\n", pc); while (t) { int data = * (int*) t; int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2); @@ -597,8 +706,20 @@ class Compiler { } } + virtual int finishCompile() { +#if defined(__arm__) + const long base = long(getBase()); + const long curr = long(getPC()); + int err = cacheflush(base, curr, 0); + return err; +#else + return 0; +#endif + } + virtual int disassemble(FILE* out) { - disasmOut = out; +#ifdef ENABLE_ARM_DISASSEMBLY + disasmOut = out; disasm_interface_t di; di.di_readword = disassemble_readword; di.di_printaddr = disassemble_printaddr; @@ -610,6 +731,7 @@ class Compiler { fprintf(out, "%08x: %08x ", i, *(int*) i); ::disasm(&di, i, 0); } +#endif return 0; } @@ -679,7 +801,7 @@ class Compiler { } }; -#endif // PROVIDE_X86_CODEGEN +#endif // PROVIDE_ARM_CODEGEN #ifdef PROVIDE_X86_CODEGEN @@ -730,23 +852,23 @@ class Compiler { o(0x92); /* xchg %edx, %eax */ } - virtual void clearECX() { + virtual void clearR1() { oad(0xb9, 0); /* movl $0, %ecx */ } - virtual void pushEAX() { + virtual void pushR0() { o(0x50); /* push %eax */ } - virtual void popECX() { + virtual void popR1() { o(0x59); /* pop %ecx */ } - virtual void storeEAXToAddressECX(bool isInt) { + virtual void storeR0ToR1(bool isInt) { o(0x0188 + isInt); /* movl %eax/%al, (%ecx) */ } - virtual void loadEAXIndirect(bool isInt) { + virtual void loadR0FromR0(bool isInt) { if (isInt) o(0x8b); /* mov (%eax), %eax */ else @@ -754,15 +876,15 @@ class Compiler { ob(0); /* add zero in code */ } - virtual void leaEAX(int ea) { + virtual void leaR0(int ea) { gmov(10, ea); /* leal EA, %eax */ } - virtual void storeEAX(int ea) { + virtual void storeR0(int ea) { gmov(6, ea); /* mov %eax, EA */ } - virtual void loadEAX(int ea, bool isIncDec, int op) { + virtual void loadR0(int ea, bool isIncDec, int op) { gmov(8, ea); /* mov EA, %eax */ if (isIncDec) { /* Implement post-increment or post decrement. @@ -776,7 +898,7 @@ class Compiler { return oad(0xec81, 0); /* sub $xxx, %esp */ } - virtual void storeEAToArg(int l) { + virtual void storeR0ToArg(int l) { oad(0x248489, l); /* movl %eax, xxx(%esp) */ } @@ -808,7 +930,7 @@ class Compiler { } virtual int disassemble(FILE* out) { - return 1; + return 0; } /* output a symbol and patch all calls to it */ @@ -822,6 +944,10 @@ class Compiler { } } + virtual int finishCompile() { + return 0; + } + private: /** Output 1 to 4 bytes. @@ -868,6 +994,39 @@ class Compiler { #endif // PROVIDE_X86_CODEGEN + class InputStream { + public: + virtual int get() = 0; + virtual long tell() = 0; + }; + + class FileInputStream : public InputStream { + public: + FileInputStream(FILE* in) : f(in) {} + virtual int get() { return fgetc(f); } + virtual long tell() { return ftell(f); } + private: + FILE* f; + }; + + class TextInputStream : public InputStream { + public: + TextInputStream(const char* text, size_t textLength) + : pText(text), mTextLength(textLength), mPosition(0) { + } + virtual int get() { + return mPosition < mTextLength ? pText[mPosition++] : EOF; + } + virtual long tell() { + return mPosition; + } + + private: + const char* pText; + size_t mTextLength; + size_t mPosition; + }; + /* vars: value of variables loc : local variable index glo : global variable index @@ -882,7 +1041,8 @@ class Compiler { void* pSymbolBase; void* pGlobalBase; void* pVarsBase; - FILE* file; + + InputStream* file; CodeBuf codeBuf; CodeGenerator* pGen; @@ -957,7 +1117,7 @@ class Compiler { ch = dch; } } else - ch = fgetc(file); + ch = file->get(); /* printf("ch=%c 0x%x\n", ch, ch); */ } @@ -1108,7 +1268,7 @@ class Compiler { va_list ap; va_start(ap, fmt); - fprintf(stderr, "%ld: ", ftell((FILE *) file)); + fprintf(stderr, "%ld: ", file->tell()); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -1149,7 +1309,7 @@ class Compiler { } else if (c == 2) { /* -, +, !, ~ */ unary(0); - pGen->clearECX(); + pGen->clearR1(); if (t == '!') pGen->gcmp(a); else @@ -1175,15 +1335,15 @@ class Compiler { unary(0); if (tok == '=') { next(); - pGen->pushEAX(); + pGen->pushR0(); expr(); - pGen->popECX(); - pGen->storeEAXToAddressECX(t == TOK_INT); + pGen->popR1(); + pGen->storeR0ToR1(t == TOK_INT); } else if (t) { - pGen->loadEAXIndirect(t == TOK_INT); + pGen->loadR0FromR0(t == TOK_INT); } } else if (t == '&') { - pGen->leaEAX(*(int *) tok); + pGen->leaR0(*(int *) tok); next(); } else { n = *(int *) t; @@ -1195,10 +1355,10 @@ class Compiler { /* assignment */ next(); expr(); - pGen->storeEAX(n); + pGen->storeR0(n); } else if (tok != '(') { /* variable */ - pGen->loadEAX(n, tokl == 11, tokc); + pGen->loadR0(n, tokl == 11, tokc); if (tokl == 11) { next(); } @@ -1209,7 +1369,7 @@ class Compiler { /* function call */ if (tok == '(') { if (n == 1) - pGen->pushEAX(); + pGen->pushR0(); /* push args and invert order */ a = pGen->beginFunctionCallArguments(); @@ -1217,7 +1377,7 @@ class Compiler { l = 0; while (tok != ')') { expr(); - pGen->storeEAToArg(l); + pGen->storeR0ToArg(l); if (tok == ',') next(); l = l + 4; @@ -1255,9 +1415,9 @@ class Compiler { a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ sum(l); } else { - pGen->pushEAX(); + pGen->pushR0(); sum(l); - pGen->popECX(); + pGen->popR1(); if ((l == 4) | (l == 5)) { pGen->gcmp(t); @@ -1420,6 +1580,10 @@ class Compiler { delete pGen; pGen = 0; } + if (file) { + delete file; + file = 0; + } } void clear() { @@ -1470,7 +1634,7 @@ class Compiler { #endif } if (pGen == NULL) { - fprintf(stderr, "No code generator defined."); + fprintf(stderr, "No code generator defined.\n"); } } @@ -1490,16 +1654,16 @@ public: cleanup(); } - int compile(FILE* in, args& args) { + int compile(const char* text, size_t textLength) { cleanup(); clear(); codeBuf.init(ALLOC_SIZE); - setArchitecture(args.architecture); + setArchitecture(NULL); if (!pGen) { return -1; } pGen->init(&codeBuf); - file = in; + file = new TextInputStream(text, textLength); sym_stk = (intptr_t) calloc(1, ALLOC_SIZE); dstk = (intptr_t) strcpy((char*) sym_stk, " int if else while break return for define main ") @@ -1534,6 +1698,38 @@ public: return pGen->disassemble(out); } + /* Look through the symbol table to find a symbol. + * If found, return its value. + */ + void* lookup(const char* name) { + if (!sym_stk) { + return NULL; + } + size_t nameLen = strlen(name); + char* pSym = (char*) sym_stk; + char c; + for(;;) { + c = *pSym++; + if (c == 0) { + break; + } + if (c == TAG_TOK) { + if (memcmp(pSym, name, nameLen) == 0 + && pSym[nameLen] == TAG_TOK) { + int tok = pSym - 1 - (char*) sym_stk; + tok = tok * 8 + TOK_IDENT; + if (tok <= TOK_DEFINE) { + return 0; + } else { + tok = vars + tok; + return * (void**) tok; + } + } + } + } + return NULL; + } + }; const char* Compiler::operatorChars = @@ -1578,96 +1774,130 @@ const int Compiler::X86CodeGenerator::operatorHelper[] = { }; #endif -} // namespace acc +struct ACCscript { + ACCscript() { + text = 0; + textLength = 0; + accError = ACC_NO_ERROR; + } -// This is a separate function so it can easily be set by breakpoint in gdb. -int run(acc::Compiler& c, int argc, char** argv) { - return c.run(argc, argv); -} + ~ACCscript() { + delete text; + } -int main(int argc, char** argv) { - bool doDump = false; - bool doDisassemble = false; - const char* inFile = NULL; - const char* outFile = NULL; - const char* architecture = NULL; - int i; - for (i = 1; i < argc; i++) { - char* arg = argv[i]; - if (arg[0] == '-') { - switch (arg[1]) { - case 'a': - if (i + 1 >= argc) { - fprintf(stderr, "Expected architecture after -a\n"); - return 2; - } - architecture = argv[i+1]; - i += 1; - break; - case 'd': - if (i + 1 >= argc) { - fprintf(stderr, "Expected filename after -d\n"); - return 2; - } - doDump = true; - outFile = argv[i + 1]; - i += 1; - break; - case 'S': - doDisassemble = true; - break; - default: - fprintf(stderr, "Unrecognized flag %s\n", arg); - return 3; - } - } else if (inFile == NULL) { - inFile = arg; - } else { - break; + void setError(ACCenum error) { + if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) { + accError = error; } } - FILE* in = stdin; - if (inFile) { - in = fopen(inFile, "r"); - if (!in) { - fprintf(stderr, "Could not open input file %s\n", inFile); - return 1; - } + ACCenum getError() { + ACCenum result = accError; + accError = ACC_NO_ERROR; + return result; } - acc::Compiler compiler; - acc::Compiler::args args; - if (architecture != NULL) { - args.architecture = architecture; + + Compiler compiler; + char* text; + int textLength; + ACCenum accError; +}; + + +extern "C" +ACCscript* accCreateScript() { + return new ACCscript(); +} + +extern "C" +ACCenum accGetError( ACCscript* script ) { + return script->getError(); +} + +extern "C" +void accDeleteScript(ACCscript* script) { + delete script; +} + +extern "C" +void accScriptSource(ACCscript* script, + ACCsizei count, + const ACCchar ** string, + const ACCint * length) { + int totalLength = 0; + for(int i = 0; i < count; i++) { + int len = -1; + const ACCchar* s = string[i]; + if (length) { + len = length[i]; + } + if (len < 0) { + len = strlen(s); + } + totalLength += len; } - int compileResult = compiler.compile(in, args); - if (in != stdin) { - fclose(in); + delete script->text; + char* text = new char[totalLength + 1]; + script->text = text; + script->textLength = totalLength; + char* dest = text; + for(int i = 0; i < count; i++) { + int len = -1; + const ACCchar* s = string[i]; + if (length) { + len = length[i]; + } + if (len < 0) { + len = strlen(s); + } + memcpy(dest, s, len); + dest += len; } - if (compileResult) { - fprintf(stderr, "Compile failed: %d\n", compileResult); - return 6; + text[totalLength] = '\0'; +} + +extern "C" +void accCompileScript(ACCscript* script) { + int result = script->compiler.compile(script->text, script->textLength); + if (result) { + script->setError(ACC_INVALID_OPERATION); } - if (doDisassemble) { - compiler.disassemble(stderr); +} + +extern "C" +void accGetScriptiv(ACCscript* script, + ACCenum pname, + ACCint * params) { + switch (pname) { + case ACC_INFO_LOG_LENGTH: + *params = 0; + break; } - if (doDump) { - 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"); - int result = run(compiler, codeArgc, codeArgv); - fprintf(stderr, "result: %d\n", result); - return result; +} + +extern "C" +void accGetScriptInfoLog(ACCscript* script, + ACCsizei maxLength, + ACCsizei * length, + ACCchar * infoLog) { + if (length) { + *length = 0; + } + if (maxLength > 0 && infoLog) { + *infoLog = 0; } +} - return 0; +extern "C" +void accGetScriptLabel(ACCscript* script, const ACCchar * name, + ACCvoid ** address) { + void* value = script->compiler.lookup(name); + if (value) { + *address = value; + } else { + script->setError(ACC_INVALID_VALUE); + } } + +} // namespace acc + diff --git a/libacc/test b/libacc/test deleted file mode 100755 index 28b7655..0000000 --- a/libacc/test +++ /dev/null @@ -1,13 +0,0 @@ -#!/bin/sh -rm -f tests/acc -g++ acc.cpp disassem.cpp -g -ldl -o tests/acc && tests/acc tests/otcc.c -a x86 -d tests/otcc.out && diff tests/otcc.out tests/otcc.out-orig -if [ -x "tests/acc" ]; then - tests/acc -S tests/returnval.c - - if [ "$(uname)" = "Linux" ]; then - if [ "$(uname -m)" = "i686" ]; then - echo "Linux i686. Testing otcc.c" - tests/acc tests/otcc.c tests/otcc.c tests/returnval.c - fi - fi -fi diff --git a/libacc/testarm b/libacc/testarm deleted file mode 100755 index d1a442e..0000000 --- a/libacc/testarm +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -adb remount -adb push tests/returnval.c /system/bin/returnval.c -mm -j8 && adb sync && adb shell /system/bin/acc -S /system/bin/returnval.c diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore index 9974532..a26b298 100644 --- a/libacc/tests/.gitignore +++ b/libacc/tests/.gitignore @@ -1,2 +1,2 @@ -acc +test-acc *.out diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk new file mode 100644 index 0000000..2cff9d3 --- /dev/null +++ b/libacc/tests/Android.mk @@ -0,0 +1,15 @@ +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES:= \ + main.cpp + +LOCAL_SHARED_LIBRARIES := \ + libacc + +LOCAL_MODULE:= acc + +LOCAL_MODULE_TAGS := tests + +include $(BUILD_EXECUTABLE) + diff --git a/libacc/tests/bellard.otccex.c b/libacc/tests/data/bellard.otccex.c index e8f0989..e8f0989 100644 --- a/libacc/tests/bellard.otccex.c +++ b/libacc/tests/data/bellard.otccex.c diff --git a/libacc/tests/expr.c b/libacc/tests/data/expr.c index 4f2d2e7..4f2d2e7 100644 --- a/libacc/tests/expr.c +++ b/libacc/tests/data/expr.c diff --git a/libacc/tests/hello.c b/libacc/tests/data/hello.c index 585ce6c..585ce6c 100644 --- a/libacc/tests/hello.c +++ b/libacc/tests/data/hello.c diff --git a/libacc/tests/missing-main.c b/libacc/tests/data/missing-main.c index e73eec4..e73eec4 100644 --- a/libacc/tests/missing-main.c +++ b/libacc/tests/data/missing-main.c diff --git a/libacc/tests/otcc.c b/libacc/tests/data/otcc.c index 577fcf3..577fcf3 100644 --- a/libacc/tests/otcc.c +++ b/libacc/tests/data/otcc.c diff --git a/libacc/tests/returnval.c b/libacc/tests/data/returnval.c index 3142fe2..3142fe2 100644 --- a/libacc/tests/returnval.c +++ b/libacc/tests/data/returnval.c diff --git a/libacc/tests/simplest.c b/libacc/tests/data/simplest.c index bae895a..bae895a 100644 --- a/libacc/tests/simplest.c +++ b/libacc/tests/data/simplest.c diff --git a/libacc/tests/hello.out-orig b/libacc/tests/hello.out-orig Binary files differdeleted file mode 100644 index 1fb7bf5..0000000 --- a/libacc/tests/hello.out-orig +++ /dev/null diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp new file mode 100644 index 0000000..8cfc196 --- /dev/null +++ b/libacc/tests/main.cpp @@ -0,0 +1,102 @@ +/* + * Android "Almost" C Compiler. + * This is a compiler for a small subset of the C language, intended for use + * in scripting environments where speed and memory footprint are important. + * + * This code is based upon the "unobfuscated" version of the + * Obfuscated Tiny C compiler, see the file LICENSE for details. + * + */ + +#include <ctype.h> +#include <dlfcn.h> +#include <stdarg.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#if defined(__arm__) +#include <unistd.h> +#endif + +#include <acc/acc.h> + + +typedef int (*MainPtr)(int, char**); +// This is a separate function so it can easily be set by breakpoint in gdb. +int run(MainPtr mainFunc, int argc, char** argv) { + return mainFunc(argc, argv); +} + +int main(int argc, char** argv) { + const char* inFile = NULL; + bool printListing; + FILE* in = stdin; + int i; + for (i = 1; i < argc; i++) { + char* arg = argv[i]; + if (arg[0] == '-') { + switch (arg[1]) { + case 'S': + printListing = true; + break; + default: + fprintf(stderr, "Unrecognized flag %s\n", arg); + return 3; + } + } else if (inFile == NULL) { + inFile = arg; + } else { + break; + } + } + + if (! inFile) { + fprintf(stderr, "input file required\n"); + return 2; + } + + if (inFile) { + in = fopen(inFile, "r"); + if (!in) { + fprintf(stderr, "Could not open input file %s\n", inFile); + return 1; + } + } + + fseek(in, 0, SEEK_END); + size_t fileSize = (size_t) ftell(in); + rewind(in); + ACCchar* text = new ACCchar[fileSize]; + size_t bytesRead = fread(text, 1, fileSize, in); + if (bytesRead != fileSize) { + fprintf(stderr, "Could not read all of file %s\n", inFile); + } + + ACCscript* script = accCreateScript(); + + const ACCchar* scriptSource[] = {text}; + accScriptSource(script, 1, scriptSource, NULL); + delete[] text; + + accCompileScript(script); + + MainPtr mainPointer = 0; + + accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); + + int result = accGetError(script); + if (result == ACC_NO_ERROR) { + fprintf(stderr, "Executing compiled code:\n"); + int codeArgc = argc - i + 1; + char** codeArgv = argv + i - 1; + codeArgv[0] = (char*) (inFile ? inFile : "stdin"); + result = run(mainPointer, codeArgc, codeArgv); + fprintf(stderr, "result: %d\n", result); + } + + accDeleteScript(script); + + return result; +} diff --git a/libacc/tests/otcc.out-orig b/libacc/tests/otcc.out-orig Binary files differdeleted file mode 100644 index fa14c72..0000000 --- a/libacc/tests/otcc.out-orig +++ /dev/null diff --git a/libacc/tests/testarm b/libacc/tests/testarm new file mode 100755 index 0000000..db7ebe5 --- /dev/null +++ b/libacc/tests/testarm @@ -0,0 +1,9 @@ +#!/bin/sh +adb remount +adb shell rm /system/bin/acc +adb push data/returnval.c /system/bin/returnval.c +cd .. +mm -j8 +cd tests +adb sync +adb shell /system/bin/acc -S /system/bin/returnval.c diff --git a/libacc/tests/testlocal b/libacc/tests/testlocal new file mode 100755 index 0000000..a76322b --- /dev/null +++ b/libacc/tests/testlocal @@ -0,0 +1,15 @@ +#!/bin/sh +rm -f test-acc +cd .. +g++ -I../include acc.cpp disassem.cpp tests/main.cpp -g -ldl -o tests/test-acc +cd tests +if [ -x "test-acc" ]; then + ./test-acc -S data/returnval.c + + if [ "$(uname)" = "Linux" ]; then + if [ "$(uname -m)" = "i686" ]; then + echo "Linux i686. Testing otcc.c" + ./test-acc data/otcc.c data/otcc.c data/returnval.c + fi + fi +fi diff --git a/libcutils/Android.mk b/libcutils/Android.mk index aaee8bf..087d652 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -17,7 +17,6 @@ LOCAL_PATH := $(my-dir) include $(CLEAR_VARS) commonSources := \ - abort_socket.c \ array.c \ hashmap.c \ atomic.c \ @@ -45,22 +44,23 @@ commonHostSources := \ # 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 -WITH_MINGW := +WINDOWS_HOST_ONLY := ifeq ($(HOST_OS),windows) ifeq ($(strip $(USE_CYGWIN)),) - WITH_MINGW := 1 + WINDOWS_HOST_ONLY := 1 endif endif # USE_MINGW is defined when we build against Mingw on Linux ifneq ($(strip $(USE_MINGW)),) - WITH_MINGW := 1 + WINDOWS_HOST_ONLY := 1 endif -ifeq ($(WITH_MINGW),1) +ifeq ($(WINDOWS_HOST_ONLY),1) commonSources += \ uio.c else commonSources += \ + abort_socket.c \ mspace.c \ selector.c \ tztime.c \ diff --git a/libcutils/abort_socket.c b/libcutils/abort_socket.c index d732142..6a5e5e4 100644 --- a/libcutils/abort_socket.c +++ b/libcutils/abort_socket.c @@ -239,7 +239,7 @@ int asocket_write(struct asocket *s, const void *buf, size_t count, } if (pfd[0].revents) { - if (pfd[0].revents & POLLIN) { + if (pfd[0].revents & POLLOUT) { /* ready to write() without blocking */ do { ret = write(s->fd, buf, count); diff --git a/nexus/CommandListener.cpp b/nexus/CommandListener.cpp index fdf3fed..5b03357 100644 --- a/nexus/CommandListener.cpp +++ b/nexus/CommandListener.cpp @@ -33,54 +33,19 @@ CommandListener::CommandListener() : FrameworkListener("nexus") { - registerCmd(new WifiEnableCmd()); - registerCmd(new WifiDisableCmd()); - registerCmd(new WifiScanCmd()); registerCmd(new WifiScanResultsCmd()); registerCmd(new WifiListNetworksCmd()); registerCmd(new WifiAddNetworkCmd()); registerCmd(new WifiRemoveNetworkCmd()); - registerCmd(new WifiSetVarCmd()); - registerCmd(new WifiGetVarCmd()); - registerCmd(new VpnEnableCmd()); - registerCmd(new VpnSetVarCmd()); - registerCmd(new VpnGetVarCmd()); - registerCmd(new VpnDisableCmd()); + registerCmd(new GetCmd()); + registerCmd(new SetCmd()); } /* ------------- * Wifi Commands * ------------ */ -CommandListener::WifiEnableCmd::WifiEnableCmd() : - NexusCommand("wifi_enable") { -} - -int CommandListener::WifiEnableCmd::runCommand(SocketClient *cli, char *data) { - Controller *c = NetworkManager::Instance()->findController("WIFI"); - - if (c->enable()) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable wifi", true); - else - cli->sendMsg(ErrorCode::CommandOkay, "Wifi Enabled", false); - return 0; -} - -CommandListener::WifiDisableCmd::WifiDisableCmd() : - NexusCommand("wifi_disable") { -} - -int CommandListener::WifiDisableCmd::runCommand(SocketClient *cli, char *data) { - Controller *c = NetworkManager::Instance()->findController("WIFI"); - - if (c->disable()) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable wifi", true); - else - cli->sendMsg(ErrorCode::CommandOkay, "Wifi Disabled", false); - return 0; -} - CommandListener::WifiAddNetworkCmd::WifiAddNetworkCmd() : NexusCommand("wifi_add_network") { } @@ -116,21 +81,6 @@ int CommandListener::WifiRemoveNetworkCmd::runCommand(SocketClient *cli, char *d return 0; } -CommandListener::WifiScanCmd::WifiScanCmd() : - NexusCommand("wifi_scan") { -} - -int CommandListener::WifiScanCmd::runCommand(SocketClient *cli, char *data) { - WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI"); - - if (wc->setScanMode(atoi(data))) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to set scan mode", true); - else - cli->sendMsg(ErrorCode::CommandOkay, "Scan mode set", false); - - return 0; -} - CommandListener::WifiScanResultsCmd::WifiScanResultsCmd() : NexusCommand("wifi_scan_results") { } @@ -181,68 +131,39 @@ int CommandListener::WifiListNetworksCmd::runCommand(SocketClient *cli, char *da return 0; } -CommandListener::WifiSetVarCmd::WifiSetVarCmd() : - NexusCommand("wifi_setvar") { -} - -int CommandListener::WifiSetVarCmd::runCommand(SocketClient *cli, char *data) { - WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI"); - - char *bword; - char *last; - char varname[32]; - char val[250]; - int networkId; - - if (!(bword = strtok_r(data, ":", &last))) - goto out_inval; - - networkId = atoi(bword); - - if (!(bword = strtok_r(NULL, ":", &last))) - goto out_inval; - - strncpy(varname, bword, sizeof(varname)); - - if (!(bword = strtok_r(NULL, ":", &last))) - goto out_inval; - - strncpy(val, bword, sizeof(val)); - - LOGD("Network id %d, varname '%s', value '%s'", networkId, varname, val); - - return 0; - -out_inval: - errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true); - return 0; -} +/* ------------ + * Vpn Commands + * ------------ */ -CommandListener::WifiGetVarCmd::WifiGetVarCmd() : - NexusCommand("wifi_getvar") { +/* ---------------- + * Generic Commands + * ---------------- */ +CommandListener::GetCmd::GetCmd() : + NexusCommand("get") { } -int CommandListener::WifiGetVarCmd::runCommand(SocketClient *cli, char *data) { - WifiController *wc = (WifiController *) NetworkManager::Instance()->findController("WIFI"); - +int CommandListener::GetCmd::runCommand(SocketClient *cli, char *data) { char *bword; char *last; - char varname[32]; - int networkId; + char propname[32]; if (!(bword = strtok_r(data, ":", &last))) goto out_inval; - networkId = atoi(bword); + strncpy(propname, bword, sizeof(propname)); - if (!(bword = strtok_r(NULL, ":", &last))) - goto out_inval; + char pb[255]; + snprintf(pb, sizeof(pb), "%s:", propname); - strncpy(varname, bword, sizeof(varname)); + if (!NetworkManager::Instance()->getProperty(propname, + &pb[strlen(pb)], + sizeof(pb) - strlen(pb))) { + goto out_inval; + } - LOGD("networkId = %d, varname '%s'", networkId, varname); + cli->sendMsg(ErrorCode::VariableRead, pb, false); + cli->sendMsg(ErrorCode::CommandOkay, "Property read.", false); return 0; out_inval: errno = EINVAL; @@ -250,106 +171,34 @@ out_inval: return 0; } -/* ------------ - * Vpn Commands - * ------------ */ -CommandListener::VpnEnableCmd::VpnEnableCmd() : - NexusCommand("vpn_enable") { -} - -int CommandListener::VpnEnableCmd::runCommand(SocketClient *cli, char *data) { - Controller *c = NetworkManager::Instance()->findController("VPN"); - - if (c->enable()) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to enable VPN", true); - else - cli->sendMsg(ErrorCode::CommandOkay, "VPN enabled", false); - return 0; +CommandListener::SetCmd::SetCmd() : + NexusCommand("set") { } -CommandListener::VpnSetVarCmd::VpnSetVarCmd() : - NexusCommand("vpn_setvar") { -} - -int CommandListener::VpnSetVarCmd::runCommand(SocketClient *cli, char *data) { - VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN"); - +int CommandListener::SetCmd::runCommand(SocketClient *cli, char *data) { char *bword; char *last; - char varname[32]; - char val[250]; + char propname[32]; + char propval[250]; if (!(bword = strtok_r(data, ":", &last))) goto out_inval; - strncpy(varname, bword, sizeof(varname)); + strncpy(propname, bword, sizeof(propname)); if (!(bword = strtok_r(NULL, ":", &last))) goto out_inval; - strncpy(val, bword, sizeof(val)); - - if (!strcasecmp(varname, "vpn_gateway")) { - if (vc->setVpnGateway(val)) - goto out_inval; - } else { - cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true); - return 0; - } - - cli->sendMsg(ErrorCode::CommandOkay, "Variable written.", false); - return 0; - -out_inval: - errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set variable.", true); - return 0; -} - -CommandListener::VpnGetVarCmd::VpnGetVarCmd() : - NexusCommand("vpn_getvar") { -} + strncpy(propval, bword, sizeof(propval)); -int CommandListener::VpnGetVarCmd::runCommand(SocketClient *cli, char *data) { - VpnController *vc = (VpnController *) NetworkManager::Instance()->findController("VPN"); - - char *bword; - char *last; - char varname[32]; - - if (!(bword = strtok_r(data, ":", &last))) + if (NetworkManager::Instance()->setProperty(propname, propval)) goto out_inval; - - strncpy(varname, bword, sizeof(varname)); - if (!strcasecmp(varname, "vpn_gateway")) { - char buffer[255]; - - sprintf(buffer, "%s:%s", varname, inet_ntoa(vc->getVpnGateway())); - cli->sendMsg(ErrorCode::VariableRead, buffer, false); - } else { - cli->sendMsg(ErrorCode::CommandParameterError, "Variable not found.", true); - return 0; - } - - cli->sendMsg(ErrorCode::CommandOkay, "Variable read.", false); + cli->sendMsg(ErrorCode::CommandOkay, "Property set.", false); return 0; + out_inval: errno = EINVAL; - cli->sendMsg(ErrorCode::CommandParameterError, "Failed to get variable.", true); - return 0; -} - -CommandListener::VpnDisableCmd::VpnDisableCmd() : - NexusCommand("vpn_disable") { -} - -int CommandListener::VpnDisableCmd::runCommand(SocketClient *cli, char *data) { - Controller *c = NetworkManager::Instance()->findController("VPN"); - - if (c->disable()) - cli->sendMsg(ErrorCode::OperationFailed, "Failed to disable VPN", true); - else - cli->sendMsg(ErrorCode::CommandOkay, "VPN disabled", false); + cli->sendMsg(ErrorCode::CommandParameterError, "Failed to set property.", true); return 0; } diff --git a/nexus/CommandListener.h b/nexus/CommandListener.h index a44aa29..6973aaa 100644 --- a/nexus/CommandListener.h +++ b/nexus/CommandListener.h @@ -25,19 +25,6 @@ public: virtual ~CommandListener() {} private: - class WifiEnableCmd : public NexusCommand { - public: - WifiEnableCmd(); - virtual ~WifiEnableCmd() {} - int runCommand(SocketClient *c, char *data); - }; - - class WifiDisableCmd : public NexusCommand { - public: - WifiDisableCmd(); - virtual ~WifiDisableCmd() {} - int runCommand(SocketClient *c, char *data); - }; class WifiScanCmd : public NexusCommand { public: @@ -74,48 +61,19 @@ private: int runCommand(SocketClient *c, char *data); }; - class WifiSetVarCmd : public NexusCommand { - public: - WifiSetVarCmd(); - virtual ~WifiSetVarCmd() {} - int runCommand(SocketClient *c, char *data); - }; - - class WifiGetVarCmd : public NexusCommand { - public: - WifiGetVarCmd(); - virtual ~WifiGetVarCmd() {} - int runCommand(SocketClient *c, char *data); - }; - - class VpnEnableCmd : public NexusCommand { - public: - VpnEnableCmd(); - virtual ~VpnEnableCmd() {} - int runCommand(SocketClient *c, char *data); - }; - - class VpnSetVarCmd : public NexusCommand { - public: - VpnSetVarCmd(); - virtual ~VpnSetVarCmd() {} - int runCommand(SocketClient *c, char *data); - }; - - class VpnGetVarCmd : public NexusCommand { + class SetCmd : public NexusCommand { public: - VpnGetVarCmd(); - virtual ~VpnGetVarCmd() {} + SetCmd(); + virtual ~SetCmd() {} int runCommand(SocketClient *c, char *data); }; - class VpnDisableCmd : public NexusCommand { + class GetCmd : public NexusCommand { public: - VpnDisableCmd(); - virtual ~VpnDisableCmd() {} + GetCmd(); + virtual ~GetCmd() {} int runCommand(SocketClient *c, char *data); }; - }; #endif diff --git a/nexus/Controller.cpp b/nexus/Controller.cpp index cc1a187..133e796 100644 --- a/nexus/Controller.cpp +++ b/nexus/Controller.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ #include <stdio.h> +#include <stdlib.h> #include <string.h> #include <fcntl.h> #include <unistd.h> @@ -32,8 +33,13 @@ extern "C" int init_module(void *, unsigned int, const char *); extern "C" int delete_module(const char *, unsigned int); -Controller::Controller(const char *name) { +Controller::Controller(const char *name, const char *prefix) { mName = name; + mPropertyPrefix = prefix; + mProperties = new PropertyCollection(); + + mEnabled = false; + registerProperty("enable"); } int Controller::start() { @@ -44,12 +50,69 @@ int Controller::stop() { return 0; } +const PropertyCollection & Controller::getProperties() { + return *mProperties; +} + +int Controller::setProperty(const char *name, char *value) { + if (!strcmp(name, "enable")) { + int en = atoi(value); + int rc; + + rc = (en ? enable() : disable()); + + if (!rc) + mEnabled = en; + + return rc; + } + + errno = ENOENT; + return -1; +} + +const char *Controller::getProperty(const char *name, char *buffer, size_t maxsize) { + if (!strcmp(name, "enable")) { + snprintf(buffer, maxsize, "%d", mEnabled); + return buffer; + } + + errno = ENOENT; + return NULL; +} + +int Controller::registerProperty(const char *name) { + PropertyCollection::iterator it; + + for (it = mProperties->begin(); it != mProperties->end(); ++it) { + if (!strcmp(name, (*it))) { + errno = EADDRINUSE; + LOGE("Failed to register property (%s)", strerror(errno)); + return -1; + } + } + + mProperties->push_back(name); + return 0; +} + +int Controller::unregisterProperty(const char *name) { + PropertyCollection::iterator it; + + for (it = mProperties->begin(); it != mProperties->end(); ++it) { + if (!strcmp(name, (*it))) { + mProperties->erase(it); + return 0; + } + } + errno = ENOENT; + return -1; +} + int Controller::loadKernelModule(char *modpath, const char *args) { void *module; unsigned int size; - LOGD("loadKernelModule(%s, %s)", modpath, args); - module = loadFile(modpath, &size); if (!module) { errno = -EIO; @@ -65,7 +128,6 @@ int Controller::unloadKernelModule(const char *modtag) { int rc = -1; int retries = 10; - LOGD("unloadKernelModule(%s)", modtag); while (retries--) { rc = delete_module(modtag, O_NONBLOCK | O_EXCL); if (rc < 0 && errno == EAGAIN) @@ -107,7 +169,6 @@ bool Controller::isKernelModuleLoaded(const char *modtag) { return false; } - void *Controller::loadFile(char *filename, unsigned int *_size) { int ret, fd; diff --git a/nexus/Controller.h b/nexus/Controller.h index 8e69978..ae37426 100644 --- a/nexus/Controller.h +++ b/nexus/Controller.h @@ -16,31 +16,48 @@ #ifndef _CONTROLLER_H #define _CONTROLLER_H +#include <unistd.h> +#include <sys/types.h> + #include "../../../frameworks/base/include/utils/List.h" +#include "PropertyCollection.h" + class Controller { private: const char *mName; + const char *mPropertyPrefix; + PropertyCollection *mProperties; + bool mEnabled; public: - Controller(const char *name); + Controller(const char *name, const char *prefix); virtual ~Controller() {} virtual int start(); virtual int stop(); - virtual int enable() = 0; - virtual int disable() = 0; + virtual const PropertyCollection &getProperties(); + virtual int setProperty(const char *name, char *value); + virtual const char *getProperty(const char *name, char *buffer, size_t maxsize); - virtual const char *getName() { return mName; } + const char *getName() { return mName; } + const char *getPropertyPrefix() { return mPropertyPrefix; } protected: int loadKernelModule(char *modpath, const char *args); bool isKernelModuleLoaded(const char *modtag); int unloadKernelModule(const char *modtag); + int registerProperty(const char *name); + int unregisterProperty(const char *name); + private: void *loadFile(char *filename, unsigned int *_size); + + virtual int enable() = 0; + virtual int disable() = 0; + }; typedef android::List<Controller *> ControllerCollection; diff --git a/nexus/LoopController.cpp b/nexus/LoopController.cpp index 38037ac..400d279 100644 --- a/nexus/LoopController.cpp +++ b/nexus/LoopController.cpp @@ -18,7 +18,7 @@ #include "LoopController.h" LoopController::LoopController() : - Controller("LOOP") { + Controller("LOOP", "loop") { } int LoopController::enable() { diff --git a/nexus/LoopController.h b/nexus/LoopController.h index 8b89977..d047f87 100644 --- a/nexus/LoopController.h +++ b/nexus/LoopController.h @@ -23,6 +23,7 @@ public: LoopController(); virtual ~LoopController() {} +private: int enable(); int disable(); }; diff --git a/nexus/NetworkManager.cpp b/nexus/NetworkManager.cpp index 3b823d1..022d7f8 100644 --- a/nexus/NetworkManager.cpp +++ b/nexus/NetworkManager.cpp @@ -83,6 +83,73 @@ Controller *NetworkManager::findController(const char *name) { return NULL; } +int NetworkManager::setProperty(const char *name, char *value) { + char *tmp = strdup(name); + char *next = tmp; + char *prefix; + char *rest; + ControllerCollection::iterator it; + + if (!(prefix = strsep(&next, "."))) + goto out_inval; + + rest = next; + + if (!strncasecmp(prefix, "netman", 6)) { + errno = ENOSYS; + return -1; + } + + for (it = mControllers->begin(); it != mControllers->end(); ++it) { + if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) { + return (*it)->setProperty(rest, value); + } + } + + errno = ENOENT; + return -1; + +out_inval: + errno = EINVAL; + return -1; +} + +const char *NetworkManager::getProperty(const char *name, char *buffer, + size_t maxsize) { + char *tmp = strdup(name); + char *next = tmp; + char *prefix; + char *rest; + ControllerCollection::iterator it; + + if (!(prefix = strsep(&next, "."))) + goto out_inval; + + rest = next; + + if (!strncasecmp(prefix, "netman", 6)) { + errno = ENOSYS; + return NULL; + } + + for (it = mControllers->begin(); it != mControllers->end(); ++it) { + if (!strcasecmp(prefix, (*it)->getPropertyPrefix())) { + return (*it)->getProperty(rest, buffer, maxsize); + } + } + + errno = ENOENT; + return NULL; + +out_inval: + errno = EINVAL; + return NULL; +} + +const PropertyCollection &NetworkManager::getProperties() { + return *mProperties; +} + int NetworkManager::onInterfaceCreated(Controller *c, char *name) { LOGD("Interface %s created by controller %s", name, c->getName()); return 0; diff --git a/nexus/NetworkManager.h b/nexus/NetworkManager.h index 0ac4a4d..bd00849 100644 --- a/nexus/NetworkManager.h +++ b/nexus/NetworkManager.h @@ -19,6 +19,7 @@ #include <sysutils/SocketListener.h> #include "Controller.h" +#include "PropertyCollection.h" class NetworkManager { private: @@ -27,6 +28,7 @@ private: private: ControllerCollection *mControllers; SocketListener *mBroadcaster; + PropertyCollection *mProperties; public: virtual ~NetworkManager() {} @@ -37,6 +39,10 @@ public: Controller *findController(const char *name); + const PropertyCollection &getProperties(); + int setProperty(const char *name, char *value); + const char *getProperty(const char *name, char *buffer, size_t maxsize); + void setBroadcaster(SocketListener *sl) { mBroadcaster = sl; } SocketListener *getBroadcaster() { return mBroadcaster; } @@ -45,6 +51,9 @@ public: private: int startControllers(); int stopControllers(); + int registerProperty(const char *name); + int unregisterProperty(const char *name); + NetworkManager(); public: diff --git a/nexus/OpenVpnController.cpp b/nexus/OpenVpnController.cpp index 411a0c7..1934024 100644 --- a/nexus/OpenVpnController.cpp +++ b/nexus/OpenVpnController.cpp @@ -63,7 +63,6 @@ int OpenVpnController::enable() { } int OpenVpnController::disable() { - if (mServiceManager->stop("openvpn")) return -1; return 0; diff --git a/nexus/OpenVpnController.h b/nexus/OpenVpnController.h index b321029..439e18a 100644 --- a/nexus/OpenVpnController.h +++ b/nexus/OpenVpnController.h @@ -31,6 +31,8 @@ public: int start(); int stop(); + +private: int enable(); int disable(); }; diff --git a/nexus/PropertyCollection.h b/nexus/PropertyCollection.h new file mode 100644 index 0000000..4be1cf0 --- /dev/null +++ b/nexus/PropertyCollection.h @@ -0,0 +1,25 @@ +/* + * Copyright (C) 2008 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. + */ + +#ifndef _PROPERTY_COLLECTION_H +#define _PROPERTY_COLLECTION_H + +#include "../../../frameworks/base/include/utils/List.h" + +typedef android::List<const char *> PropertyCollection; + +#endif + diff --git a/nexus/VpnController.cpp b/nexus/VpnController.cpp index cd24c19..d3bc216 100644 --- a/nexus/VpnController.cpp +++ b/nexus/VpnController.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include <stdio.h> #include <string.h> #include <errno.h> #include <sys/socket.h> @@ -23,7 +24,8 @@ #include "VpnController.h" VpnController::VpnController() : - Controller("VPN") { + Controller("VPN", "vpn") { + registerProperty("gateway"); } int VpnController::start() { @@ -46,15 +48,23 @@ int VpnController::disable() { return -1; } -int VpnController::setVpnGateway(const char *vpnGw) { - if (!inet_aton(vpnGw, &mVpnGateway)) { - errno = EINVAL; - return -1; - } - return 0; +int VpnController::setProperty(const char *name, char *value) { + if (!strcmp(name, "gateway")) { + if (!inet_aton(value, &mVpnGateway)) { + errno = EINVAL; + return -1; + } + return 0; + } + + return Controller::setProperty(name, value); } -int VpnController::setVpnGateway(struct in_addr *vpnGw) { - memcpy(&mVpnGateway, vpnGw, sizeof(struct in_addr)); - return 0; +const char *VpnController::getProperty(const char *name, char *buffer, size_t maxsize) { + if (!strcmp(name, "gateway")) { + snprintf(buffer, maxsize, "%s", inet_ntoa(mVpnGateway)); + return buffer; + } + + return Controller::getProperty(name, buffer, maxsize); } diff --git a/nexus/VpnController.h b/nexus/VpnController.h index 4088e6a..0a93990 100644 --- a/nexus/VpnController.h +++ b/nexus/VpnController.h @@ -33,14 +33,14 @@ public: virtual int start(); virtual int stop(); + virtual int setProperty(const char *name, char *value); + virtual const char *getProperty(const char *name, char *buffer, + size_t maxlen); + +private: virtual int enable(); virtual int disable(); - struct in_addr &getVpnGateway() { return mVpnGateway; } - int setVpnGateway(const char *vpnGw); - int setVpnGateway(struct in_addr *vpnGw); - -protected: }; #endif diff --git a/nexus/WifiController.cpp b/nexus/WifiController.cpp index 126db69..72207ce 100644 --- a/nexus/WifiController.cpp +++ b/nexus/WifiController.cpp @@ -13,6 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + +#include <stdlib.h> #include <string.h> #include <errno.h> @@ -26,7 +28,7 @@ #include "ErrorCode.h" WifiController::WifiController(char *modpath, char *modname, char *modargs) : - Controller("WIFI") { + Controller("WIFI", "wifi") { strncpy(mModulePath, modpath, sizeof(mModulePath)); strncpy(mModuleName, modname, sizeof(mModuleName)); strncpy(mModuleArgs, modargs, sizeof(mModuleArgs)); @@ -34,6 +36,8 @@ WifiController::WifiController(char *modpath, char *modname, char *modargs) : mSupplicant = new Supplicant(); mScanner = new WifiScanner(mSupplicant, 10); mCurrentScanMode = 0; + + registerProperty("scanmode"); } int WifiController::start() { @@ -94,7 +98,7 @@ out_powerdown: return -1; } -void WifiController::sendStatusBroadcast(char *msg) { +void WifiController::sendStatusBroadcast(const char *msg) { NetworkManager::Instance()-> getBroadcaster()-> sendBroadcast(ErrorCode::UnsolicitedInformational, msg, false); @@ -167,3 +171,20 @@ ScanResultCollection *WifiController::createScanResults() { WifiNetworkCollection *WifiController::createNetworkList() { return mSupplicant->createNetworkList(); } + +int WifiController::setProperty(const char *name, char *value) { + if (!strcmp(name, "scanmode")) + return setScanMode((uint32_t) strtoul(value, NULL, 0)); + + return Controller::setProperty(name, value); +} + +const char *WifiController::getProperty(const char *name, char *buffer, size_t maxsize) { + if (!strcmp(name, "scanmode")) { + snprintf(buffer, maxsize, "0x%.8x", mCurrentScanMode); + return buffer; + } + + return Controller::getProperty(name, buffer, maxsize); +} + diff --git a/nexus/WifiController.h b/nexus/WifiController.h index b9c981c..a70fb5b 100644 --- a/nexus/WifiController.h +++ b/nexus/WifiController.h @@ -54,15 +54,14 @@ public: int start(); int stop(); - int enable(); - int disable(); - int addNetwork(); int removeNetwork(int networkId); WifiNetworkCollection *createNetworkList(); - int getScanMode() { return mCurrentScanMode; } - int setScanMode(uint32_t mode); + virtual int setProperty(const char *name, char *value); + virtual const char *getProperty(const char *name, char *buffer, + size_t maxlen); + ScanResultCollection *createScanResults(); char *getModulePath() { return mModulePath; } @@ -79,7 +78,13 @@ protected: virtual bool isFirmwareLoaded() = 0; virtual bool isPoweredUp() = 0; - void sendStatusBroadcast(char *msg); + void sendStatusBroadcast(const char *msg); + +private: + int setScanMode(uint32_t mode); + int enable(); + int disable(); + }; #endif diff --git a/nexus/WifiScanner.cpp b/nexus/WifiScanner.cpp index 1bc9722..048e784 100644 --- a/nexus/WifiScanner.cpp +++ b/nexus/WifiScanner.cpp @@ -65,7 +65,7 @@ void WifiScanner::run() { struct timeval to; int rc = 0; - to.tv_sec = 0; + to.tv_usec = 0; to.tv_sec = mPeriod; FD_ZERO(&read_fds); @@ -83,4 +83,5 @@ void WifiScanner::run() { } else if (FD_ISSET(mCtrlPipe[0], &read_fds)) break; } // while + LOGD("Stopping wifi scanner"); } diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh index 0eb0154..f1b801d 100755 --- a/rootdir/etc/init.goldfish.sh +++ b/rootdir/etc/init.goldfish.sh @@ -34,6 +34,10 @@ case "$boot_anim" in ;; esac +# call 'qemu-props' to set system properties from the emulator. +# +/system/bin/qemu-props + # this line doesn't really do anything useful. however without it the # previous setprop doesn't seem to apply for some really odd reason setprop ro.qemu.init.completed 1 |