diff options
155 files changed, 3545 insertions, 12305 deletions
@@ -25,6 +25,7 @@ else liblog \ libnetutils \ libpixelflinger \ + libusbhost \ libzipfile \ )) endif diff --git a/CleanSpec.mk b/CleanSpec.mk index b84e1b6..8611d3b 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -47,3 +47,6 @@ # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ + +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc) +$(call add-clean-step, rm -rf $(PRODUCT_OUT)/root/init.rc) diff --git a/adb/Android.mk b/adb/Android.mk index 7faca9b..6ed31eb 100644 --- a/adb/Android.mk +++ b/adb/Android.mk @@ -83,7 +83,7 @@ endif include $(BUILD_HOST_EXECUTABLE) -$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) +$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) ifeq ($(HOST_OS),windows) $(LOCAL_INSTALLED_MODULE): \ @@ -152,3 +152,47 @@ else endif endif + + +# adb host tool for device-as-host +# ========================================================= +ifneq ($(TARGET_SIMULATOR),true) +ifneq ($(SDK_ONLY),true) +include $(CLEAR_VARS) + +LOCAL_LDLIBS := -lrt -lncurses -lpthread + +LOCAL_SRC_FILES := \ + adb.c \ + console.c \ + transport.c \ + transport_local.c \ + transport_usb.c \ + commandline.c \ + adb_client.c \ + sockets.c \ + services.c \ + file_sync_client.c \ + get_my_path_linux.c \ + usb_linux.c \ + utils.c \ + usb_vendors.c \ + fdevent.c + +LOCAL_CFLAGS := \ + -O2 \ + -g \ + -DADB_HOST=1 \ + -DADB_HOST_ON_TARGET=1 \ + -Wall \ + -Wno-unused-parameter \ + -D_XOPEN_SOURCE \ + -D_GNU_SOURCE + +LOCAL_MODULE := adb + +LOCAL_STATIC_LIBRARIES := libzipfile libunz libcutils + +include $(BUILD_EXECUTABLE) +endif +endif @@ -366,7 +366,15 @@ typedef enum { #define print_packet(tag,p) do {} while (0) #endif -#define DEFAULT_ADB_PORT 5037 +#if ADB_HOST_ON_TARGET +/* adb and adbd are coexisting on the target, so use 5038 for adb + * to avoid conflicting with adbd's usage of 5037 + */ +# define DEFAULT_ADB_PORT 5038 +#else +# define DEFAULT_ADB_PORT 5037 +#endif + #define DEFAULT_ADB_LOCAL_TRANSPORT_PORT 5555 #define ADB_CLASS 0xff diff --git a/adb/framebuffer_service.c b/adb/framebuffer_service.c index 2f45694..862dd91 100644 --- a/adb/framebuffer_service.c +++ b/adb/framebuffer_service.c @@ -51,56 +51,125 @@ struct fbinfo { void framebuffer_service(int fd, void *cookie) { - struct fb_var_screeninfo vinfo; - int fb, offset; - char x[256]; - struct fbinfo fbinfo; - unsigned i, bytespp; - - fb = open("/dev/graphics/fb0", O_RDONLY); - if(fb < 0) goto done; + unsigned int i; + char buf[640]; + int fd_screencap; + int w, h, f; + int fds[2]; + + if (pipe(fds) < 0) goto done; + + pid_t pid = fork(); + if (pid < 0) goto done; + + if (pid == 0) { + dup2(fds[1], STDOUT_FILENO); + close(fds[0]); + close(fds[1]); + const char* command = "screencap"; + const char *args[2] = {command, NULL}; + execvp(command, (char**)args); + exit(1); + } - if(ioctl(fb, FBIOGET_VSCREENINFO, &vinfo) < 0) goto done; - fcntl(fb, F_SETFD, FD_CLOEXEC); + fd_screencap = fds[0]; - bytespp = vinfo.bits_per_pixel / 8; + /* read w, h & format */ + if(readx(fd_screencap, &w, 4)) goto done; + if(readx(fd_screencap, &h, 4)) goto done; + if(readx(fd_screencap, &f, 4)) goto done; fbinfo.version = DDMS_RAWIMAGE_VERSION; - fbinfo.bpp = vinfo.bits_per_pixel; - fbinfo.size = vinfo.xres * vinfo.yres * bytespp; - fbinfo.width = vinfo.xres; - fbinfo.height = vinfo.yres; - fbinfo.red_offset = vinfo.red.offset; - fbinfo.red_length = vinfo.red.length; - fbinfo.green_offset = vinfo.green.offset; - fbinfo.green_length = vinfo.green.length; - fbinfo.blue_offset = vinfo.blue.offset; - fbinfo.blue_length = vinfo.blue.length; - fbinfo.alpha_offset = vinfo.transp.offset; - fbinfo.alpha_length = vinfo.transp.length; - - /* HACK: for several of our 3d cores a specific alignment - * is required so the start of the fb may not be an integer number of lines - * from the base. As a result we are storing the additional offset in - * xoffset. This is not the correct usage for xoffset, it should be added - * to each line, not just once at the beginning */ - offset = vinfo.xoffset * bytespp; - - offset += vinfo.xres * vinfo.yoffset * bytespp; + /* see hardware/hardware.h */ + switch (f) { + case 1: /* RGBA_8888 */ + fbinfo.bpp = 32; + fbinfo.size = w * h * 4; + fbinfo.width = w; + fbinfo.height = h; + fbinfo.red_offset = 0; + fbinfo.red_length = 8; + fbinfo.green_offset = 8; + fbinfo.green_length = 8; + fbinfo.blue_offset = 16; + fbinfo.blue_length = 8; + fbinfo.alpha_offset = 24; + fbinfo.alpha_length = 8; + break; + case 2: /* RGBX_8888 */ + fbinfo.bpp = 32; + fbinfo.size = w * h * 4; + fbinfo.width = w; + fbinfo.height = h; + fbinfo.red_offset = 0; + fbinfo.red_length = 8; + fbinfo.green_offset = 8; + fbinfo.green_length = 8; + fbinfo.blue_offset = 16; + fbinfo.blue_length = 8; + fbinfo.alpha_offset = 24; + fbinfo.alpha_length = 0; + break; + case 3: /* RGB_888 */ + fbinfo.bpp = 24; + fbinfo.size = w * h * 3; + fbinfo.width = w; + fbinfo.height = h; + fbinfo.red_offset = 0; + fbinfo.red_length = 8; + fbinfo.green_offset = 8; + fbinfo.green_length = 8; + fbinfo.blue_offset = 16; + fbinfo.blue_length = 8; + fbinfo.alpha_offset = 24; + fbinfo.alpha_length = 0; + break; + case 4: /* RGB_565 */ + fbinfo.bpp = 16; + fbinfo.size = w * h * 2; + fbinfo.width = w; + fbinfo.height = h; + fbinfo.red_offset = 11; + fbinfo.red_length = 5; + fbinfo.green_offset = 5; + fbinfo.green_length = 6; + fbinfo.blue_offset = 0; + fbinfo.blue_length = 5; + fbinfo.alpha_offset = 0; + fbinfo.alpha_length = 0; + break; + case 5: /* BGRA_8888 */ + fbinfo.bpp = 32; + fbinfo.size = w * h * 4; + fbinfo.width = w; + fbinfo.height = h; + fbinfo.red_offset = 16; + fbinfo.red_length = 8; + fbinfo.green_offset = 8; + fbinfo.green_length = 8; + fbinfo.blue_offset = 0; + fbinfo.blue_length = 8; + fbinfo.alpha_offset = 24; + fbinfo.alpha_length = 8; + break; + default: + goto done; + } + /* write header */ if(writex(fd, &fbinfo, sizeof(fbinfo))) goto done; - lseek(fb, offset, SEEK_SET); - for(i = 0; i < fbinfo.size; i += 256) { - if(readx(fb, &x, 256)) goto done; - if(writex(fd, &x, 256)) goto done; + /* write data */ + for(i = 0; i < fbinfo.size; i += sizeof(buf)) { + if(readx(fd_screencap, buf, sizeof(buf))) goto done; + if(writex(fd, buf, sizeof(buf))) goto done; } - - if(readx(fb, &x, fbinfo.size % 256)) goto done; - if(writex(fd, &x, fbinfo.size % 256)) goto done; + if(readx(fd_screencap, buf, fbinfo.size % sizeof(buf))) goto done; + if(writex(fd, buf, fbinfo.size % sizeof(buf))) goto done; done: - if(fb >= 0) close(fb); + close(fds[0]); + close(fds[1]); close(fd); } diff --git a/adb/services.c b/adb/services.c index c22ce17..7eab17a 100644 --- a/adb/services.c +++ b/adb/services.c @@ -32,7 +32,7 @@ # include <netdb.h> # endif #else -# include <sys/reboot.h> +# include <cutils/android_reboot.h> #endif typedef struct stinfo stinfo; @@ -193,8 +193,7 @@ void reboot_service(int fd, void *arg) waitpid(pid, &ret, 0); } - ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART2, (char *)arg); + ret = android_reboot(ANDROID_RB_RESTART2, 0, (char *) arg); if (ret < 0) { snprintf(buf, sizeof(buf), "reboot failed: %s\n", strerror(errno)); writex(fd, buf, strlen(buf)); diff --git a/cpio/Android.mk b/cpio/Android.mk index 8d01852..5184463 100644 --- a/cpio/Android.mk +++ b/cpio/Android.mk @@ -10,4 +10,4 @@ LOCAL_MODULE := mkbootfs include $(BUILD_HOST_EXECUTABLE) -$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) +$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) diff --git a/debuggerd/Android.mk b/debuggerd/Android.mk index 752c953..6cfe79b 100644 --- a/debuggerd/Android.mk +++ b/debuggerd/Android.mk @@ -29,7 +29,7 @@ LOCAL_SRC_FILES := crasher.c LOCAL_SRC_FILES += $(TARGET_ARCH)/crashglue.S LOCAL_MODULE := crasher LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional #LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_SHARED_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) @@ -45,7 +45,7 @@ endif # ARCH_ARM_HAVE_VFP_D32 LOCAL_SRC_FILES := vfp-crasher.c vfp.S LOCAL_MODULE := vfp-crasher LOCAL_MODULE_PATH := $(TARGET_OUT_OPTIONAL_EXECUTABLES) -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcutils libc include $(BUILD_EXECUTABLE) endif # ARCH_ARM_HAVE_VFP == true diff --git a/debuggerd/arm/machine.c b/debuggerd/arm/machine.c index ccd0baf..88bf054 100644 --- a/debuggerd/arm/machine.c +++ b/debuggerd/arm/machine.c @@ -32,6 +32,7 @@ #include <cutils/properties.h> #include <linux/input.h> +#include <linux/user.h> #include "utility.h" @@ -53,7 +54,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, int unwind_depth, unsigned int sp_list[], bool at_fault) { - unsigned int sp, pc, p, end, data; + unsigned int sp, pc, lr, p, end, data; struct pt_regs r; int sp_depth; bool only_in_tombstone = !at_fault; @@ -62,19 +63,25 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return; sp = r.ARM_sp; pc = r.ARM_pc; + lr = r.ARM_lr; _LOG(tfd, only_in_tombstone, "\ncode around pc:\n"); - end = p = pc & ~3; + p = pc & ~3; p -= 32; - end += 32; + if (p > pc) + p = 0; + end = p + 80; + /* 'end - p' has to be multiples of 16 */ + while (end < p) + end -= 16; /* Dump the code around PC as: * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ - while (p <= end) { + while (p < end) { int i; sprintf(code_buffer, "%08x ", p); @@ -86,19 +93,24 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, _LOG(tfd, only_in_tombstone, "%s\n", code_buffer); } - if ((unsigned) r.ARM_lr != pc) { + if (lr != pc) { _LOG(tfd, only_in_tombstone, "\ncode around lr:\n"); - end = p = r.ARM_lr & ~3; + p = lr & ~3; p -= 32; - end += 32; + if (p > lr) + p = 0; + end = p + 80; + /* 'end - p' has to be multiples of 16 */ + while (end < p) + end -= 16; /* Dump the code around LR as: * addr contents * 00008d34 fffffcd0 4c0eb530 b0934a0e 1c05447c * 00008d44 f7ff18a0 490ced94 68035860 d0012b00 */ - while (p <= end) { + while (p < end) { int i; sprintf(code_buffer, "%08x ", p); @@ -112,6 +124,8 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, } p = sp - 64; + if (p > sp) + p = 0; p &= ~3; if (unwind_depth != 0) { if (unwind_depth < STACK_CONTENT_DEPTH) { @@ -122,8 +136,10 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, } } else { - end = sp | 0x000000ff; - end += 0xff; + end = p + 256; + /* 'end - p' has to be multiples of 4 */ + if (end < p) + end = ~7; } _LOG(tfd, only_in_tombstone, "\nstack:\n"); @@ -161,6 +177,10 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map, /* print another 64-byte of stack data after the last frame */ end = p+64; + /* 'end - p' has to be multiples of 4 */ + if (end < p) + end = ~7; + while (p <= end) { data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL); _LOG(tfd, (sp_depth > 2) || only_in_tombstone, diff --git a/debuggerd/debuggerd.c b/debuggerd/debuggerd.c index ecfe01f..7a3e781 100644 --- a/debuggerd/debuggerd.c +++ b/debuggerd/debuggerd.c @@ -37,6 +37,7 @@ #include <private/android_filesystem_config.h> +#include <byteswap.h> #include "debuggerd.h" #include "utility.h" @@ -195,6 +196,73 @@ void dump_crash_banner(int tfd, unsigned pid, unsigned tid, int sig) if(sig) dump_fault_addr(tfd, tid, sig); } +/* After randomization (ASLR), stack contents that point to randomized + * code become uninterpretable (e.g. can't be resolved to line numbers). + * Here, we bundle enough information so that stack analysis on the + * server side can still be performed. This means we are leaking some + * information about the device (its randomization base). We have to make + * sure an attacker has no way of intercepting the tombstone. + */ + +typedef struct { + int32_t mmap_addr; + char tag[4]; /* 'P', 'R', 'E', ' ' */ +} prelink_info_t __attribute__((packed)); + +static inline void set_prelink(long *prelink_addr, + prelink_info_t *info) +{ + // We will assume the binary is little-endian, and test the + // host endianness here. + unsigned long test_endianness = 0xFF; + + if (sizeof(prelink_info_t) == 8 && prelink_addr) { + if (*(unsigned char *)&test_endianness) + *prelink_addr = info->mmap_addr; + else + *prelink_addr = bswap_32(info->mmap_addr); + } +} + +static int check_prelinked(const char *fname, + long *prelink_addr) +{ + *prelink_addr = 0; + if (sizeof(prelink_info_t) != 8) return 0; + + int fd = open(fname, O_RDONLY); + if (fd < 0) return 0; + off_t end = lseek(fd, 0, SEEK_END); + int nr = sizeof(prelink_info_t); + + off_t sz = lseek(fd, -nr, SEEK_CUR); + if ((long)(end - sz) != (long)nr) return 0; + if (sz == (off_t)-1) return 0; + + prelink_info_t info; + int num_read = read(fd, &info, nr); + if (num_read < 0) return 0; + if (num_read != sizeof(info)) return 0; + + int prelinked = 0; + if (!strncmp(info.tag, "PRE ", 4)) { + set_prelink(prelink_addr, &info); + prelinked = 1; + } + if (close(fd) < 0) return 0; + return prelinked; +} + +void dump_randomization_base(int tfd, bool at_fault) { + bool only_in_tombstone = !at_fault; + long prelink_addr; + check_prelinked("/system/lib/libc.so", &prelink_addr); + _LOG(tfd, only_in_tombstone, + "\nlibc base address: %08x\n", prelink_addr); +} + +/* End of ASLR-related logic. */ + static void parse_elf_info(mapinfo *milist, pid_t pid) { mapinfo *mi; @@ -285,6 +353,7 @@ void dump_crash_report(int tfd, unsigned pid, unsigned tid, bool at_fault) dump_pc_and_lr(tfd, tid, milist, stack_depth, at_fault); } + dump_randomization_base(tfd, at_fault); dump_stack_and_code(tfd, tid, milist, stack_depth, sp_list, at_fault); #elif __i386__ /* If stack unwinder fails, use the default solution to dump the stack @@ -573,7 +642,7 @@ static void handle_crashing_process(int fd) goto done; } - sprintf(buf,"/proc/%d/task/%d", cr.pid, tid); + snprintf(buf, sizeof buf, "/proc/%d/task/%d", cr.pid, tid); if(stat(buf, &s)) { LOG("tid %d does not exist in pid %d. ignoring debug request\n", tid, cr.pid); @@ -583,7 +652,19 @@ static void handle_crashing_process(int fd) XLOG("BOOM: pid=%d uid=%d gid=%d tid=%d\n", cr.pid, cr.uid, cr.gid, tid); + /* Note that at this point, the target thread's signal handler + * is blocked in a read() call. This gives us the time to PTRACE_ATTACH + * to it before it has a chance to really fault. + * + * After the attach, the thread is stopped, and we write to the file + * descriptor to ensure that it will run as soon as we call PTRACE_CONT + * below. See details in bionic/libc/linker/debugger.c, in function + * debugger_signal_handler(). + */ tid_attach_status = ptrace(PTRACE_ATTACH, tid, 0, 0); + + TEMP_FAILURE_RETRY(write(fd, &tid, 1)); + if(tid_attach_status < 0) { LOG("ptrace attach failed: %s\n", strerror(errno)); goto done; diff --git a/debuggerd/symbol_table.c b/debuggerd/symbol_table.c index fd008fe..23572a3 100644 --- a/debuggerd/symbol_table.c +++ b/debuggerd/symbol_table.c @@ -50,7 +50,7 @@ struct symbol_table *symbol_table_create(const char *filename) int length; char *base; - XLOG("Creating symbol table for %s\n", filename); + XLOG2("Creating symbol table for %s\n", filename); int fd = open(filename, O_RDONLY); if(fd < 0) { @@ -126,7 +126,7 @@ struct symbol_table *symbol_table_create(const char *filename) dynsymbol_count++; } } - XLOG("Dynamic Symbol count: %d\n", dynsymbol_count); + XLOG2("Dynamic Symbol count: %d\n", dynsymbol_count); } if (sym_idx != -1) { @@ -139,7 +139,7 @@ struct symbol_table *symbol_table_create(const char *filename) symbol_count++; } } - XLOG("Symbol count: %d\n", symbol_count); + XLOG2("Symbol count: %d\n", symbol_count); } // Now, create an entry in our symbol table structure for each symbol... @@ -160,7 +160,7 @@ struct symbol_table *symbol_table_create(const char *filename) table->symbols[j].name = strdup(dynstr + dynsyms[i].st_name); table->symbols[j].addr = dynsyms[i].st_value; table->symbols[j].size = dynsyms[i].st_size; - XLOG("name: %s, addr: %x, size: %x\n", + XLOG2("name: %s, addr: %x, size: %x\n", table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size); j++; } @@ -176,7 +176,7 @@ struct symbol_table *symbol_table_create(const char *filename) table->symbols[j].name = strdup(str + syms[i].st_name); table->symbols[j].addr = syms[i].st_value; table->symbols[j].size = syms[i].st_size; - XLOG("name: %s, addr: %x, size: %x\n", + XLOG2("name: %s, addr: %x, size: %x\n", table->symbols[j].name, table->symbols[j].addr, table->symbols[j].size); j++; } diff --git a/debuggerd/utility.h b/debuggerd/utility.h index 0682b85..45e2067 100644 --- a/debuggerd/utility.h +++ b/debuggerd/utility.h @@ -57,10 +57,19 @@ const char *map_to_name(mapinfo *mi, unsigned pc, const char* def); extern void _LOG(int tfd, bool in_tombstone_only, const char *fmt, ...); #define LOG(fmt...) _LOG(-1, 0, fmt) + +/* Set to 1 for normal debug traces */ #if 0 #define XLOG(fmt...) _LOG(-1, 0, fmt) #else #define XLOG(fmt...) do {} while(0) #endif +/* Set to 1 for chatty debug traces. Includes all resolved dynamic symbols */ +#if 0 +#define XLOG2(fmt...) _LOG(-1, 0, fmt) +#else +#define XLOG2(fmt...) do {} while(0) +#endif + #endif diff --git a/fastboot/Android.mk b/fastboot/Android.mk index 34380ec..3c5538f 100644 --- a/fastboot/Android.mk +++ b/fastboot/Android.mk @@ -50,7 +50,7 @@ endif LOCAL_STATIC_LIBRARIES := $(EXTRA_STATIC_LIBS) libzipfile libunz include $(BUILD_HOST_EXECUTABLE) -$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) +$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) ifeq ($(HOST_OS),linux) include $(CLEAR_VARS) diff --git a/fastboot/engine.c b/fastboot/engine.c index 48073ee..6d94035 100644 --- a/fastboot/engine.c +++ b/fastboot/engine.c @@ -69,6 +69,7 @@ struct Action Action *next; char cmd[64]; + const char *prod; void *data; unsigned size; @@ -183,6 +184,16 @@ static int cb_check(Action *a, int status, char *resp, int invert) return status; } + if (a->prod) { + if (strcmp(a->prod, cur_product) != 0) { + double split = now(); + fprintf(stderr,"IGNORE, product is %s required only for %s [%7.3fs]\n", + cur_product, a->prod, (split - a->start)); + a->start = split; + return 0; + } + } + yes = match(resp, value, count); if (invert) yes = !yes; @@ -214,10 +225,12 @@ static int cb_reject(Action *a, int status, char *resp) return cb_check(a, status, resp, 1); } -void fb_queue_require(const char *var, int invert, unsigned nvalues, const char **value) +void fb_queue_require(const char *prod, const char *var, + int invert, unsigned nvalues, const char **value) { Action *a; a = queue_action(OP_QUERY, "getvar:%s", var); + a->prod = prod; a->data = value; a->size = nvalues; a->msg = mkmsg("checking %s", var); @@ -244,6 +257,25 @@ void fb_queue_display(const char *var, const char *prettyname) a->func = cb_display; } +static int cb_save(Action *a, int status, char *resp) +{ + if (status) { + fprintf(stderr, "%s FAILED (%s)\n", a->cmd, resp); + return status; + } + strncpy(a->data, resp, a->size); + return 0; +} + +void fb_queue_query_save(const char *var, char *dest, unsigned dest_size) +{ + Action *a; + a = queue_action(OP_QUERY, "getvar:%s", var); + a->data = (void *)dest; + a->size = dest_size; + a->func = cb_save; +} + static int cb_do_nothing(Action *a, int status, char *resp) { fprintf(stderr,"\n"); @@ -277,11 +309,11 @@ void fb_queue_notice(const char *notice) a->data = (void*) notice; } -void fb_execute_queue(usb_handle *usb) +int fb_execute_queue(usb_handle *usb) { Action *a; char resp[FB_RESPONSE_SZ+1]; - int status; + int status = 0; a = action_list; resp[FB_RESPONSE_SZ] = 0; @@ -314,5 +346,5 @@ void fb_execute_queue(usb_handle *usb) } fprintf(stderr,"finished. total time: %.3fs\n", (now() - start)); + return status; } - diff --git a/fastboot/fastboot.c b/fastboot/fastboot.c index 14048a1..4a2de20 100644 --- a/fastboot/fastboot.c +++ b/fastboot/fastboot.c @@ -9,7 +9,7 @@ * notice, this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the + * the documentation and/or other materials provided with the * distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS @@ -19,7 +19,7 @@ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS - * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF @@ -42,6 +42,8 @@ #include "fastboot.h" +char cur_product[FB_RESPONSE_SZ + 1]; + void bootimg_set_cmdline(boot_img_hdr *h, const char *cmdline); boot_img_hdr *mkbootimg(void *kernel, unsigned kernel_size, @@ -68,7 +70,7 @@ void die(const char *fmt, ...) fprintf(stderr,"\n"); va_end(ap); exit(1); -} +} void get_my_path(char *path); @@ -99,13 +101,13 @@ char *find_item(const char *item, const char *product) "../../../target/product/%s/%s", product, fn); return strdup(path); } - + dir = getenv("ANDROID_PRODUCT_OUT"); if((dir == 0) || (dir[0] == 0)) { die("neither -p product specified nor ANDROID_PRODUCT_OUT set"); return 0; } - + sprintf(path, "%s/%s", dir, fn); return strdup(path); } @@ -189,12 +191,12 @@ usb_handle *open_device(void) int announce = 1; if(usb) return usb; - + for(;;) { usb = usb_open(match_fastboot); if(usb) return usb; if(announce) { - announce = 0; + announce = 0; fprintf(stderr,"< waiting for device >\n"); } sleep(1); @@ -226,6 +228,7 @@ void usage(void) " continue continue with autoboot\n" " reboot reboot device normally\n" " reboot-bootloader reboot device into bootloader\n" + " help show this help message\n" "\n" "options:\n" " -w erase userdata and cache\n" @@ -236,7 +239,6 @@ void usage(void) " -b <base_addr> specify a custom kernel base address\n" " -n <page size> specify the nand page size. default: 2048\n" ); - exit(1); } void *load_bootable_image(unsigned page_size, const char *kernel, const char *ramdisk, @@ -257,16 +259,16 @@ void *load_bootable_image(unsigned page_size, const char *kernel, const char *ra fprintf(stderr, "cannot load '%s'\n", kernel); return 0; } - + /* is this actually a boot image? */ if(!memcmp(kdata, BOOT_MAGIC, BOOT_MAGIC_SIZE)) { if(cmdline) bootimg_set_cmdline((boot_img_hdr*) kdata, cmdline); - + if(ramdisk) { fprintf(stderr, "cannot boot a boot.img *and* ramdisk\n"); return 0; } - + *sz = ksize; return kdata; } @@ -288,7 +290,7 @@ void *load_bootable_image(unsigned page_size, const char *kernel, const char *ra if(cmdline) bootimg_set_cmdline((boot_img_hdr*) bdata, cmdline); fprintf(stderr,"creating boot image - %d bytes\n", bsize); *sz = bsize; - + return bdata; } @@ -297,7 +299,7 @@ void *unzip_file(zipfile_t zip, const char *name, unsigned *sz) void *data; zipentry_t entry; unsigned datasz; - + entry = lookup_zipentry(zip, name); if (entry == NULL) { fprintf(stderr, "archive does not contain '%s'\n", name); @@ -340,16 +342,25 @@ static int setup_requirement_line(char *name) { char *val[MAX_OPTIONS]; const char **out; + char *prod = NULL; unsigned n, count; char *x; int invert = 0; - + if (!strncmp(name, "reject ", 7)) { name += 7; invert = 1; } else if (!strncmp(name, "require ", 8)) { name += 8; invert = 0; + } else if (!strncmp(name, "require-for-product:", 20)) { + // Get the product and point name past it + prod = name + 20; + name = strchr(name, ' '); + if (!name) return -1; + *name = 0; + name += 1; + invert = 0; } x = strchr(name, '='); @@ -363,10 +374,10 @@ static int setup_requirement_line(char *name) *x = 0; val[count] = x + 1; } - + name = strip(name); for(n = 0; n < count; n++) val[n] = strip(val[n]); - + name = strip(name); if (name == 0) return -1; @@ -381,7 +392,7 @@ static int setup_requirement_line(char *name) if (out[n] == 0) return -1; } - fb_queue_require(name, invert, n, out); + fb_queue_require(prod, name, invert, n, out); return 0; } @@ -432,6 +443,8 @@ void do_update(char *fn) queue_info_dump(); + fb_queue_query_save("product", cur_product, sizeof(cur_product)); + zdata = load_file(fn, &zsize); if (zdata == 0) die("failed to load '%s'", fn); @@ -477,11 +490,11 @@ void do_send_signature(char *fn) void *data; unsigned sz; char *xtn; - + xtn = strrchr(fn, '.'); if (!xtn) return; if (strcmp(xtn, ".img")) return; - + strcpy(xtn,".sig"); data = load_file(fn, &sz); strcpy(xtn,".img"); @@ -498,6 +511,8 @@ void do_flashall(void) queue_info_dump(); + fb_queue_query_save("product", cur_product, sizeof(cur_product)); + fname = find_item("info", product); if (fname == 0) die("cannot find android-info.txt"); data = load_file(fname, &sz); @@ -521,18 +536,18 @@ void do_flashall(void) data = load_file(fname, &sz); if (data == 0) die("could not load system.img"); do_send_signature(fname); - fb_queue_flash("system", data, sz); + fb_queue_flash("system", data, sz); } #define skip(n) do { argc -= (n); argv += (n); } while (0) -#define require(n) do { if (argc < (n)) usage(); } while (0) +#define require(n) do { if (argc < (n)) {usage(); exit(1);}} while (0) int do_oem_command(int argc, char **argv) { int i; char command[256]; if (argc <= 1) return 0; - + command[0] = 0; while(1) { strcat(command,*argv); @@ -541,7 +556,7 @@ int do_oem_command(int argc, char **argv) strcat(command," "); } - fb_queue_command(command,""); + fb_queue_command(command,""); return 0; } @@ -553,11 +568,12 @@ int main(int argc, char **argv) void *data; unsigned sz; unsigned page_size = 2048; + int status; skip(1); if (argc == 0) { usage(); - return 0; + return 1; } if (!strcmp(*argv, "devices")) { @@ -565,6 +581,12 @@ int main(int argc, char **argv) return 0; } + if (!strcmp(*argv, "help")) { + usage(); + return 0; + } + + serial = getenv("ANDROID_SERIAL"); while (argc > 0) { @@ -689,6 +711,7 @@ int main(int argc, char **argv) argc = do_oem_command(argc, argv); } else { usage(); + return 1; } } @@ -704,6 +727,6 @@ int main(int argc, char **argv) usb = open_device(); - fb_execute_queue(usb); - return 0; + status = fb_execute_queue(usb); + return (status) ? 1 : 0; } diff --git a/fastboot/fastboot.h b/fastboot/fastboot.h index a36c569..9e043fe 100644 --- a/fastboot/fastboot.h +++ b/fastboot/fastboot.h @@ -43,15 +43,20 @@ char *fb_get_error(void); /* engine.c - high level command queue engine */ void fb_queue_flash(const char *ptn, void *data, unsigned sz);; void fb_queue_erase(const char *ptn); -void fb_queue_require(const char *var, int invert, unsigned nvalues, const char **value); +void fb_queue_require(const char *prod, const char *var, int invert, + unsigned nvalues, const char **value); void fb_queue_display(const char *var, const char *prettyname); +void fb_queue_query_save(const char *var, char *dest, unsigned dest_size); void fb_queue_reboot(void); void fb_queue_command(const char *cmd, const char *msg); void fb_queue_download(const char *name, void *data, unsigned size); void fb_queue_notice(const char *notice); -void fb_execute_queue(usb_handle *usb); +int fb_execute_queue(usb_handle *usb); /* util stuff */ void die(const char *fmt, ...); +/* Current product */ +extern char cur_product[FB_RESPONSE_SZ + 1]; + #endif diff --git a/fastboot/usb_osx.c b/fastboot/usb_osx.c index 9488687..570a456 100644 --- a/fastboot/usb_osx.c +++ b/fastboot/usb_osx.c @@ -231,8 +231,7 @@ static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkIn); if (kr != 0) { - ERR("could not clear input pipe; result %d", kr); - return -1; + ERR("could not clear input pipe; result %x, ignoring...\n", kr); } } @@ -240,8 +239,7 @@ static int try_interfaces(IOUSBDeviceInterface182 **dev, usb_handle *handle) { kr = (*interface)->ClearPipeStallBothEnds(interface, handle->bulkOut); if (kr != 0) { - ERR("could not clear output pipe; result %d", kr); - return -1; + ERR("could not clear output pipe; result %x, ignoring....\n", kr); } } diff --git a/gpttool/Android.mk b/gpttool/Android.mk new file mode 100644 index 0000000..a9fffe9 --- /dev/null +++ b/gpttool/Android.mk @@ -0,0 +1,14 @@ +ifeq ($(HOST_OS),linux) + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := gpttool.c +LOCAL_STATIC_LIBRARIES := libz + +LOCAL_MODULE := gpttool +LOCAL_MODULE_TAGS := eng + +include $(BUILD_HOST_EXECUTABLE) + +endif diff --git a/gpttool/gpttool.c b/gpttool/gpttool.c new file mode 100644 index 0000000..05d5177 --- /dev/null +++ b/gpttool/gpttool.c @@ -0,0 +1,376 @@ +/* system/core/gpttool/gpttool.c +** +** Copyright 2011, 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. +*/ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <fcntl.h> + +#include <zlib.h> + +#include <linux/fs.h> + +#include <sys/stat.h> + +typedef unsigned char u8; +typedef unsigned short u16; +typedef unsigned int u32; +typedef unsigned long long u64; + +const u8 partition_type_uuid[16] = { + 0xa2, 0xa0, 0xd0, 0xeb, 0xe5, 0xb9, 0x33, 0x44, + 0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7, +}; + + +#define EFI_VERSION 0x00010000 +#define EFI_MAGIC "EFI PART" +#define EFI_ENTRIES 128 +#define EFI_NAMELEN 36 + +struct efi_header { + u8 magic[8]; + + u32 version; + u32 header_sz; + + u32 crc32; + u32 reserved; + + u64 header_lba; + u64 backup_lba; + u64 first_lba; + u64 last_lba; + + u8 volume_uuid[16]; + + u64 entries_lba; + + u32 entries_count; + u32 entries_size; + u32 entries_crc32; +} __attribute__((packed)); + +struct efi_entry { + u8 type_uuid[16]; + u8 uniq_uuid[16]; + u64 first_lba; + u64 last_lba; + u64 attr; + u16 name[EFI_NAMELEN]; +}; + +struct ptable { + u8 mbr[512]; + union { + struct efi_header header; + u8 block[512]; + }; + struct efi_entry entry[EFI_ENTRIES]; +}; + +void get_uuid(u8 *uuid) +{ + int fd; + fd = open("/dev/urandom", O_RDONLY); + read(fd, uuid, 16); + close(fd); +} + +void init_mbr(u8 *mbr, u32 blocks) +{ + mbr[0x1be] = 0x00; // nonbootable + mbr[0x1bf] = 0xFF; // bogus CHS + mbr[0x1c0] = 0xFF; + mbr[0x1c1] = 0xFF; + + mbr[0x1c2] = 0xEE; // GPT partition + mbr[0x1c3] = 0xFF; // bogus CHS + mbr[0x1c4] = 0xFF; + mbr[0x1c5] = 0xFF; + + mbr[0x1c6] = 0x01; // start + mbr[0x1c7] = 0x00; + mbr[0x1c8] = 0x00; + mbr[0x1c9] = 0x00; + + memcpy(mbr + 0x1ca, &blocks, sizeof(u32)); + + mbr[0x1fe] = 0x55; + mbr[0x1ff] = 0xaa; +} + +int add_ptn(struct ptable *ptbl, u64 first, u64 last, const char *name) +{ + struct efi_header *hdr = &ptbl->header; + struct efi_entry *entry = ptbl->entry; + unsigned n; + + if (first < 34) { + fprintf(stderr,"partition '%s' overlaps partition table\n", name); + return -1; + } + + if (last > hdr->last_lba) { + fprintf(stderr,"partition '%s' does not fit on disk\n", name); + return -1; + } + for (n = 0; n < EFI_ENTRIES; n++, entry++) { + if (entry->type_uuid[0]) + continue; + memcpy(entry->type_uuid, partition_type_uuid, 16); + get_uuid(entry->uniq_uuid); + entry->first_lba = first; + entry->last_lba = last; + for (n = 0; (n < EFI_NAMELEN) && *name; n++) + entry->name[n] = *name++; + return 0; + } + fprintf(stderr,"out of partition table entries\n"); + return -1; +} + +int usage(void) +{ + fprintf(stderr, + "usage: gpttool write <disk> [ <partition> ]*\n" + " gpttool read <disk>\n" + " gpttool test [ <partition> ]*\n" + "\n" + "partition: [<name>]:<size>[kmg] | @<file-of-partitions>\n" + ); + return 0; +} + +void show(struct ptable *ptbl) +{ + struct efi_entry *entry = ptbl->entry; + unsigned n, m; + char name[EFI_NAMELEN]; + + fprintf(stderr,"ptn start block end block name\n"); + fprintf(stderr,"---- ------------- ------------- --------------------\n"); + + for (n = 0; n < EFI_ENTRIES; n++, entry++) { + if (entry->type_uuid[0] == 0) + break; + for (m = 0; m < EFI_NAMELEN; m++) { + name[m] = entry->name[m] & 127; + } + name[m] = 0; + fprintf(stderr,"#%03d %13lld %13lld %s\n", + n + 1, entry->first_lba, entry->last_lba, name); + } +} + +u64 find_next_lba(struct ptable *ptbl) +{ + struct efi_entry *entry = ptbl->entry; + unsigned n; + u64 a = 0; + for (n = 0; n < EFI_ENTRIES; n++, entry++) { + if ((entry->last_lba + 1) > a) + a = entry->last_lba + 1; + } + return a; +} + +u64 next_lba = 0; + +u64 parse_size(char *sz) +{ + int l = strlen(sz); + u64 n = strtoull(sz, 0, 10); + if (l) { + switch(sz[l-1]){ + case 'k': + case 'K': + n *= 1024; + break; + case 'm': + case 'M': + n *= (1024 * 1024); + break; + case 'g': + case 'G': + n *= (1024 * 1024 * 1024); + break; + } + } + return n; +} + +int parse_ptn(struct ptable *ptbl, char *x) +{ + char *y = strchr(x, ':'); + u64 sz; + + if (!y) { + fprintf(stderr,"invalid partition entry: %s\n", x); + return -1; + } + *y++ = 0; + + if (*y == 0) { + sz = ptbl->header.last_lba - next_lba; + } else { + sz = parse_size(y); + if (sz & 511) { + fprintf(stderr,"partition size must be multiple of 512\n"); + return -1; + } + sz /= 512; + } + + if (sz == 0) { + fprintf(stderr,"zero size partitions not allowed\n"); + return -1; + } + + if (x[0] && add_ptn(ptbl, next_lba, next_lba + sz - 1, x)) + return -1; + + next_lba = next_lba + sz; + return 0; +} + +int main(int argc, char **argv) +{ + struct ptable ptbl; + struct efi_entry *entry; + struct efi_header *hdr = &ptbl.header; + struct stat s; + u32 n; + u64 sz, blk; + int fd; + const char *device; + int real_disk = 0; + + if (argc < 2) + return usage(); + + if (!strcmp(argv[1], "write")) { + if (argc < 3) + return usage(); + device = argv[2]; + argc -= 2; + argv += 2; + real_disk = 1; + } else if (!strcmp(argv[1], "test")) { + argc -= 1; + argv += 1; + real_disk = 0; + sz = 2097152 * 16; + fprintf(stderr,"< simulating 16GB disk >\n\n"); + } else { + return usage(); + } + + if (real_disk) { + if (!strcmp(device, "/dev/sda") || + !strcmp(device, "/dev/sdb")) { + fprintf(stderr,"error: refusing to partition sda or sdb\n"); + return -1; + } + + fd = open(device, O_RDWR); + if (fd < 0) { + fprintf(stderr,"error: cannot open '%s'\n", device); + return -1; + } + if (ioctl(fd, BLKGETSIZE64, &sz)) { + fprintf(stderr,"error: cannot query block device size\n"); + return -1; + } + sz /= 512; + fprintf(stderr,"blocks %lld\n", sz); + } + + memset(&ptbl, 0, sizeof(ptbl)); + + init_mbr(ptbl.mbr, sz - 1); + + memcpy(hdr->magic, EFI_MAGIC, sizeof(hdr->magic)); + hdr->version = EFI_VERSION; + hdr->header_sz = sizeof(struct efi_header); + hdr->header_lba = 1; + hdr->backup_lba = sz - 1; + hdr->first_lba = 34; + hdr->last_lba = sz - 1; + get_uuid(hdr->volume_uuid); + hdr->entries_lba = 2; + hdr->entries_count = 128; + hdr->entries_size = sizeof(struct efi_entry); + + while (argc > 1) { + if (argv[1][0] == '@') { + char line[256], *p; + FILE *f; + f = fopen(argv[1] + 1, "r"); + if (!f) { + fprintf(stderr,"cannot read partitions from '%s\n", argv[1]); + return -1; + } + while (fgets(line, sizeof(line), f)) { + p = line + strlen(line); + while (p > line) { + p--; + if (*p > ' ') + break; + *p = 0; + } + p = line; + while (*p && (*p <= ' ')) + p++; + if (*p == '#') + continue; + if (*p == 0) + continue; + if (parse_ptn(&ptbl, p)) + return -1; + } + fclose(f); + } else { + if (parse_ptn(&ptbl, argv[1])) + return -1; + } + argc--; + argv++; + } + + n = crc32(0, Z_NULL, 0); + n = crc32(n, (void*) ptbl.entry, sizeof(ptbl.entry)); + hdr->entries_crc32 = n; + + n = crc32(0, Z_NULL, 0); + n = crc32(n, (void*) &ptbl.header, sizeof(ptbl.header)); + hdr->crc32 = n; + + show(&ptbl); + + if (real_disk) { + write(fd, &ptbl, sizeof(ptbl)); + fsync(fd); + + if (ioctl(fd, BLKRRPART, 0)) { + fprintf(stderr,"could not re-read partition table\n"); + } + close(fd); + } + return 0; +} diff --git a/include/acc/acc.h b/include/acc/acc.h deleted file mode 100644 index 1182355..0000000 --- a/include/acc/acc.h +++ /dev/null @@ -1,92 +0,0 @@ -/* - * 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); - -typedef ACCvoid* (*ACCSymbolLookupFn)(ACCvoid* pContext, const ACCchar * name); - -void accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, - ACCvoid* pContext); - -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); - -void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings); - -/* Used to implement disassembly */ - -void accGetProgramBinary(ACCscript* script, - ACCvoid** base, - ACCsizei* length); - -#ifdef __cplusplus -}; -#endif - -// ---------------------------------------------------------------------------- - -#endif diff --git a/include/arch/darwin-x86/AndroidConfig.h b/include/arch/darwin-x86/AndroidConfig.h index 9914bd5..d99072a 100644 --- a/include/arch/darwin-x86/AndroidConfig.h +++ b/include/arch/darwin-x86/AndroidConfig.h @@ -159,6 +159,11 @@ #define _LARGEFILE_SOURCE 1 /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +/* #define HAVE_OFF64_T */ + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/freebsd-x86/AndroidConfig.h b/include/arch/freebsd-x86/AndroidConfig.h index ed5af59..9703c76 100644 --- a/include/arch/freebsd-x86/AndroidConfig.h +++ b/include/arch/freebsd-x86/AndroidConfig.h @@ -175,6 +175,11 @@ #define _LARGEFILE_SOURCE 1 /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +/* #define HAVE_OFF64_T */ + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/linux-arm/AndroidConfig.h b/include/arch/linux-arm/AndroidConfig.h index c70618d..5138d90 100644 --- a/include/arch/linux-arm/AndroidConfig.h +++ b/include/arch/linux-arm/AndroidConfig.h @@ -174,6 +174,11 @@ /* #define _LARGEFILE_SOURCE 1 */ /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. @@ -206,7 +211,9 @@ /* * Add any extra platform-specific defines here. */ +#ifndef __linux__ #define __linux__ +#endif /* * Define if we have <malloc.h> header diff --git a/include/arch/linux-ppc/AndroidConfig.h b/include/arch/linux-ppc/AndroidConfig.h index 91af629..60bddd6 100644 --- a/include/arch/linux-ppc/AndroidConfig.h +++ b/include/arch/linux-ppc/AndroidConfig.h @@ -164,6 +164,11 @@ #define _LARGEFILE_SOURCE 1 /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/linux-sh/AndroidConfig.h b/include/arch/linux-sh/AndroidConfig.h index 622ca50..9303bb6 100644 --- a/include/arch/linux-sh/AndroidConfig.h +++ b/include/arch/linux-sh/AndroidConfig.h @@ -174,6 +174,11 @@ /* #define _LARGEFILE_SOURCE 1 */ /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/linux-x86/AndroidConfig.h b/include/arch/linux-x86/AndroidConfig.h index 26dcf1f..6fd26ea 100644 --- a/include/arch/linux-x86/AndroidConfig.h +++ b/include/arch/linux-x86/AndroidConfig.h @@ -164,6 +164,11 @@ #define _LARGEFILE_SOURCE 1 /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/target_linux-x86/AndroidConfig.h b/include/arch/target_linux-x86/AndroidConfig.h index 9b357d9..a6f7090 100644 --- a/include/arch/target_linux-x86/AndroidConfig.h +++ b/include/arch/target_linux-x86/AndroidConfig.h @@ -163,6 +163,11 @@ */ /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/arch/windows/AndroidConfig.h b/include/arch/windows/AndroidConfig.h index 17c84c7..8a7e062 100644 --- a/include/arch/windows/AndroidConfig.h +++ b/include/arch/windows/AndroidConfig.h @@ -177,6 +177,11 @@ #define _LARGEFILE_SOURCE 1 /* + * Define if platform has off64_t (and lseek64 and other xxx64 functions) + */ +#define HAVE_OFF64_T + +/* * Defined if we have the backtrace() call for retrieving a stack trace. * Needed for CallStack to operate; if not defined, CallStack is * non-functional. diff --git a/include/cutils/android_reboot.h b/include/cutils/android_reboot.h new file mode 100644 index 0000000..0c79be7 --- /dev/null +++ b/include/cutils/android_reboot.h @@ -0,0 +1,35 @@ +/* + * Copyright 2011, 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 __CUTILS_ANDROID_REBOOT_H__ +#define __CUTILS_ANDROID_REBOOT_H__ + +__BEGIN_DECLS + +/* Commands */ +#define ANDROID_RB_RESTART 0xDEAD0001 +#define ANDROID_RB_POWEROFF 0xDEAD0002 +#define ANDROID_RB_RESTART2 0xDEAD0003 + +/* Flags */ +#define ANDROID_RB_FLAG_NO_SYNC 0x1 +#define ANDROID_RB_FLAG_NO_REMOUNT_RO 0x2 + +int android_reboot(int cmd, int flags, char *arg); + +__END_DECLS + +#endif /* __CUTILS_ANDROID_REBOOT_H__ */ diff --git a/include/cutils/atomic-arm.h b/include/cutils/atomic-arm.h index 93633c4..16fe512 100644 --- a/include/cutils/atomic-arm.h +++ b/include/cutils/atomic-arm.h @@ -28,18 +28,29 @@ extern inline void android_compiler_barrier(void) #if ANDROID_SMP == 0 extern inline void android_memory_barrier(void) { - android_compiler_barrier(); + android_compiler_barrier(); +} +extern inline void android_memory_store_barrier(void) +{ + android_compiler_barrier(); } #elif defined(__ARM_HAVE_DMB) extern inline void android_memory_barrier(void) { __asm__ __volatile__ ("dmb" : : : "memory"); } +extern inline void android_memory_store_barrier(void) +{ + __asm__ __volatile__ ("dmb st" : : : "memory"); +} #elif defined(__ARM_HAVE_LDREX_STREX) extern inline void android_memory_barrier(void) { - __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" - : : "r" (0) : "memory"); + __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory"); +} +extern inline void android_memory_store_barrier(void) +{ + android_memory_barrier(); } #else extern inline void android_memory_barrier(void) @@ -47,6 +58,10 @@ extern inline void android_memory_barrier(void) typedef void (kuser_memory_barrier)(void); (*(kuser_memory_barrier *)0xffff0fa0)(); } +extern inline void android_memory_store_barrier(void) +{ + android_memory_barrier(); +} #endif extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) @@ -131,38 +146,6 @@ extern inline int android_atomic_release_cas(int32_t old_value, #if defined(__thumb__) -extern int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr); -#elif defined(__ARM_HAVE_LDREX_STREX) -extern inline int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr) -{ - int32_t prev, status; - do { - __asm__ __volatile__ ("ldrex %0, [%3]\n" - "strex %1, %4, [%3]" - : "=&r" (prev), "=&r" (status), "+m" (*ptr) - : "r" (ptr), "r" (new_value) - : "cc"); - } while (__builtin_expect(status != 0, 0)); - android_memory_barrier(); - return prev; -} -#else -extern inline int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr) -{ - int32_t prev; - __asm__ __volatile__ ("swp %0, %2, [%3]" - : "=&r" (prev), "+m" (*ptr) - : "r" (new_value), "r" (ptr) - : "cc"); - android_memory_barrier(); - return prev; -} -#endif - -#if defined(__thumb__) extern int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr); #elif defined(__ARM_HAVE_LDREX_STREX) diff --git a/include/cutils/atomic-inline.h b/include/cutils/atomic-inline.h index 715e0aa..6acb67c 100644 --- a/include/cutils/atomic-inline.h +++ b/include/cutils/atomic-inline.h @@ -55,4 +55,10 @@ #define ANDROID_MEMBAR_FULL android_memory_barrier #endif +#if ANDROID_SMP == 0 +#define ANDROID_MEMBAR_STORE android_compiler_barrier +#else +#define ANDROID_MEMBAR_STORE android_memory_store_barrier +#endif + #endif /* ANDROID_CUTILS_ATOMIC_INLINE_H */ diff --git a/include/cutils/atomic-x86.h b/include/cutils/atomic-x86.h index 12a1985..438012e 100644 --- a/include/cutils/atomic-x86.h +++ b/include/cutils/atomic-x86.h @@ -29,11 +29,19 @@ extern inline void android_memory_barrier(void) { android_compiler_barrier(); } +extern inline void android_memory_store_barrier(void) +{ + android_compiler_barrier(); +} #else extern inline void android_memory_barrier(void) { __asm__ __volatile__ ("mfence" : : : "memory"); } +extern inline void android_memory_store_barrier(void) +{ + android_compiler_barrier(); +} #endif extern inline int32_t android_atomic_acquire_load(volatile const int32_t *ptr) @@ -90,17 +98,6 @@ extern inline int android_atomic_release_cas(int32_t old_value, return android_atomic_cas(old_value, new_value, ptr); } -extern inline int32_t android_atomic_swap(int32_t new_value, - volatile int32_t *ptr) -{ - __asm__ __volatile__ ("xchgl %1, %0" - : "=r" (new_value) - : "m" (*ptr), "0" (new_value) - : "memory"); - /* new_value now holds the old value of *ptr */ - return new_value; -} - extern inline int32_t android_atomic_add(int32_t increment, volatile int32_t *ptr) { diff --git a/include/cutils/atomic.h b/include/cutils/atomic.h index a50bf0f..ae42eb8 100644 --- a/include/cutils/atomic.h +++ b/include/cutils/atomic.h @@ -90,13 +90,6 @@ void android_atomic_acquire_store(int32_t value, volatile int32_t* addr); void android_atomic_release_store(int32_t value, volatile int32_t* addr); /* - * Unconditional swap operation with release ordering. - * - * Stores the new value at *addr, and returns the previous value. - */ -int32_t android_atomic_swap(int32_t value, volatile int32_t* addr); - -/* * Compare-and-set operation with "acquire" or "release" ordering. * * This returns zero if the new value was successfully stored, which will diff --git a/include/netutils/dhcp.h b/include/netutils/dhcp.h index 96798c5..bd16240 100644 --- a/include/netutils/dhcp.h +++ b/include/netutils/dhcp.h @@ -24,12 +24,12 @@ __BEGIN_DECLS extern int do_dhcp(char *iname); extern int dhcp_do_request(const char *ifname, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease); extern int dhcp_stop(const char *ifname); extern int dhcp_release_lease(const char *ifname); diff --git a/include/netutils/ifc.h b/include/netutils/ifc.h index e245262..36827ee 100644 --- a/include/netutils/ifc.h +++ b/include/netutils/ifc.h @@ -36,8 +36,10 @@ extern int ifc_disable(const char *ifname); extern int ifc_reset_connections(const char *ifname); +extern int ifc_get_addr(const char *name, in_addr_t *addr); extern int ifc_set_addr(const char *name, in_addr_t addr); -extern int ifc_set_mask(const char *name, in_addr_t mask); +extern int ifc_get_prefixLength(const char *name, uint32_t *prefixLength); +extern int ifc_set_prefixLength(const char *name, uint32_t prefixLength); extern int ifc_set_hwaddr(const char *name, const void *ptr); /* This function is deprecated. Use ifc_add_route instead. */ @@ -56,7 +58,7 @@ extern int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, in_addr_t *flags); extern int ifc_configure(const char *ifname, in_addr_t address, - in_addr_t netmask, in_addr_t gateway, + uint32_t prefixLength, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2); __END_DECLS diff --git a/include/private/android_filesystem_config.h b/include/private/android_filesystem_config.h index 4d19f17..f23c235 100644 --- a/include/private/android_filesystem_config.h +++ b/include/private/android_filesystem_config.h @@ -53,11 +53,11 @@ #define AID_KEYSTORE 1017 /* keystore subsystem */ #define AID_USB 1018 /* USB devices */ #define AID_DRM 1019 /* DRM server */ -#define AID_DRMIO 1020 /* DRM IO server */ +#define AID_AVAILABLE 1020 /* available for use */ #define AID_GPS 1021 /* GPS daemon */ #define AID_UNUSED1 1022 /* deprecated, DO NOT USE */ -#define AID_RFU1 1023 /* RFU */ -#define AID_RFU2 1024 /* RFU */ +#define AID_MEDIA_RW 1023 /* internal media storage write access */ +#define AID_MTP 1024 /* MTP USB driver access */ #define AID_NFC 1025 /* nfc subsystem */ #define AID_SHELL 2000 /* adb and debug shell user */ @@ -101,7 +101,7 @@ static const struct android_id_info android_ids[] = { { "install", AID_INSTALL, }, { "media", AID_MEDIA, }, { "drm", AID_DRM, }, - { "drmio", AID_DRMIO, }, + { "available", AID_AVAILABLE, }, { "nfc", AID_NFC, }, { "shell", AID_SHELL, }, { "cache", AID_CACHE, }, @@ -109,9 +109,11 @@ static const struct android_id_info android_ids[] = { { "net_bt_admin", AID_NET_BT_ADMIN, }, { "net_bt", AID_NET_BT, }, { "sdcard_rw", AID_SDCARD_RW, }, + { "media_rw", AID_MEDIA_RW, }, { "vpn", AID_VPN, }, { "keystore", AID_KEYSTORE, }, { "usb", AID_USB, }, + { "mtp", AID_MTP, }, { "gps", AID_GPS, }, { "inet", AID_INET, }, { "net_raw", AID_NET_RAW, }, @@ -146,6 +148,8 @@ static struct fs_path_config android_dirs[] = { { 00771, AID_SHELL, AID_SHELL, "data/local" }, { 01771, AID_SYSTEM, AID_MISC, "data/misc" }, { 00770, AID_DHCP, AID_DHCP, "data/misc/dhcp" }, + { 00775, AID_MEDIA_RW, AID_MEDIA_RW, "data/media" }, + { 00775, AID_MEDIA_RW, AID_MEDIA_RW, "data/media/Music" }, { 00771, AID_SYSTEM, AID_SYSTEM, "data" }, { 00750, AID_ROOT, AID_SHELL, "sbin" }, { 00755, AID_ROOT, AID_SHELL, "system/bin" }, @@ -173,12 +177,14 @@ static struct fs_path_config android_files[] = { { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/main.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/input.conf" }, { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/audio.conf" }, + { 00440, AID_BLUETOOTH, AID_BLUETOOTH, "system/etc/bluetooth/network.conf" }, { 00444, AID_NET_BT, AID_NET_BT, "system/etc/bluetooth/blacklist.conf" }, { 00640, AID_SYSTEM, AID_SYSTEM, "system/etc/bluetooth/auto_pairing.conf" }, { 00444, AID_RADIO, AID_AUDIO, "system/etc/AudioPara4.csv" }, { 00555, AID_ROOT, AID_ROOT, "system/etc/ppp/*" }, { 00555, AID_ROOT, AID_ROOT, "system/etc/rc.*" }, { 00644, AID_SYSTEM, AID_SYSTEM, "data/app/*" }, + { 00644, AID_MEDIA_RW, AID_MEDIA_RW, "data/media/*" }, { 00644, AID_SYSTEM, AID_SYSTEM, "data/app-private/*" }, { 00644, AID_APP, AID_APP, "data/data/*" }, /* the following two files are INTENTIONALLY set-gid and not set-uid. @@ -197,6 +203,7 @@ static struct fs_path_config android_files[] = { * in user builds. */ { 06750, AID_ROOT, AID_SHELL, "system/bin/run-as" }, { 00755, AID_ROOT, AID_SHELL, "system/bin/*" }, + { 00755, AID_ROOT, AID_ROOT, "system/lib/valgrind/*" }, { 00755, AID_ROOT, AID_SHELL, "system/xbin/*" }, { 00755, AID_ROOT, AID_SHELL, "system/vendor/bin/*" }, { 00750, AID_ROOT, AID_SHELL, "sbin/*" }, diff --git a/include/usbhost/usbhost.h b/include/usbhost/usbhost.h new file mode 100644 index 0000000..9a6b59c --- /dev/null +++ b/include/usbhost/usbhost.h @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2010 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 __USB_HOST_H +#define __USB_HOST_H + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stdint.h> + +#include <linux/version.h> +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 20) +#include <linux/usb/ch9.h> +#else +#include <linux/usb_ch9.h> +#endif + +struct usb_host_context; +struct usb_endpoint_descriptor; + +struct usb_descriptor_iter { + unsigned char* config; + unsigned char* config_end; + unsigned char* curr_desc; +}; + +struct usb_request +{ + struct usb_device *dev; + void* buffer; + int buffer_length; + int actual_length; + int max_packet_size; + void *private_data; /* struct usbdevfs_urb* */ + int endpoint; + void *client_data; /* free for use by client */ +}; + +/* Callback for notification when new USB devices are attached. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_device_added_cb)(const char *dev_name, void *client_data); + +/* Callback for notification when USB devices are removed. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_device_removed_cb)(const char *dev_name, void *client_data); + +/* Callback indicating that initial device discovery is done. + * Return true to exit from usb_host_run. + */ +typedef int (* usb_discovery_done_cb)(void *client_data); + +/* Call this to initialize the USB host library. */ +struct usb_host_context *usb_host_init(void); + +/* Call this to cleanup the USB host library. */ +void usb_host_cleanup(struct usb_host_context *context); + +/* Call this to monitor the USB bus for new and removed devices. + * This is intended to be called from a dedicated thread, + * as it will not return until one of the callbacks returns true. + * added_cb will be called immediately for each existing USB device, + * and subsequently each time a new device is added. + * removed_cb is called when USB devices are removed from the bus. + * discovery_done_cb is called after the initial discovery of already + * connected devices is complete. + */ +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data); + +/* Creates a usb_device object for a USB device */ +struct usb_device *usb_device_open(const char *dev_name); + +/* Releases all resources associated with the USB device */ +void usb_device_close(struct usb_device *device); + +/* Creates a usb_device object for already open USB device */ +struct usb_device *usb_device_new(const char *dev_name, int fd); + +/* Returns the file descriptor for the usb_device */ +int usb_device_get_fd(struct usb_device *device); + +/* Returns the name for the USB device, which is the same as + * the dev_name passed to usb_device_open() + */ +const char* usb_device_get_name(struct usb_device *device); + +/* Returns a unique ID for the device. + *Currently this is generated from the dev_name path. + */ +int usb_device_get_unique_id(struct usb_device *device); + +/* Returns a unique ID for the device name. + * Currently this is generated from the device path. + */ +int usb_device_get_unique_id_from_name(const char* name); + +/* Returns the device name for the unique ID. + * Call free() to deallocate the returned string */ +char* usb_device_get_name_from_unique_id(int id); + +/* Returns the USB vendor ID from the device descriptor for the USB device */ +uint16_t usb_device_get_vendor_id(struct usb_device *device); + +/* Returns the USB product ID from the device descriptor for the USB device */ +uint16_t usb_device_get_product_id(struct usb_device *device); + +const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device); + +/* Returns a USB descriptor string for the given string ID. + * Used to implement usb_device_get_manufacturer_name, + * usb_device_get_product_name and usb_device_get_serial. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_string(struct usb_device *device, int id); + +/* Returns the manufacturer name for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_manufacturer_name(struct usb_device *device); + +/* Returns the product name for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_product_name(struct usb_device *device); + +/* Returns the USB serial number for the USB device. + * Call free() to free the result when you are done with it. + */ +char* usb_device_get_serial(struct usb_device *device); + +/* Returns true if we have write access to the USB device, + * and false if we only have access to the USB device configuration. + */ +int usb_device_is_writeable(struct usb_device *device); + +/* Initializes a usb_descriptor_iter, which can be used to iterate through all + * the USB descriptors for a USB device. + */ +void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter); + +/* Returns the next USB descriptor for a device, or NULL if we have reached the + * end of the list. + */ +struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter); + +/* Claims the specified interface of a USB device */ +int usb_device_claim_interface(struct usb_device *device, unsigned int interface); + +/* Releases the specified interface of a USB device */ +int usb_device_release_interface(struct usb_device *device, unsigned int interface); + +/* Requests the kernel to connect or disconnect its driver for the specified interface. + * This can be used to ask the kernel to disconnect its driver for a device + * so usb_device_claim_interface can claim it instead. + */ +int usb_device_connect_kernel_driver(struct usb_device *device, + unsigned int interface, int connect); + +/* Sends a control message to the specified device on endpoint zero */ +int usb_device_control_transfer(struct usb_device *device, + int requestType, + int request, + int value, + int index, + void* buffer, + int length, + unsigned int timeout); + +/* Reads or writes on a bulk endpoint. + * Returns number of bytes transferred, or negative value for error. + */ +int usb_device_bulk_transfer(struct usb_device *device, + int endpoint, + void* buffer, + int length, + unsigned int timeout); + +/* Creates a new usb_request. */ +struct usb_request *usb_request_new(struct usb_device *dev, + const struct usb_endpoint_descriptor *ep_desc); + +/* Releases all resources associated with the request */ +void usb_request_free(struct usb_request *req); + +/* Submits a read or write request on the specified device */ +int usb_request_queue(struct usb_request *req); + + /* Waits for the results of a previous usb_request_queue operation. + * Returns a usb_request, or NULL for error. + */ +struct usb_request *usb_request_wait(struct usb_device *dev); + +/* Cancels a pending usb_request_queue() operation. */ +int usb_request_cancel(struct usb_request *req); + +#ifdef __cplusplus +} +#endif +#endif /* __USB_HOST_H */ diff --git a/init/builtins.c b/init/builtins.c index e0ccf9f..f2f76b7 100644 --- a/init/builtins.c +++ b/init/builtins.c @@ -162,6 +162,12 @@ int do_class_stop(int nargs, char **args) return 0; } +int do_class_reset(int nargs, char **args) +{ + service_for_each_class(args[1], service_reset); + return 0; +} + int do_domainname(int nargs, char **args) { return write_file("/proc/sys/kernel/domainname", args[1]); @@ -258,7 +264,6 @@ static struct { const char *name; unsigned flag; } mount_flags[] = { - { "move", MS_MOVE }, { "noatime", MS_NOATIME }, { "nosuid", MS_NOSUID }, { "nodev", MS_NODEV }, @@ -270,6 +275,8 @@ static struct { { 0, 0 }, }; +#define DATA_MNT_POINT "/data" + /* mount <type> <device> <path> <flags ...> <options> */ int do_mount(int nargs, char **args) { @@ -315,7 +322,7 @@ int do_mount(int nargs, char **args) return -1; } - return 0; + goto exit_success; } else if (!strncmp(source, "loop@", 5)) { int mode, loop, fd; struct loop_info info; @@ -346,7 +353,7 @@ int do_mount(int nargs, char **args) } close(loop); - return 0; + goto exit_success; } } @@ -360,11 +367,68 @@ int do_mount(int nargs, char **args) if (wait) wait_for_file(source, COMMAND_RETRY_TIMEOUT); if (mount(source, target, system, flags, options) < 0) { - return -1; + /* If this fails, it may be an encrypted filesystem. + * We only support encrypting /data. Check + * if we're trying to mount it, and if so, + * assume it's encrypted, mount a tmpfs instead. + * Then save the orig mount parms in properties + * for vold to query when it mounts the real + * encrypted /data. + */ + if (!strcmp(target, DATA_MNT_POINT)) { + const char *tmpfs_options; + + tmpfs_options = property_get("ro.crypto.tmpfs_options"); + + if (mount("tmpfs", target, "tmpfs", MS_NOATIME | MS_NOSUID | MS_NODEV, + tmpfs_options) < 0) { + return -1; + } + + /* Set the property that triggers the framework to do a minimal + * startup and ask the user for a password + */ + property_set("ro.crypto.state", "encrypted"); + property_set("vold.decrypt", "1"); + } else { + return -1; + } } - return 0; + if (!strcmp(target, DATA_MNT_POINT)) { + char fs_flags[32]; + + /* Save the original mount options */ + property_set("ro.crypto.fs_type", system); + property_set("ro.crypto.fs_real_blkdev", source); + property_set("ro.crypto.fs_mnt_point", target); + if (options) { + property_set("ro.crypto.fs_options", options); + } + snprintf(fs_flags, sizeof(fs_flags), "0x%8.8x", flags); + property_set("ro.crypto.fs_flags", fs_flags); + } + } + +exit_success: + /* If not running encrypted, then set the property saying we are + * unencrypted, and also trigger the action for a nonencrypted system. + */ + if (!strcmp(target, DATA_MNT_POINT)) { + const char *prop; + + prop = property_get("ro.crypto.state"); + if (! prop) { + prop = "notset"; + } + if (strcmp(prop, "encrypted")) { + property_set("ro.crypto.state", "unencrypted"); + action_for_each_trigger("nonencrypted", action_add_queue_tail); + } } + + return 0; + } int do_setkey(int nargs, char **args) @@ -434,6 +498,16 @@ int do_symlink(int nargs, char **args) return symlink(args[1], args[2]); } +int do_rm(int nargs, char **args) +{ + return unlink(args[1]); +} + +int do_rmdir(int nargs, char **args) +{ + return rmdir(args[1]); +} + int do_sysclktz(int nargs, char **args) { struct timezone tz; @@ -558,6 +632,14 @@ int do_loglevel(int nargs, char **args) { return -1; } +int do_load_persist_props(int nargs, char **args) { + if (nargs == 1) { + load_persist_props(); + return 0; + } + return -1; +} + int do_wait(int nargs, char **args) { if (nargs == 2) { diff --git a/init/devices.c b/init/devices.c index eb5d84e..9c07e99 100644 --- a/init/devices.c +++ b/init/devices.c @@ -15,6 +15,7 @@ */ #include <errno.h> +#include <stddef.h> #include <stdio.h> #include <stdlib.h> #include <sys/stat.h> @@ -280,6 +281,57 @@ static void parse_event(const char *msg, struct uevent *uevent) uevent->firmware, uevent->major, uevent->minor); } +static char **get_character_device_symlinks(struct uevent *uevent) +{ + const char *parent; + char *slash; + char **links; + int link_num = 0; + int width; + + if (strncmp(uevent->path, "/devices/platform/", 18)) + return NULL; + + links = malloc(sizeof(char *) * 2); + if (!links) + return NULL; + memset(links, 0, sizeof(char *) * 2); + + /* skip "/devices/platform/<driver>" */ + parent = strchr(uevent->path + 18, '/'); + if (!*parent) + goto err; + + if (!strncmp(parent, "/usb", 4)) { + /* skip root hub name and device. use device interface */ + while (*++parent && *parent != '/'); + if (*parent) + while (*++parent && *parent != '/'); + if (!*parent) + goto err; + slash = strchr(++parent, '/'); + if (!slash) + goto err; + width = slash - parent; + if (width <= 0) + goto err; + + if (asprintf(&links[link_num], "/dev/usb/%s%.*s", uevent->subsystem, width, parent) > 0) + link_num++; + else + links[link_num] = NULL; + mkdir("/dev/usb", 0755); + } + else { + goto err; + } + + return links; +err: + free(links); + return NULL; +} + static char **parse_platform_block_device(struct uevent *uevent) { const char *driver; @@ -426,6 +478,7 @@ static void handle_device_event(struct uevent *uevent) name += 4; } else base = "/dev/"; + links = get_character_device_symlinks(uevent); } if (!devpath_ready) @@ -539,8 +592,10 @@ static void process_firmware_event(struct uevent *uevent) fw_fd = open(file1, O_RDONLY); if(fw_fd < 0) { fw_fd = open(file2, O_RDONLY); - if(fw_fd < 0) + if (fw_fd < 0) { + write(loading_fd, "-1", 2); goto data_close_out; + } } if(!load_firmware(fw_fd, loading_fd, data_fd)) diff --git a/init/init.c b/init/init.c index 75ffb5c..e13d4b1 100755 --- a/init/init.c +++ b/init/init.c @@ -150,11 +150,11 @@ void service_start(struct service *svc, const char *dynamic_args) int needs_console; int n; - /* starting a service removes it from the disabled + /* starting a service removes it from the disabled or reset * state and immediately takes it out of the restarting * state if it was in there */ - svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING)); + svc->flags &= (~(SVC_DISABLED|SVC_RESTARTING|SVC_RESET)); svc->time_started = 0; /* running processes require no additional work -- if @@ -243,13 +243,22 @@ void service_start(struct service *svc, const char *dynamic_args) /* as requested, set our gid, supplemental gids, and uid */ if (svc->gid) { - setgid(svc->gid); + if (setgid(svc->gid) != 0) { + ERROR("setgid failed: %s\n", strerror(errno)); + _exit(127); + } } if (svc->nr_supp_gids) { - setgroups(svc->nr_supp_gids, svc->supp_gids); + if (setgroups(svc->nr_supp_gids, svc->supp_gids) != 0) { + ERROR("setgroups failed: %s\n", strerror(errno)); + _exit(127); + } } if (svc->uid) { - setuid(svc->uid); + if (setuid(svc->uid) != 0) { + ERROR("setuid failed: %s\n", strerror(errno)); + _exit(127); + } } if (!dynamic_args) { @@ -291,27 +300,42 @@ void service_start(struct service *svc, const char *dynamic_args) notify_service_state(svc->name, "running"); } -void service_stop(struct service *svc) +/* The how field should be either SVC_DISABLED or SVC_RESET */ +static void service_stop_or_reset(struct service *svc, int how) { /* we are no longer running, nor should we * attempt to restart */ svc->flags &= (~(SVC_RUNNING|SVC_RESTARTING)); + if ((how != SVC_DISABLED) && (how != SVC_RESET)) { + /* Hrm, an illegal flag. Default to SVC_DISABLED */ + how = SVC_DISABLED; + } /* if the service has not yet started, prevent * it from auto-starting with its class */ - svc->flags |= SVC_DISABLED; + svc->flags |= how; if (svc->pid) { NOTICE("service '%s' is being killed\n", svc->name); - kill(-svc->pid, SIGTERM); + kill(-svc->pid, SIGKILL); notify_service_state(svc->name, "stopping"); } else { notify_service_state(svc->name, "stopped"); } } +void service_reset(struct service *svc) +{ + service_stop_or_reset(svc, SVC_RESET); +} + +void service_stop(struct service *svc) +{ + service_stop_or_reset(svc, SVC_DISABLED); +} + void property_changed(const char *name, const char *value) { if (property_triggers_enabled) @@ -384,6 +408,9 @@ void handle_control_message(const char *msg, const char *arg) msg_start(arg); } else if (!strcmp(msg,"stop")) { msg_stop(arg); + } else if (!strcmp(msg,"restart")) { + msg_stop(arg); + msg_start(arg); } else { ERROR("unknown control msg '%s'\n", msg); } @@ -674,7 +701,7 @@ int main(int argc, char **argv) mkdir("/proc", 0755); mkdir("/sys", 0755); - mount("tmpfs", "/dev", "tmpfs", 0, "mode=0755"); + mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mkdir("/dev/pts", 0755); mkdir("/dev/socket", 0755); mount("devpts", "/dev/pts", "devpts", 0, NULL); @@ -713,6 +740,7 @@ int main(int argc, char **argv) action_for_each_trigger("early-fs", action_add_queue_tail); action_for_each_trigger("fs", action_add_queue_tail); action_for_each_trigger("post-fs", action_add_queue_tail); + action_for_each_trigger("post-fs-data", action_add_queue_tail); queue_builtin_action(property_service_init_action, "property_service_init"); queue_builtin_action(signal_init_action, "signal_init"); diff --git a/init/init.h b/init/init.h index 8691335..05cdfaa 100644 --- a/init/init.h +++ b/init/init.h @@ -69,6 +69,8 @@ struct svcenvinfo { #define SVC_RESTARTING 0x08 /* waiting to restart */ #define SVC_CONSOLE 0x10 /* requires console */ #define SVC_CRITICAL 0x20 /* will reboot into recovery if keeps crashing */ +#define SVC_RESET 0x40 /* Use when stopping a process, but not disabling + so it can be restarted with its class */ #define NR_SVC_SUPP_GIDS 12 /* twelve supplementary groups */ @@ -121,6 +123,7 @@ void service_for_each_class(const char *classname, void service_for_each_flags(unsigned matchflags, void (*func)(struct service *svc)); void service_stop(struct service *svc); +void service_reset(struct service *svc); void service_start(struct service *svc, const char *dynamic_args); void property_changed(const char *name, const char *value); diff --git a/init/init_parser.c b/init/init_parser.c index fafd732..e8e65ac 100644 --- a/init/init_parser.c +++ b/init/init_parser.c @@ -82,6 +82,7 @@ int lookup_keyword(const char *s) if (!strcmp(s, "lass")) return K_class; if (!strcmp(s, "lass_start")) return K_class_start; if (!strcmp(s, "lass_stop")) return K_class_stop; + if (!strcmp(s, "lass_reset")) return K_class_reset; if (!strcmp(s, "onsole")) return K_console; if (!strcmp(s, "hown")) return K_chown; if (!strcmp(s, "hmod")) return K_chmod; @@ -112,6 +113,7 @@ int lookup_keyword(const char *s) break; case 'l': if (!strcmp(s, "oglevel")) return K_loglevel; + if (!strcmp(s, "oad_persist_props")) return K_load_persist_props; break; case 'm': if (!strcmp(s, "kdir")) return K_mkdir; @@ -124,6 +126,8 @@ int lookup_keyword(const char *s) break; case 'r': if (!strcmp(s, "estart")) return K_restart; + if (!strcmp(s, "mdir")) return K_rmdir; + if (!strcmp(s, "m")) return K_rm; break; case 's': if (!strcmp(s, "ervice")) return K_service; diff --git a/init/keychords.c b/init/keychords.c index febb62f..aab0819 100644 --- a/init/keychords.c +++ b/init/keychords.c @@ -17,9 +17,11 @@ #include <errno.h> #include <fcntl.h> #include <stdlib.h> +#include <string.h> #include <sys/stat.h> #include <sys/types.h> #include <linux/keychord.h> +#include <unistd.h> #include "init.h" #include "log.h" diff --git a/init/keywords.h b/init/keywords.h index 25315d8..95acd01 100644 --- a/init/keywords.h +++ b/init/keywords.h @@ -4,6 +4,7 @@ int do_chroot(int nargs, char **args); int do_chdir(int nargs, char **args); int do_class_start(int nargs, char **args); int do_class_stop(int nargs, char **args); +int do_class_reset(int nargs, char **args); int do_domainname(int nargs, char **args); int do_exec(int nargs, char **args); int do_export(int nargs, char **args); @@ -14,6 +15,8 @@ int do_import(int nargs, char **args); int do_mkdir(int nargs, char **args); int do_mount(int nargs, char **args); int do_restart(int nargs, char **args); +int do_rm(int nargs, char **args); +int do_rmdir(int nargs, char **args); int do_setkey(int nargs, char **args); int do_setprop(int nargs, char **args); int do_setrlimit(int nargs, char **args); @@ -27,6 +30,7 @@ int do_copy(int nargs, char **args); int do_chown(int nargs, char **args); int do_chmod(int nargs, char **args); int do_loglevel(int nargs, char **args); +int do_load_persist_props(int nargs, char **args); int do_wait(int nargs, char **args); #define __MAKE_KEYWORD_ENUM__ #define KEYWORD(symbol, flags, nargs, func) K_##symbol, @@ -39,6 +43,7 @@ enum { KEYWORD(class, OPTION, 0, 0) KEYWORD(class_start, COMMAND, 1, do_class_start) KEYWORD(class_stop, COMMAND, 1, do_class_stop) + KEYWORD(class_reset, COMMAND, 1, do_class_reset) KEYWORD(console, OPTION, 0, 0) KEYWORD(critical, OPTION, 0, 0) KEYWORD(disabled, OPTION, 0, 0) @@ -57,6 +62,8 @@ enum { KEYWORD(oneshot, OPTION, 0, 0) KEYWORD(onrestart, OPTION, 0, 0) KEYWORD(restart, COMMAND, 1, do_restart) + KEYWORD(rm, COMMAND, 1, do_rm) + KEYWORD(rmdir, COMMAND, 1, do_rmdir) KEYWORD(service, SECTION, 0, 0) KEYWORD(setenv, OPTION, 2, 0) KEYWORD(setkey, COMMAND, 0, do_setkey) @@ -75,6 +82,7 @@ enum { KEYWORD(chown, COMMAND, 2, do_chown) KEYWORD(chmod, COMMAND, 2, do_chmod) KEYWORD(loglevel, COMMAND, 1, do_loglevel) + KEYWORD(load_persist_props, COMMAND, 0, do_load_persist_props) KEYWORD(ioprio, OPTION, 0, 0) #ifdef __MAKE_KEYWORD_ENUM__ KEYWORD_COUNT, diff --git a/init/list.h b/init/list.h index 0a7b28c..7b9ef32 100644 --- a/init/list.h +++ b/init/list.h @@ -17,6 +17,8 @@ #ifndef _INIT_LIST_H_ #define _INIT_LIST_H_ +#include <stddef.h> + struct listnode { struct listnode *next; diff --git a/init/property_service.c b/init/property_service.c index d8fea56..c8d6c09 100644 --- a/init/property_service.c +++ b/init/property_service.c @@ -61,6 +61,7 @@ struct { { "net.rmnet0.", AID_RADIO, 0 }, { "net.gprs.", AID_RADIO, 0 }, { "net.ppp", AID_RADIO, 0 }, + { "net.qmi", AID_RADIO, 0 }, { "ril.", AID_RADIO, 0 }, { "gsm.", AID_RADIO, 0 }, { "persist.radio", AID_RADIO, 0 }, @@ -79,6 +80,7 @@ struct { { "debug.", AID_SHELL, 0 }, { "log.", AID_SHELL, 0 }, { "service.adb.root", AID_SHELL, 0 }, + { "service.adb.tcp.port", AID_SHELL, 0 }, { "persist.sys.", AID_SYSTEM, 0 }, { "persist.service.", AID_SYSTEM, 0 }, { "persist.security.", AID_SYSTEM, 0 }, @@ -95,6 +97,7 @@ struct { unsigned int gid; } control_perms[] = { { "dumpstate",AID_SHELL, AID_LOG }, + { "ril-daemon",AID_RADIO, AID_RADIO }, {NULL, 0, 0 } }; @@ -186,15 +189,6 @@ static void update_prop_info(prop_info *pi, const char *value, unsigned len) __futex_wake(&pi->serial, INT32_MAX); } -static int property_write(prop_info *pi, const char *value) -{ - int valuelen = strlen(value); - if(valuelen >= PROP_VALUE_MAX) return -1; - update_prop_info(pi, value, valuelen); - return 0; -} - - /* * Checks permissions for starting/stoping system services. * AID_SYSTEM and AID_ROOT are always allowed. @@ -381,8 +375,8 @@ void handle_property_set_fd() } r = recv(s, &msg, sizeof(msg), 0); - close(s); if(r != sizeof(prop_msg)) { + close(s); ERROR("sys_prop: mis-match msg size recieved: %d expected: %d\n", r, sizeof(prop_msg)); return; @@ -394,11 +388,14 @@ void handle_property_set_fd() msg.value[PROP_VALUE_MAX-1] = 0; if(memcmp(msg.name,"ctl.",4) == 0) { + // Keep the old close-socket-early behavior when handling + // ctl.* properties. + close(s); if (check_control_perms(msg.value, cr.uid, cr.gid)) { handle_control_message((char*) msg.name + 4, (char*) msg.value); } else { - ERROR("sys_prop: Unable to %s service ctl [%s] uid: %d pid:%d\n", - msg.name + 4, msg.value, cr.uid, cr.pid); + ERROR("sys_prop: Unable to %s service ctl [%s] uid:%d gid:%d pid:%d\n", + msg.name + 4, msg.value, cr.uid, cr.gid, cr.pid); } } else { if (check_perms(msg.name, cr.uid, cr.gid)) { @@ -407,10 +404,16 @@ void handle_property_set_fd() ERROR("sys_prop: permission denied uid:%d name:%s\n", cr.uid, msg.name); } + + // Note: bionic's property client code assumes that the + // property server will not close the socket until *AFTER* + // the property is written to memory. + close(s); } break; default: + close(s); break; } } @@ -512,6 +515,18 @@ int properties_inited(void) return property_area_inited; } +/* When booting an encrypted system, /data is not mounted when the + * property service is started, so any properties stored there are + * not loaded. Vold triggers init to load these properties once it + * has mounted /data. + */ +void load_persist_props(void) +{ + load_properties_from_file(PROP_PATH_LOCAL_OVERRIDE); + /* Read persistent properties after all default values have been loaded. */ + load_persistent_properties(); +} + void start_property_service(void) { int fd; diff --git a/init/property_service.h b/init/property_service.h index 045d20a..bc97cc4 100644 --- a/init/property_service.h +++ b/init/property_service.h @@ -19,6 +19,7 @@ extern void handle_property_set_fd(void); extern void property_init(void); +extern void load_persist_props(void); extern void start_property_service(void); void get_property_workspace(int *fd, int *sz); extern const char* property_get(const char *name); diff --git a/init/signal_handler.c b/init/signal_handler.c index 3e5d136..f89d058 100644 --- a/init/signal_handler.c +++ b/init/signal_handler.c @@ -23,7 +23,7 @@ #include <sys/socket.h> #include <sys/wait.h> #include <cutils/sockets.h> -#include <sys/reboot.h> +#include <cutils/android_reboot.h> #include "init.h" #include "list.h" @@ -83,8 +83,8 @@ static int wait_for_one_process(int block) svc->flags |= SVC_DISABLED; } - /* disabled processes do not get restarted automatically */ - if (svc->flags & SVC_DISABLED) { + /* disabled and reset processes do not get restarted automatically */ + if (svc->flags & (SVC_DISABLED | SVC_RESET) ) { notify_service_state(svc->name, "stopped"); return 0; } @@ -96,9 +96,7 @@ static int wait_for_one_process(int block) ERROR("critical process '%s' exited %d times in %d minutes; " "rebooting into recovery mode\n", svc->name, CRITICAL_CRASH_THRESHOLD, CRITICAL_CRASH_WINDOW / 60); - sync(); - __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, - LINUX_REBOOT_CMD_RESTART2, "recovery"); + android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); return 0; } } else { diff --git a/libacc/Android.mk b/libacc/Android.mk deleted file mode 100644 index 5101e16..0000000 --- a/libacc/Android.mk +++ /dev/null @@ -1,31 +0,0 @@ -LOCAL_PATH:= $(call my-dir) -include $(CLEAR_VARS) - -# Shared library for target -# ======================================================== - -LOCAL_MODULE:= libacc -LOCAL_SRC_FILES := acc.cpp - -LOCAL_SHARED_LIBRARIES := libdl libcutils - -include $(BUILD_SHARED_LIBRARY) - -# Static library for host -# ======================================================== - -include $(CLEAR_VARS) -LOCAL_MODULE:= libacc -LOCAL_SRC_FILES := acc.cpp - -LOCAL_CFLAGS := -O0 -g - -LOCAL_STATIC_LIBRARIES := libcutils -LOCAL_LDLIBS := -ldl - -include $(BUILD_HOST_STATIC_LIBRARY) - -# Build children -# ======================================================== - -include $(call all-makefiles-under,$(LOCAL_PATH)) diff --git a/libacc/FEATURES b/libacc/FEATURES deleted file mode 100644 index 20f9d98..0000000 --- a/libacc/FEATURES +++ /dev/null @@ -1,89 +0,0 @@ - -Supported C language subset: - - - Expressions: - - * binary operators, by decreasing priority order: '*' '/' '%', - '+' '-', '>>' '<<', '<' '<=' '>' '>=', '==' '!=', '&', - '^', '|', '=', '&&', '||'. - - * '&&' and '||' have the same semantics as C : left to right - evaluation and early exit. - - * Parenthesis are supported. - - * Comma operator is supported. - - * Trinary operator (?:) is not supported. - - * Unary operators: '&', '*' (pointer indirection), '-' - (negation), '+', '!', '~', '++' and '--'. - - * Pointer indirection ('*') is supported. - - * Square brackets are supported. - - * '=' and <op>= are supported. - - * Function calls are supported with standard Linux calling - convention. Function pointers are supported. - Functions can be used before being declared. - - - sizeof() is not supported. - - - Types: - + int, short, char, float, double - + pointers - + variables can be initialized in declarations. - + Only ANSI-style function declarations are supported. - - "..." is not supported. - - short is supported - - const is not supported - - signed and unsigned are not supported. - - arrays are supported - - long doubles are not supported - - structs and unions are supported - - typedef is supported - - explicit storage class specifiers are not supported: register, auto, static, extern - - - Unknown functions and variables are bound at compile time by calling - back to the caller. For the 'acc' command-line tool unknown functions - and variables are looked up using dlsym, to allow using many libc - functions and variables. - - - 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. - - - switch / case is not supported. - - goto and labels are not supported. - - continue is not supported. - - - 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). - - - Float and double constants are supported. - - - '#define' is supported without function like arguments. - - Macro recursion is allowed. - - Self-referential macros are handled as in gcc. - - '#pragma' is supported. The pragma text is passed to a callback function, - and is used to implement meta-information. - - Other preprocessor directives are ignored. - - - C Strings and C character constants are supported. All ANSI C - character escapes are supported. - - - Both C comments ( /* */ ) and C++ comments ( // ... end-of-line ) are - supported. - - - Some syntax errors are reported, others may cause a crash. - - - Memory: the code, data, and symbol sizes are limited to 100KB - (it can be changed in the source code). - diff --git a/libacc/LICENSE b/libacc/LICENSE deleted file mode 100644 index aea41e0..0000000 --- a/libacc/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ - 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/MODULE_LICENSE_BSD_LIKE b/libacc/MODULE_LICENSE_BSD_LIKE deleted file mode 100644 index e69de29..0000000 --- a/libacc/MODULE_LICENSE_BSD_LIKE +++ /dev/null diff --git a/libacc/acc.cpp b/libacc/acc.cpp deleted file mode 100644 index 6e13f9a..0000000 --- a/libacc/acc.cpp +++ /dev/null @@ -1,6407 +0,0 @@ -/* - * 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. - * - */ - -#define LOG_TAG "acc" -#include <cutils/log.h> - -#include <ctype.h> -#include <errno.h> -#include <limits.h> -#include <stdarg.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include <cutils/hashmap.h> - -#include <sys/mman.h> - -#if defined(MAP_ANON) && !defined(MAP_ANONYMOUS) -#define MAP_ANONYMOUS MAP_ANON -#endif - -#if defined(__arm__) -#define DEFAULT_ARM_CODEGEN -#define PROVIDE_ARM_CODEGEN -#elif defined(__i386__) -#define DEFAULT_X86_CODEGEN -#define PROVIDE_X86_CODEGEN -#elif defined(__x86_64__) -#define DEFAULT_X64_CODEGEN -#define PROVIDE_X64_CODEGEN -#endif - -#if (defined(__VFP_FP__) && !defined(__SOFTFP__)) -#define ARM_USE_VFP -#endif - -#include <acc/acc.h> - -#define LOG_API(...) do {} while(0) -// #define LOG_API(...) fprintf (stderr, __VA_ARGS__) - -#define LOG_STACK(...) do {} while(0) -// #define LOG_STACK(...) fprintf (stderr, __VA_ARGS__) - -// #define PROVIDE_TRACE_CODEGEN - -// Uncomment to disable ARM peephole optimizations -// #define DISABLE_ARM_PEEPHOLE - -// Uncomment to save input to a text file in DEBUG_DUMP_PATTERN -// #define DEBUG_SAVE_INPUT_TO_FILE - -#ifdef DEBUG_SAVE_INPUT_TO_FILE -#ifdef ARM_USE_VFP -#define DEBUG_DUMP_PATTERN "/data/misc/acc_dump/%d.c" -#else -#define DEBUG_DUMP_PATTERN "/tmp/acc_dump/%d.c" -#endif -#endif - -#define assert(b) assertImpl(b, __LINE__) - -namespace acc { - -// Subset of STL vector. -template<class E> class Vector { - public: - Vector() { - mpBase = 0; - mUsed = 0; - mSize = 0; - } - - ~Vector() { - if (mpBase) { - clear(); - free(mpBase); - } - } - - inline E& operator[](size_t i) { - return mpBase[i]; - } - - inline E& front() { - return mpBase[0]; - } - - inline E& back() { - return mpBase[mUsed - 1]; - } - - void pop_back() { - mUsed -= 1; - mpBase[mUsed].~E(); - } - - void push_back(const E& item) { - * ensure(1) = item; - } - - inline size_t size() { - return mUsed; - } - - void clear() { - if (mpBase) { - size_t used = mUsed; - for(size_t i = 0; i < used; i++) { - mpBase[i].~E(); - } - } - mUsed = 0; - } - -private: - E* ensure(int n) { - size_t newUsed = mUsed + n; - if (newUsed > mSize) { - size_t newSize = mSize * 2 + 10; - if (newSize < newUsed) { - newSize = newUsed; - } - mpBase = (E*) realloc(mpBase, sizeof(E) * newSize); - mSize = newSize; - } - E* result = mpBase + mUsed; - mUsed = newUsed; - return result; - } - - E* mpBase; - size_t mUsed; - size_t mSize; -}; - -class ErrorSink { -public: - void error(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - verror(fmt, ap); - va_end(ap); - } - - virtual ~ErrorSink() {} - virtual void verror(const char* fmt, va_list ap) = 0; -}; - -class Compiler : public ErrorSink { - typedef int tokenid_t; - enum TypeTag { - TY_UNKNOWN = -1, - TY_INT, // 0 - TY_CHAR, // 1 - TY_SHORT, // 2 - TY_VOID, // 3 - TY_FLOAT, // 4 - TY_DOUBLE, // 5 - TY_POINTER, // 6 - TY_ARRAY, // 7 - TY_STRUCT, // 8 - TY_FUNC, // 9 - TY_PARAM // 10 - }; - - enum StorageClass { - SC_DEFAULT, // 0 - SC_AUTO, // 1 - SC_REGISTER, // 2 - SC_STATIC, // 3 - SC_EXTERN, // 4 - SC_TYPEDEF // 5 - }; - - struct Type { - TypeTag tag; - StorageClass storageClass; - tokenid_t id; // For function arguments, global vars, local vars, struct elements - tokenid_t structTag; // For structs the name of the struct - int length; // length of array, offset of struct element. -1 means struct is forward defined - int alignment; // for structs only - Type* pHead; // For a struct this is the prototype struct. - Type* pTail; - }; - - enum ExpressionType { - ET_RVALUE, - ET_LVALUE - }; - - struct ExpressionValue { - ExpressionValue() { - et = ET_RVALUE; - pType = NULL; - } - ExpressionType et; - Type* pType; - }; - - class ICodeBuf { - public: - virtual ~ICodeBuf() {} - virtual void init(int size) = 0; - virtual void setErrorSink(ErrorSink* pErrorSink) = 0; - virtual void o4(int n) = 0; - virtual void ob(int n) = 0; - virtual void* getBase() = 0; - virtual intptr_t getSize() = 0; - virtual intptr_t getPC() = 0; - // Call this before trying to modify code in the buffer. - virtual void flush() = 0; - }; - - class CodeBuf : public ICodeBuf { - char* ind; // Output code pointer - char* pProgramBase; - ErrorSink* mErrorSink; - int mSize; - bool mOverflowed; - - void release() { - if (pProgramBase != 0) { - munmap(pProgramBase, mSize); - pProgramBase = 0; - } - } - - bool check(int n) { - int newSize = ind - pProgramBase + n; - bool overflow = newSize > mSize; - if (overflow && !mOverflowed) { - mOverflowed = true; - if (mErrorSink) { - mErrorSink->error("Code too large: %d bytes", newSize); - } - } - return overflow; - } - - public: - CodeBuf() { - pProgramBase = 0; - ind = 0; - mErrorSink = 0; - mSize = 0; - mOverflowed = false; - } - - virtual ~CodeBuf() { - release(); - } - - virtual void init(int size) { - release(); - mSize = size; - pProgramBase = (char*) mmap(NULL, size, - PROT_EXEC | PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); - ind = pProgramBase; - } - - virtual void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - } - - virtual void o4(int n) { - if(check(4)) { - return; - } - * (int*) ind = n; - ind += 4; - } - - /* - * Output a byte. Handles all values, 0..ff. - */ - virtual void ob(int n) { - if(check(1)) { - return; - } - *ind++ = n; - } - - virtual void* getBase() { - return (void*) pProgramBase; - } - - virtual intptr_t getSize() { - return ind - pProgramBase; - } - - virtual intptr_t getPC() { - return (intptr_t) ind; - } - - virtual void flush() {} - }; - - /** - * 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 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 register is not saved across function calls. The - * FP and SP registers are saved. - */ - - class CodeGenerator { - public: - CodeGenerator() { - mErrorSink = 0; - pCodeBuf = 0; - pushType(); - } - virtual ~CodeGenerator() {} - - virtual void init(ICodeBuf* pCodeBuf) { - this->pCodeBuf = pCodeBuf; - pCodeBuf->setErrorSink(mErrorSink); - } - - virtual void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - if (pCodeBuf) { - pCodeBuf->setErrorSink(mErrorSink); - } - } - - /* Give the code generator some utility types so it can - * use its own types as needed for the results of some - * operations like gcmp. - */ - - void setTypes(Type* pInt) { - mkpInt = pInt; - } - - /* Emit a function prolog. - * pDecl is the function declaration, which gives the 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(Type* pDecl) = 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(Type* pDecl, int localVariableAddress, - int localVariableSize) = 0; - - /* load immediate value to R0 */ - virtual void li(int i) = 0; - - /* Load floating point value from global address. */ - virtual void loadFloat(int address, Type* pType) = 0; - - /* Add the struct offset in bytes to R0, change the type to pType */ - virtual void addStructOffsetR0(int offset, Type* pType) = 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; - - /* 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 TOS against R0, and store the boolean result in R0. - * Pops TOS. - * op specifies the comparison. - */ - virtual void gcmp(int op) = 0; - - /* Perform the arithmetic op specified by op. TOS is the - * left argument, R0 is the right argument. - * Pops TOS. - */ - virtual void genOp(int op) = 0; - - /* Compare 0 against R0, and store the boolean result in R0. - * op specifies the comparison. - */ - virtual void gUnaryCmp(int op) = 0; - - /* Perform the arithmetic op specified by op. 0 is the - * left argument, R0 is the right argument. - */ - virtual void genUnaryOp(int op) = 0; - - /* Push R0 onto the stack. (Also known as "dup" for duplicate.) - */ - virtual void pushR0() = 0; - - /* Turn R0, TOS into R0 TOS R0 */ - - virtual void over() = 0; - - /* Pop R0 from the stack. (Also known as "drop") - */ - virtual void popR0() = 0; - - /* Store R0 to the address stored in TOS. - * The TOS is popped. - */ - virtual void storeR0ToTOS() = 0; - - /* Load R0 from the address stored in R0. - */ - virtual void loadR0FromR0() = 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. - * - * et is ET_RVALUE for things like string constants, ET_LVALUE for - * variables. - */ - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) = 0; - - /* Load the pc-relative address of a forward-referenced variable to R0. - * Return the address of the 4-byte constant so that it can be filled - * in later. - */ - virtual int leaForward(int ea, Type* pPointerType) = 0; - - /** - * Convert R0 to the given type. - */ - - void convertR0(Type* pType) { - convertR0Imp(pType, false); - } - - void castR0(Type* pType) { - convertR0Imp(pType, true); - } - - virtual void convertR0Imp(Type* pType, bool isCast) = 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; - - /* Emit code to store R0 to the stack at byte offset l. - * Returns stack size of object (typically 4 or 8 bytes) - */ - virtual size_t storeR0ToArg(int l, Type* pArgType) = 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(Type* pDecl, 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, Type* pFunc) = 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, Type* pFunc) = 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(Type* pDecl, int l, bool isIndirect) = 0; - - /* 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; - - /* Resolve a forward reference function at the current PC. - * t is the head of a - * linked list of addresses to patch. - * (Like gsym, but using absolute address, not PC relative address.) - */ - virtual void resolveForward(int t) = 0; - - /* - * 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. - */ - virtual int jumpOffset() = 0; - - /** - * Memory alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* type) = 0; - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* type) = 0; - - virtual Type* getR0Type() { - return mExpressionStack.back().pType; - } - - virtual ExpressionType getR0ExpressionType() { - return mExpressionStack.back().et; - } - - virtual void setR0ExpressionType(ExpressionType et) { - mExpressionStack.back().et = et; - } - - virtual size_t getExpressionStackDepth() { - return mExpressionStack.size(); - } - - virtual void forceR0RVal() { - if (getR0ExpressionType() == ET_LVALUE) { - loadR0FromR0(); - } - } - - protected: - /* - * Output a byte. Handles all values, 0..ff. - */ - void ob(int n) { - pCodeBuf->ob(n); - } - - void o4(int data) { - pCodeBuf->o4(data); - } - - intptr_t getBase() { - return (intptr_t) pCodeBuf->getBase(); - } - - intptr_t getPC() { - return pCodeBuf->getPC(); - } - - intptr_t getSize() { - return pCodeBuf->getSize(); - } - - void flush() { - pCodeBuf->flush(); - } - - void error(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - mErrorSink->verror(fmt, ap); - va_end(ap); - } - - void assertImpl(bool test, int line) { - if (!test) { - error("code generator assertion failed at line %s:%d.", __FILE__, line); - LOGD("code generator assertion failed at line %s:%d.", __FILE__, line); - * (char*) 0 = 0; - } - } - - void setR0Type(Type* pType) { - assert(pType != NULL); - mExpressionStack.back().pType = pType; - mExpressionStack.back().et = ET_RVALUE; - } - - void setR0Type(Type* pType, ExpressionType et) { - assert(pType != NULL); - mExpressionStack.back().pType = pType; - mExpressionStack.back().et = et; - } - - Type* getTOSType() { - return mExpressionStack[mExpressionStack.size()-2].pType; - } - - void pushType() { - if (mExpressionStack.size()) { - mExpressionStack.push_back(mExpressionStack.back()); - } else { - mExpressionStack.push_back(ExpressionValue()); - } - - } - - void overType() { - size_t size = mExpressionStack.size(); - if (size >= 2) { - mExpressionStack.push_back(mExpressionStack.back()); - mExpressionStack[size-1] = mExpressionStack[size-2]; - mExpressionStack[size-2] = mExpressionStack[size]; - } - } - - void popType() { - mExpressionStack.pop_back(); - } - - bool bitsSame(Type* pA, Type* pB) { - return collapseType(pA->tag) == collapseType(pB->tag); - } - - TypeTag collapseType(TypeTag tag) { - static const TypeTag collapsedTag[] = { - TY_INT, - TY_INT, - TY_INT, - TY_VOID, - TY_FLOAT, - TY_DOUBLE, - TY_INT, - TY_INT, - TY_VOID, - TY_VOID, - TY_VOID - }; - return collapsedTag[tag]; - } - - TypeTag collapseTypeR0() { - return collapseType(getR0Type()->tag); - } - - static bool isFloatType(Type* pType) { - return isFloatTag(pType->tag); - } - - static bool isFloatTag(TypeTag tag) { - return tag == TY_FLOAT || tag == TY_DOUBLE; - } - - static bool isPointerType(Type* pType) { - return isPointerTag(pType->tag); - } - - static bool isPointerTag(TypeTag tag) { - return tag == TY_POINTER || tag == TY_ARRAY; - } - - Type* getPointerArithmeticResultType(Type* a, Type* b) { - TypeTag aTag = a->tag; - TypeTag bTag = b->tag; - if (aTag == TY_POINTER) { - return a; - } - if (bTag == TY_POINTER) { - return b; - } - if (aTag == TY_ARRAY) { - return a->pTail; - } - if (bTag == TY_ARRAY) { - return b->pTail; - } - return NULL; - } - Type* mkpInt; - - private: - Vector<ExpressionValue> mExpressionStack; - ICodeBuf* pCodeBuf; - ErrorSink* mErrorSink; - }; - -#ifdef PROVIDE_ARM_CODEGEN - - static size_t rotateRight(size_t n, size_t rotate) { - return (n >> rotate) | (n << (32 - rotate)); - } - - static size_t rotateLeft(size_t n, size_t rotate) { - return (n << rotate) | (n >> (32 - rotate)); - } - - static bool encode12BitImmediate(size_t immediate, size_t* pResult) { - for(size_t i = 0; i < 16; i++) { - size_t rotate = i * 2; - size_t mask = rotateRight(0xff, rotate); - if ((immediate | mask) == mask) { - size_t bits8 = rotateLeft(immediate, rotate); - // assert(bits8 <= 0xff); - *pResult = (i << 8) | bits8; - return true; - } - } - return false; - } - - static size_t decode12BitImmediate(size_t immediate) { - size_t data = immediate & 0xff; - size_t rotate = 2 * ((immediate >> 8) & 0xf); - return rotateRight(data, rotate); - } - - static bool isPowerOfTwo(size_t n) { - return (n != 0) & ((n & (n-1)) == 0); - } - - static size_t log2(size_t n) { - int result = 0; - while (n >>= 1) { - result++; - } - return result; - } - - class ARMCodeBuf : public ICodeBuf { - ICodeBuf* mpBase; - ErrorSink* mErrorSink; - - class CircularQueue { - static const int SIZE = 16; // Must be power of 2 - static const int MASK = SIZE-1; - unsigned int mBuf[SIZE]; - int mHead; - int mCount; - - public: - CircularQueue() { - mHead = 0; - mCount = 0; - } - - void pushBack(unsigned int data) { - mBuf[(mHead + mCount) & MASK] = data; - mCount += 1; - } - - unsigned int popFront() { - unsigned int result = mBuf[mHead]; - mHead = (mHead + 1) & MASK; - mCount -= 1; - return result; - } - - void popBack(int n) { - mCount -= n; - } - - inline int count() { - return mCount; - } - - bool empty() { - return mCount == 0; - } - - bool full() { - return mCount == SIZE; - } - - // The valid indexes are 1 - count() to 0 - unsigned int operator[](int i) { - return mBuf[(mHead + mCount + i) & MASK]; - } - }; - - CircularQueue mQ; - - void error(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - mErrorSink->verror(fmt, ap); - va_end(ap); - } - - void flush() { - while (!mQ.empty()) { - mpBase->o4(mQ.popFront()); - } - mpBase->flush(); - } - - public: - ARMCodeBuf(ICodeBuf* pBase) { - mpBase = pBase; - } - - virtual ~ARMCodeBuf() { - delete mpBase; - } - - void init(int size) { - mpBase->init(size); - } - - void setErrorSink(ErrorSink* pErrorSink) { - mErrorSink = pErrorSink; - mpBase->setErrorSink(pErrorSink); - } - - void o4(int n) { - if (mQ.full()) { - mpBase->o4(mQ.popFront()); - } - mQ.pushBack(n); - -#ifndef DISABLE_ARM_PEEPHOLE - // Peephole check - bool didPeep; - do { - static const unsigned int opMask = 0x01e00000; - static const unsigned int immediateMask = 0x00000fff; - static const unsigned int BMask = 0x00400000; - didPeep = false; - if (mQ.count() >= 4) { - - // Operand by a small constant - // push;mov #imm;pop;op ==> op #imm - - if (mQ[-4] == 0xe92d0001 && // stmfd r13!, {r0} - (mQ[-3] & ~immediateMask) == 0xe3a00000 && // mov r0, #X - mQ[-2] == 0xe8bd0002 && // ldmea r13!, {r1} - (mQ[-1] & ~opMask) == (0xe0810000 & ~opMask)) { // OP r0, r1, r0 - unsigned int movConst = mQ[-3]; - unsigned int op = mQ[-1]; - unsigned int combined = 0xe2000000 | (op & opMask) | (movConst & immediateMask); - // fprintf(stderr, "op %x movConst %x combined %x\n", op, movConst, combined); - if (! (combined == 0xe2800000 || combined == 0xe2400000)) { // add/sub #0 - mQ.popBack(4); - mQ.pushBack(combined); - didPeep = true; - } else { - mQ.popBack(4); - didPeep = true; - } - } - } - - // Load local variable - // sub r0,r11,#imm;ldr/ldrb r0,[r0] ==> ldr/ldrb r0, [r11,#-imm] - if (mQ.count() >= 2) { - if ((mQ[-2] & ~immediateMask) == 0xe24b0000) { // sub r0,r11,#imm - const unsigned int encodedImmediate = mQ[-2] & immediateMask; - const unsigned int ld = mQ[-1]; - if ((ld & ~BMask) == 0xe5900000) { // ldr{b} r0, [r0] - unsigned int combined = encodedImmediate | (0xE51B0000 | (ld & BMask)); // ldr r0, [r11, #-0] - mQ.popBack(2); - mQ.pushBack(combined); - didPeep = true; - } else if (ld == 0xedd07a00) { // ldcl p10, c7, [r0, #0x000] - unsigned int decodedImmediate = decode12BitImmediate(encodedImmediate); - if (decodedImmediate <= 1020 && ((decodedImmediate & 3) == 0)) { - unsigned int combined = (decodedImmediate >> 2) | 0xed5b7a00; // ldcl p10, c7, [r11, #-0] - mQ.popBack(2); - mQ.pushBack(combined); - didPeep = true; - } - } - } - } - - // Constant array lookup - - if (mQ.count() >= 6 && - mQ[-6] == 0xe92d0001 && // stmfd r13!, {r0} - (mQ[-5] & ~immediateMask)== 0xe3a00000 && // mov r0, #0x00000001 - mQ[-4] == 0xe8bd0002 && // ldmea r13!, {r1} - (mQ[-3] & ~immediateMask)== 0xe3a02000 && // mov r2, #0x00000004 - mQ[-2] == 0xe0000092 && // mul r0, r2, r0 - mQ[-1] == 0xe0810000) { // add r0, r1, r0 - unsigned int mov1 = mQ[-5]; - unsigned int mov2 = mQ[-3]; - unsigned int const1 = decode12BitImmediate(mov1); - unsigned int const2 = decode12BitImmediate(mov2); - unsigned int comboConst = const1 * const2; - size_t immediate = 0; - if (encode12BitImmediate(comboConst, &immediate)) { - mQ.popBack(6); - unsigned int add = immediate | 0xE2800000; // add r0, r0, #n - if (comboConst) { - mQ.pushBack(add); - } - didPeep = true; - } - } - - // Pointer arithmetic with a stride that is a power of two - - if (mQ.count() >= 3 && - (mQ[-3] & ~ immediateMask) == 0xe3a02000 && // mov r2, #stride - mQ[-2] == 0xe0000092 && // mul r0, r2, r0 - mQ[-1] == 0xe0810000) { // add r0, r1, r0 - int stride = decode12BitImmediate(mQ[-3]); - if (isPowerOfTwo(stride)) { - mQ.popBack(3); - unsigned int add = 0xe0810000 | (log2(stride) << 7); // add r0, r1, r0, LSL #log2(stride) - mQ.pushBack(add); - didPeep = true; - } - } - - } while (didPeep); -#endif - } - - void ob(int n) { - error("ob() not supported."); - } - - void* getBase() { - flush(); - return mpBase->getBase(); - } - - intptr_t getSize() { - flush(); - return mpBase->getSize(); - } - - intptr_t getPC() { - flush(); - return mpBase->getPC(); - } - }; - - class ARMCodeGenerator : public CodeGenerator { - public: - ARMCodeGenerator() { -#ifdef ARM_USE_VFP - // LOGD("Using ARM VFP hardware floating point."); -#else - // LOGD("Using ARM soft floating point."); -#endif - } - - virtual ~ARMCodeGenerator() {} - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - mStackUse = 0; - // sp -> arg4 arg5 ... - // Push our register-based arguments back on the stack - int regArgCount = calcRegArgCount(pDecl); - if (regArgCount > 0) { - mStackUse += regArgCount * 4; - o4(0xE92D0000 | ((1 << regArgCount) - 1)); // stmfd sp!, {} - } - // sp -> arg0 arg1 ... - o4(0xE92D4800); // stmfd sp!, {fp, lr} - mStackUse += 2 * 4; - // sp, fp -> oldfp, retadr, arg0 arg1 .... - o4(0xE1A0B00D); // mov fp, sp - LOG_STACK("functionEntry: %d\n", mStackUse); - int pc = getPC(); - o4(0xE24DD000); // sub sp, sp, # <local variables> - // We don't know how many local variables we are going to use, - // but we will round the allocation up to a multiple of - // STACK_ALIGNMENT, so it won't affect the stack alignment. - return pc; - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - // Round local variable size up to a multiple of stack alignment - localVariableSize = ((localVariableSize + STACK_ALIGNMENT - 1) / - STACK_ALIGNMENT) * STACK_ALIGNMENT; - // Patch local variable allocation code: - if (localVariableSize < 0 || localVariableSize > 255) { - error("localVariables out of range: %d", localVariableSize); - } - *(char*) (localVariableAddress) = localVariableSize; - -#ifdef ARM_USE_VFP - { - Type* pReturnType = pDecl->pHead; - switch(pReturnType->tag) { - case TY_FLOAT: - o4(0xEE170A90); // fmrs r0, s15 - break; - case TY_DOUBLE: - o4(0xEC510B17); // fmrrd r0, r1, d7 - break; - default: - break; - } - } -#endif - - // sp -> locals .... fp -> oldfp, retadr, arg0, arg1, ... - o4(0xE1A0E00B); // mov lr, fp - o4(0xE59BB000); // ldr fp, [fp] - o4(0xE28ED004); // add sp, lr, #4 - // sp -> retadr, arg0, ... - o4(0xE8BD4000); // ldmfd sp!, {lr} - // sp -> arg0 .... - - // We store the PC into the lr so we can adjust the sp before - // returning. We need to pull off the registers we pushed - // earlier. We don't need to actually store them anywhere, - // just adjust the stack. - int regArgCount = calcRegArgCount(pDecl); - if (regArgCount) { - o4(0xE28DD000 | (regArgCount << 2)); // add sp, sp, #argCount << 2 - } - o4(0xE12FFF1E); // bx lr - } - - /* load immediate value */ - virtual void li(int t) { - liReg(t, 0); - setR0Type(mkpInt); - } - - virtual void loadFloat(int address, Type* pType) { - setR0Type(pType); - // Global, absolute address - o4(0xE59F0000); // ldr r0, .L1 - o4(0xEA000000); // b .L99 - o4(address); // .L1: .word ea - // .L99: - - switch (pType->tag) { - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDD07A00); // flds s15, [r0] -#else - o4(0xE5900000); // ldr r0, [r0] -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED907B00); // fldd d7, [r0] -#else - o4(0xE1C000D0); // ldrd r0, [r0] -#endif - break; - default: - assert(false); - break; - } - } - - - virtual void addStructOffsetR0(int offset, Type* pType) { - if (offset) { - size_t immediate = 0; - if (encode12BitImmediate(offset, &immediate)) { - o4(0xE2800000 | immediate); // add r0, r0, #offset - } else { - error("structure offset out of range: %d", offset); - } - } - setR0Type(pType, ET_LVALUE); - } - - virtual int gjmp(int t) { - int pc = getPC(); - o4(0xEA000000 | encodeAddress(t)); // b .L33 - return pc; - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - Type* pR0Type = getR0Type(); - TypeTag tagR0 = pR0Type->tag; - switch(tagR0) { - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEEF57A40); // fcmpzs s15 - o4(0xEEF1FA10); // fmstat -#else - callRuntime((void*) runtime_is_non_zero_f); - o4(0xE3500000); // cmp r0,#0 -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xEEB57B40); // fcmpzd d7 - o4(0xEEF1FA10); // fmstat -#else - callRuntime((void*) runtime_is_non_zero_d); - o4(0xE3500000); // cmp r0,#0 -#endif - break; - default: - o4(0xE3500000); // cmp r0,#0 - break; - } - int branch = l ? 0x1A000000 : 0x0A000000; // bne : beq - int pc = getPC(); - o4(branch | encodeAddress(t)); - return pc; - } - - virtual void gcmp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 == TY_INT && tagTOS == TY_INT) { - setupIntPtrArgs(); - o4(0xE1510000); // cmp r1, r1 - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } - } else if (tagR0 == TY_DOUBLE || tagTOS == TY_DOUBLE) { - setupDoubleArgs(); -#ifdef ARM_USE_VFP - o4(0xEEB46BC7); // fcmped d6, d7 - o4(0xEEF1FA10); // fmstat - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } -#else - switch(op) { - case OP_EQUALS: - callRuntime((void*) runtime_cmp_eq_dd); - break; - case OP_NOT_EQUALS: - callRuntime((void*) runtime_cmp_ne_dd); - break; - case OP_LESS_EQUAL: - callRuntime((void*) runtime_cmp_le_dd); - break; - case OP_GREATER: - callRuntime((void*) runtime_cmp_gt_dd); - break; - case OP_GREATER_EQUAL: - callRuntime((void*) runtime_cmp_ge_dd); - break; - case OP_LESS: - callRuntime((void*) runtime_cmp_lt_dd); - break; - default: - error("Unknown comparison op %d", op); - break; - } -#endif - } else { - setupFloatArgs(); -#ifdef ARM_USE_VFP - o4(0xEEB47AE7); // fcmpes s14, s15 - o4(0xEEF1FA10); // fmstat - switch(op) { - case OP_EQUALS: - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case OP_NOT_EQUALS: - o4(0x03A00000); // moveq r0,#0 - o4(0x13A00001); // movne r0,#1 - break; - case OP_LESS_EQUAL: - o4(0xD3A00001); // movle r0,#1 - o4(0xC3A00000); // movgt r0,#0 - break; - case OP_GREATER: - o4(0xD3A00000); // movle r0,#0 - o4(0xC3A00001); // movgt r0,#1 - break; - case OP_GREATER_EQUAL: - o4(0xA3A00001); // movge r0,#1 - o4(0xB3A00000); // movlt r0,#0 - break; - case OP_LESS: - o4(0xA3A00000); // movge r0,#0 - o4(0xB3A00001); // movlt r0,#1 - break; - default: - error("Unknown comparison op %d", op); - break; - } -#else - switch(op) { - case OP_EQUALS: - callRuntime((void*) runtime_cmp_eq_ff); - break; - case OP_NOT_EQUALS: - callRuntime((void*) runtime_cmp_ne_ff); - break; - case OP_LESS_EQUAL: - callRuntime((void*) runtime_cmp_le_ff); - break; - case OP_GREATER: - callRuntime((void*) runtime_cmp_gt_ff); - break; - case OP_GREATER_EQUAL: - callRuntime((void*) runtime_cmp_ge_ff); - break; - case OP_LESS: - callRuntime((void*) runtime_cmp_lt_ff); - break; - default: - error("Unknown comparison op %d", op); - break; - } -#endif - } - setR0Type(mkpInt); - } - - virtual void genOp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - setupIntPtrArgs(); - bool isPtrR0 = isPointerTag(tagR0); - bool isPtrTOS = isPointerTag(tagTOS); - if (isPtrR0 || isPtrTOS) { - if (isPtrR0 && isPtrTOS) { - if (op != OP_MINUS) { - error("Unsupported pointer-pointer operation %d.", op); - } - if (! typeEqual(pR0Type, pTOSType)) { - error("Incompatible pointer types for subtraction."); - } - o4(0xE0410000); // sub r0,r1,r0 - setR0Type(mkpInt); - int size = sizeOf(pR0Type->pHead); - if (size != 1) { - pushR0(); - li(size); - // TODO: Optimize for power-of-two. - genOp(OP_DIV); - } - } else { - if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { - error("Unsupported pointer-scalar operation %d", op); - } - Type* pPtrType = getPointerArithmeticResultType( - pR0Type, pTOSType); - int size = sizeOf(pPtrType->pHead); - if (size != 1) { - // TODO: Optimize for power-of-two. - liReg(size, 2); - if (isPtrR0) { - o4(0x0E0010192); // mul r1,r2,r1 - } else { - o4(0x0E0000092); // mul r0,r2,r0 - } - } - switch(op) { - case OP_PLUS: - o4(0xE0810000); // add r0,r1,r0 - break; - case OP_MINUS: - o4(0xE0410000); // sub r0,r1,r0 - break; - } - setR0Type(pPtrType); - } - } else { - switch(op) { - case OP_MUL: - o4(0x0E0000091); // mul r0,r1,r0 - break; - case OP_DIV: - callRuntime((void*) runtime_DIV); - break; - case OP_MOD: - callRuntime((void*) runtime_MOD); - break; - case OP_PLUS: - o4(0xE0810000); // add r0,r1,r0 - break; - case OP_MINUS: - o4(0xE0410000); // sub r0,r1,r0 - break; - case OP_SHIFT_LEFT: - o4(0xE1A00011); // lsl r0,r1,r0 - break; - case OP_SHIFT_RIGHT: - o4(0xE1A00051); // asr r0,r1,r0 - break; - case OP_BIT_AND: - o4(0xE0010000); // and r0,r1,r0 - break; - case OP_BIT_XOR: - o4(0xE0210000); // eor r0,r1,r0 - break; - case OP_BIT_OR: - o4(0xE1810000); // orr r0,r1,r0 - break; - case OP_BIT_NOT: - o4(0xE1E00000); // mvn r0, r0 - break; - default: - error("Unimplemented op %d\n", op); - break; - } - } - } else { - Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; - if (pResultType->tag == TY_DOUBLE) { - setupDoubleArgs(); - - switch(op) { - case OP_MUL: -#ifdef ARM_USE_VFP - o4(0xEE267B07); // fmuld d7, d6, d7 -#else - callRuntime((void*) runtime_op_mul_dd); -#endif - break; - case OP_DIV: -#ifdef ARM_USE_VFP - o4(0xEE867B07); // fdivd d7, d6, d7 -#else - callRuntime((void*) runtime_op_div_dd); -#endif - break; - case OP_PLUS: -#ifdef ARM_USE_VFP - o4(0xEE367B07); // faddd d7, d6, d7 -#else - callRuntime((void*) runtime_op_add_dd); -#endif - break; - case OP_MINUS: -#ifdef ARM_USE_VFP - o4(0xEE367B47); // fsubd d7, d6, d7 -#else - callRuntime((void*) runtime_op_sub_dd); -#endif - break; - default: - error("Unsupported binary floating operation %d\n", op); - break; - } - } else { - setupFloatArgs(); - switch(op) { - case OP_MUL: -#ifdef ARM_USE_VFP - o4(0xEE677A27); // fmuls s15, s14, s15 -#else - callRuntime((void*) runtime_op_mul_ff); -#endif - break; - case OP_DIV: -#ifdef ARM_USE_VFP - o4(0xEEC77A27); // fdivs s15, s14, s15 -#else - callRuntime((void*) runtime_op_div_ff); -#endif - break; - case OP_PLUS: -#ifdef ARM_USE_VFP - o4(0xEE777A27); // fadds s15, s14, s15 -#else - callRuntime((void*) runtime_op_add_ff); -#endif - break; - case OP_MINUS: -#ifdef ARM_USE_VFP - o4(0xEE777A67); // fsubs s15, s14, s15 -#else - callRuntime((void*) runtime_op_sub_ff); -#endif - break; - default: - error("Unsupported binary floating operation %d\n", op); - break; - } - } - setR0Type(pResultType); - } - } - - virtual void gUnaryCmp(int op) { - if (op != OP_LOGICAL_NOT) { - error("Unknown unary cmp %d", op); - } else { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - o4(0xE3A01000); // mov r1, #0 - o4(0xE1510000); // cmp r1, r0 - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEEF57A40); // fcmpzs s15 - o4(0xEEF1FA10); // fmstat - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 -#else - callRuntime((void*) runtime_is_zero_f); -#endif - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xEEB57B40); // fcmpzd d7 - o4(0xEEF1FA10); // fmstat - o4(0x03A00001); // moveq r0,#1 - o4(0x13A00000); // movne r0,#0 -#else - callRuntime((void*) runtime_is_zero_d); -#endif - break; - default: - error("gUnaryCmp unsupported type"); - break; - } - } - setR0Type(mkpInt); - } - - virtual void genUnaryOp(int op) { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - switch(op) { - case OP_MINUS: - o4(0xE3A01000); // mov r1, #0 - o4(0xE0410000); // sub r0,r1,r0 - break; - case OP_BIT_NOT: - o4(0xE1E00000); // mvn r0, r0 - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - case TY_FLOAT: - case TY_DOUBLE: - switch (op) { - case OP_MINUS: - if (tag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEEF17A67); // fnegs s15, s15 -#else - callRuntime((void*) runtime_op_neg_f); -#endif - } else { -#ifdef ARM_USE_VFP - o4(0xEEB17B47); // fnegd d7, d7 -#else - callRuntime((void*) runtime_op_neg_d); -#endif - } - break; - case OP_BIT_NOT: - error("Can't apply '~' operator to a float or double."); - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - default: - error("genUnaryOp unsupported type"); - break; - } - } - - virtual void pushR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - -#ifdef ARM_USE_VFP - switch (r0ct ) { - case TY_FLOAT: - o4(0xED6D7A01); // fstmfds sp!,{s15} - mStackUse += 4; - break; - case TY_DOUBLE: - o4(0xED2D7B02); // fstmfdd sp!,{d7} - mStackUse += 8; - break; - default: - o4(0xE92D0001); // stmfd sp!,{r0} - mStackUse += 4; - } -#else - - if (r0ct != TY_DOUBLE) { - o4(0xE92D0001); // stmfd sp!,{r0} - mStackUse += 4; - } else { - o4(0xE92D0003); // stmfd sp!,{r0,r1} - mStackUse += 8; - } -#endif - pushType(); - LOG_STACK("pushR0: %d\n", mStackUse); - } - - virtual void over() { - // We know it's only used for int-ptr ops (++/--) - - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); - - assert (r0ct == TY_INT && tosct == TY_INT); - - o4(0xE8BD0002); // ldmfd sp!,{r1} - o4(0xE92D0001); // stmfd sp!,{r0} - o4(0xE92D0002); // stmfd sp!,{r1} - overType(); - mStackUse += 4; - } - - virtual void popR0() { - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); -#ifdef ARM_USE_VFP - if (tosct == TY_FLOAT || tosct == TY_DOUBLE) { - error("Unsupported popR0 float/double"); - } -#endif - switch (tosct){ - case TY_INT: - case TY_FLOAT: - o4(0xE8BD0001); // ldmfd sp!,{r0} - mStackUse -= 4; - break; - case TY_DOUBLE: - o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 - mStackUse -= 8; - break; - default: - error("Can't pop this type."); - break; - } - popType(); - LOG_STACK("popR0: %d\n", mStackUse); - } - - virtual void storeR0ToTOS() { - Type* pPointerType = getTOSType(); - assert(pPointerType->tag == TY_POINTER); - Type* pDestType = pPointerType->pHead; - convertR0(pDestType); - o4(0xE8BD0004); // ldmfd sp!,{r2} - popType(); - mStackUse -= 4; - switch (pDestType->tag) { - case TY_POINTER: - case TY_INT: - o4(0xE5820000); // str r0, [r2] - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDC27A00); // fsts s15, [r2, #0] -#else - o4(0xE5820000); // str r0, [r2] -#endif - break; - case TY_SHORT: - o4(0xE1C200B0); // strh r0, [r2] - break; - case TY_CHAR: - o4(0xE5C20000); // strb r0, [r2] - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED827B00); // fstd d7, [r2, #0] -#else - o4(0xE1C200F0); // strd r0, [r2] -#endif - break; - case TY_STRUCT: - { - int size = sizeOf(pDestType); - if (size > 0) { - liReg(size, 1); - callRuntime((void*) runtime_structCopy); - } - } - break; - default: - error("storeR0ToTOS: unimplemented type %d", - pDestType->tag); - break; - } - setR0Type(pDestType); - } - - virtual void loadR0FromR0() { - Type* pPointerType = getR0Type(); - assert(pPointerType->tag == TY_POINTER); - Type* pNewType = pPointerType->pHead; - TypeTag tag = pNewType->tag; - switch (tag) { - case TY_POINTER: - case TY_INT: - o4(0xE5900000); // ldr r0, [r0] - break; - case TY_FLOAT: -#ifdef ARM_USE_VFP - o4(0xEDD07A00); // flds s15, [r0, #0] -#else - o4(0xE5900000); // ldr r0, [r0] -#endif - break; - case TY_SHORT: - o4(0xE1D000F0); // ldrsh r0, [r0] - break; - case TY_CHAR: - o4(0xE5D00000); // ldrb r0, [r0] - break; - case TY_DOUBLE: -#ifdef ARM_USE_VFP - o4(0xED907B00); // fldd d7, [r0, #0] -#else - o4(0xE1C000D0); // ldrd r0, [r0] -#endif - break; - case TY_ARRAY: - pNewType = pNewType->pTail; - break; - case TY_STRUCT: - break; - default: - error("loadR0FromR0: unimplemented type %d", tag); - break; - } - setR0Type(pNewType); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - if (ea > -LOCAL && ea < LOCAL) { - // Local, fp relative - - size_t immediate = 0; - bool inRange = false; - if (ea < 0) { - inRange = encode12BitImmediate(-ea, &immediate); - o4(0xE24B0000 | immediate); // sub r0, fp, #ea - } else { - inRange = encode12BitImmediate(ea, &immediate); - o4(0xE28B0000 | immediate); // add r0, fp, #ea - } - if (! inRange) { - error("Offset out of range: %08x", ea); - } - } else { - // Global, absolute. - o4(0xE59F0000); // ldr r0, .L1 - o4(0xEA000000); // b .L99 - o4(ea); // .L1: .word 0 - // .L99: - } - setR0Type(pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - setR0Type(pPointerType); - int result = ea; - int pc = getPC(); - int offset = 0; - if (ea) { - offset = (pc - ea - 8) >> 2; - if ((offset & 0xffff) != offset) { - error("function forward reference out of bounds"); - } - } else { - offset = 0; - } - o4(0xE59F0000 | offset); // ldr r0, .L1 - - if (ea == 0) { - o4(0xEA000000); // b .L99 - result = getPC(); - o4(ea); // .L1: .word 0 - // .L99: - } - return result; - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - Type* pR0Type = getR0Type(); - if (isPointerType(pType) && isPointerType(pR0Type)) { - Type* pA = pR0Type; - Type* pB = pType; - // Array decays to pointer - if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { - pA = pA->pTail; - } - if (! (typeEqual(pA, pB) - || pB->pHead->tag == TY_VOID - || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) - )) { - error("Incompatible pointer or array types"); - } - } else if (bitsSame(pType, pR0Type)) { - // do nothing special - } else { - TypeTag r0Tag = collapseType(pR0Type->tag); - TypeTag destTag = collapseType(pType->tag); - if (r0Tag == TY_INT) { - if (destTag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEF87AE7); // fsitos s15, s15 - -#else - callRuntime((void*) runtime_int_to_float); -#endif - } else { - assert(destTag == TY_DOUBLE); -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEB87BE7); // fsitod d7, s15 - -#else - callRuntime((void*) runtime_int_to_double); -#endif - } - } else if (r0Tag == TY_FLOAT) { - if (destTag == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEEFD7AE7); // ftosizs s15, s15 - o4(0xEE170A90); // fmrs r0, s15 -#else - callRuntime((void*) runtime_float_to_int); -#endif - } else { - assert(destTag == TY_DOUBLE); -#ifdef ARM_USE_VFP - o4(0xEEB77AE7); // fcvtds d7, s15 -#else - callRuntime((void*) runtime_float_to_double); -#endif - } - } else { - if (r0Tag == TY_DOUBLE) { - if (destTag == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEEFD7BC7); // ftosizd s15, d7 - o4(0xEE170A90); // fmrs r0, s15 -#else - callRuntime((void*) runtime_double_to_int); -#endif - } else { - if(destTag == TY_FLOAT) { -#ifdef ARM_USE_VFP - o4(0xEEF77BC7); // fcvtsd s15, d7 -#else - callRuntime((void*) runtime_double_to_float); -#endif - } else { - incompatibleTypes(pR0Type, pType); - } - } - } else { - incompatibleTypes(pR0Type, pType); - } - } - } - setR0Type(pType); - } - - virtual int beginFunctionCallArguments() { - int pc = getPC(); - o4(0xE24DDF00); // Placeholder sub sp, sp, #0 - return pc; - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - convertR0(pArgType); - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); -#ifdef ARM_USE_VFP - switch(r0ct) { - case TY_INT: - if (l < 0 || l > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 | l); // str r0, [sp, #l] - return 4; - case TY_FLOAT: - if (l < 0 || l > 1020 || (l & 3)) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xEDCD7A00 | (l >> 2)); // fsts s15, [sp, #l] - return 4; - case TY_DOUBLE: { - // Align to 8 byte boundary - int l2 = (l + 7) & ~7; - if (l2 < 0 || l2 > 1020 || (l2 & 3)) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xED8D7B00 | (l2 >> 2)); // fstd d7, [sp, #l2] - return (l2 - l) + 8; - } - default: - assert(false); - return 0; - } -#else - switch(r0ct) { - case TY_INT: - case TY_FLOAT: - if (l < 0 || l > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 + l); // str r0, [sp, #l] - return 4; - case TY_DOUBLE: { - // Align to 8 byte boundary - int l2 = (l + 7) & ~7; - if (l2 < 0 || l2 > 4096-8) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE58D0000 + l2); // str r0, [sp, #l] - o4(0xE58D1000 + l2 + 4); // str r1, [sp, #l+4] - return (l2 - l) + 8; - } - default: - assert(false); - return 0; - } -#endif - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - int argumentStackUse = l; - // Have to calculate register arg count from actual stack size, - // in order to properly handle ... functions. - int regArgCount = l >> 2; - if (regArgCount > 4) { - regArgCount = 4; - } - if (regArgCount > 0) { - argumentStackUse -= regArgCount * 4; - o4(0xE8BD0000 | ((1 << regArgCount) - 1)); // ldmfd sp!,{} - } - mStackUse += argumentStackUse; - - // Align stack. - int missalignment = mStackUse - ((mStackUse / STACK_ALIGNMENT) - * STACK_ALIGNMENT); - mStackAlignmentAdjustment = 0; - if (missalignment > 0) { - mStackAlignmentAdjustment = STACK_ALIGNMENT - missalignment; - } - l += mStackAlignmentAdjustment; - - if (l < 0 || l > 0x3FC) { - error("L out of range for stack adjustment: 0x%08x", l); - } - flush(); - * (int*) a = 0xE24DDF00 | (l >> 2); // sub sp, sp, #0 << 2 - mStackUse += mStackAlignmentAdjustment; - LOG_STACK("endFunctionCallArguments mStackUse: %d, mStackAlignmentAdjustment %d\n", - mStackUse, mStackAlignmentAdjustment); - } - - virtual int callForward(int symbol, Type* pFunc) { - setR0Type(pFunc->pHead); - // Forward calls are always short (local) - int pc = getPC(); - o4(0xEB000000 | encodeAddress(symbol)); - return pc; - } - - virtual void callIndirect(int l, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - popType(); // Get rid of indirect fn pointer type - int argCount = l >> 2; - int poppedArgs = argCount > 4 ? 4 : argCount; - int adjustedL = l - (poppedArgs << 2) + mStackAlignmentAdjustment; - if (adjustedL < 0 || adjustedL > 4096-4) { - error("l out of range for stack offset: 0x%08x", l); - } - o4(0xE59DC000 | (0xfff & adjustedL)); // ldr r12, [sp,#adjustedL] - o4(0xE12FFF3C); // blx r12 - Type* pReturnType = pFunc->pHead; - setR0Type(pReturnType); -#ifdef ARM_USE_VFP - switch(pReturnType->tag) { - case TY_FLOAT: - o4(0xEE070A90); // fmsr s15, r0 - break; - case TY_DOUBLE: - o4(0xEC410B17); // fmdrr d7, r0, r1 - break; - default: - break; - } -#endif - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - int argCount = l >> 2; - // Have to calculate register arg count from actual stack size, - // in order to properly handle ... functions. - int regArgCount = l >> 2; - if (regArgCount > 4) { - regArgCount = 4; - } - int stackArgs = argCount - regArgCount; - int stackUse = stackArgs + (isIndirect ? 1 : 0) - + (mStackAlignmentAdjustment >> 2); - if (stackUse) { - if (stackUse < 0 || stackUse > 255) { - error("L out of range for stack adjustment: 0x%08x", l); - } - o4(0xE28DDF00 | stackUse); // add sp, sp, #stackUse << 2 - mStackUse -= stackUse * 4; - LOG_STACK("adjustStackAfterCall: %d\n", mStackUse); - } - } - - virtual int jumpOffset() { - return 8; - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - int n; - int base = getBase(); - int pc = getPC(); - while (t) { - int data = * (int*) t; - int decodedOffset = ((BRANCH_REL_ADDRESS_MASK & data) << 2); - if (decodedOffset == 0) { - n = 0; - } else { - n = base + decodedOffset; /* next value */ - } - *(int *) t = (data & ~BRANCH_REL_ADDRESS_MASK) - | encodeRelAddress(pc - t - 8); - t = n; - } - } - - /* output a symbol and patch all calls to it */ - virtual void resolveForward(int t) { - if (t) { - int pc = getPC(); - *(int *) t = pc; - } - } - - 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 - } - - /** - * alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - switch(pType->tag) { - case TY_CHAR: - return 1; - case TY_SHORT: - return 2; - case TY_DOUBLE: - return 8; - case TY_ARRAY: - return alignmentOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->alignment & 0x7fffffff; - case TY_FUNC: - error("alignment of func not supported"); - return 1; - default: - return 4; - } - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - switch(pType->tag) { - case TY_INT: - return 4; - case TY_SHORT: - return 2; - case TY_CHAR: - return 1; - case TY_FLOAT: - return 4; - case TY_DOUBLE: - return 8; - case TY_POINTER: - return 4; - case TY_ARRAY: - return pType->length * sizeOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->length; - default: - error("Unsupported type %d", pType->tag); - return 0; - } - } - - private: - - static const int BRANCH_REL_ADDRESS_MASK = 0x00ffffff; - - /** Encode a relative address that might also be - * a label. - */ - int encodeAddress(int value) { - int base = getBase(); - if (value >= base && value <= getPC() ) { - // This is a label, encode it relative to the base. - value = value - base; - } - return encodeRelAddress(value); - } - - int encodeRelAddress(int value) { - return BRANCH_REL_ADDRESS_MASK & (value >> 2); - } - - int calcRegArgCount(Type* pDecl) { - int reg = 0; - Type* pArgs = pDecl->pTail; - while (pArgs && reg < 4) { - Type* pArg = pArgs->pHead; - if ( pArg->tag == TY_DOUBLE) { - int evenReg = (reg + 1) & ~1; - if (evenReg >= 4) { - break; - } - reg = evenReg + 2; - } else { - reg++; - } - pArgs = pArgs->pTail; - } - return reg; - } - - void setupIntPtrArgs() { - o4(0xE8BD0002); // ldmfd sp!,{r1} - mStackUse -= 4; - popType(); - } - - /* Pop TOS to R1 (use s14 if VFP) - * Make sure both R0 and TOS are floats. (Could be ints) - * We know that at least one of R0 and TOS is already a float - */ - void setupFloatArgs() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 != TY_FLOAT) { - assert(tagR0 == TY_INT); -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEF87AE7); // fsitos s15, s15 -#else - callRuntime((void*) runtime_int_to_float); -#endif - } - if (tagTOS != TY_FLOAT) { - assert(tagTOS == TY_INT); - assert(tagR0 == TY_FLOAT); -#ifdef ARM_USE_VFP - o4(0xECBD7A01); // fldmfds sp!, {s14} - o4(0xEEB87AC7); // fsitos s14, s14 -#else - o4(0xE92D0001); // stmfd sp!,{r0} // push R0 - o4(0xE59D0004); // ldr r0, [sp, #4] - callRuntime((void*) runtime_int_to_float); - o4(0xE1A01000); // mov r1, r0 - o4(0xE8BD0001); // ldmfd sp!,{r0} // pop R0 - o4(0xE28DD004); // add sp, sp, #4 // Pop sp -#endif - } else { - // Pop TOS -#ifdef ARM_USE_VFP - o4(0xECBD7A01); // fldmfds sp!, {s14} - -#else - o4(0xE8BD0002); // ldmfd sp!,{r1} -#endif - } - mStackUse -= 4; - popType(); - } - - /* Pop TOS into R2..R3 (use D6 if VFP) - * Make sure both R0 and TOS are doubles. Could be floats or ints. - * We know that at least one of R0 and TOS are already a double. - */ - - void setupDoubleArgs() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = collapseType(pR0Type->tag); - TypeTag tagTOS = collapseType(pTOSType->tag); - if (tagR0 != TY_DOUBLE) { - if (tagR0 == TY_INT) { -#ifdef ARM_USE_VFP - o4(0xEE070A90); // fmsr s15, r0 - o4(0xEEB87BE7); // fsitod d7, s15 - -#else - callRuntime((void*) runtime_int_to_double); -#endif - } else { - assert(tagR0 == TY_FLOAT); -#ifdef ARM_USE_VFP - o4(0xEEB77AE7); // fcvtds d7, s15 -#else - callRuntime((void*) runtime_float_to_double); -#endif - } - } - if (tagTOS != TY_DOUBLE) { -#ifdef ARM_USE_VFP - if (tagTOS == TY_INT) { - o4(0xECFD6A01); // fldmfds sp!,{s13} - o4(0xEEB86BE6); // fsitod d6, s13 - } else { - assert(tagTOS == TY_FLOAT); - o4(0xECFD6A01); // fldmfds sp!,{s13} - o4(0xEEB76AE6); // fcvtds d6, s13 - } -#else - o4(0xE92D0003); // stmfd sp!,{r0,r1} // push r0,r1 - o4(0xE59D0008); // ldr r0, [sp, #8] - if (tagTOS == TY_INT) { - callRuntime((void*) runtime_int_to_double); - } else { - assert(tagTOS == TY_FLOAT); - callRuntime((void*) runtime_float_to_double); - } - o4(0xE1A02000); // mov r2, r0 - o4(0xE1A03001); // mov r3, r1 - o4(0xE8BD0003); // ldmfd sp!,{r0, r1} // Restore R0 - o4(0xE28DD004); // add sp, sp, #4 // Pop sp -#endif - mStackUse -= 4; - } else { -#ifdef ARM_USE_VFP - o4(0xECBD6B02); // fldmfdd sp!, {d6} -#else - o4(0xE8BD000C); // ldmfd sp!,{r2,r3} -#endif - mStackUse -= 8; - } - popType(); - } - - void liReg(int t, int reg) { - assert(reg >= 0 && reg < 16); - int rN = (reg & 0xf) << 12; - size_t encodedImmediate; - if (encode12BitImmediate(t, &encodedImmediate)) { - o4(0xE3A00000 | encodedImmediate | rN); // mov rN, #0 - } else if (encode12BitImmediate(-(t+1), &encodedImmediate)) { - // mvn means move constant ^ ~0 - o4(0xE3E00000 | encodedImmediate | rN); // mvn rN, #0 - } else { - o4(0xE51F0000 | rN); // ldr rN, .L3 - o4(0xEA000000); // b .L99 - o4(t); // .L3: .word 0 - // .L99: - } - } - - void incompatibleTypes(Type* pR0Type, Type* pType) { - error("Incompatible types old: %d new: %d", pR0Type->tag, pType->tag); - } - - void callRuntime(void* fn) { - o4(0xE59FC000); // ldr r12, .L1 - o4(0xEA000000); // b .L99 - o4((int) fn); //.L1: .word fn - o4(0xE12FFF3C); //.L99: blx r12 - } - - // Integer math: - - static int runtime_DIV(int b, int a) { - return a / b; - } - - static int runtime_MOD(int b, int a) { - return a % b; - } - - static void runtime_structCopy(void* src, size_t size, void* dest) { - memcpy(dest, src, size); - } - -#ifndef ARM_USE_VFP - - // Comparison to zero - - static int runtime_is_non_zero_f(float a) { - return a != 0; - } - - static int runtime_is_non_zero_d(double a) { - return a != 0; - } - - // Comparison to zero - - static int runtime_is_zero_f(float a) { - return a == 0; - } - - static int runtime_is_zero_d(double a) { - return a == 0; - } - - // Type conversion - - static int runtime_float_to_int(float a) { - return (int) a; - } - - static double runtime_float_to_double(float a) { - return (double) a; - } - - static int runtime_double_to_int(double a) { - return (int) a; - } - - static float runtime_double_to_float(double a) { - return (float) a; - } - - static float runtime_int_to_float(int a) { - return (float) a; - } - - static double runtime_int_to_double(int a) { - return (double) a; - } - - // Comparisons float - - static int runtime_cmp_eq_ff(float b, float a) { - return a == b; - } - - static int runtime_cmp_ne_ff(float b, float a) { - return a != b; - } - - static int runtime_cmp_lt_ff(float b, float a) { - return a < b; - } - - static int runtime_cmp_le_ff(float b, float a) { - return a <= b; - } - - static int runtime_cmp_ge_ff(float b, float a) { - return a >= b; - } - - static int runtime_cmp_gt_ff(float b, float a) { - return a > b; - } - - // Comparisons double - - static int runtime_cmp_eq_dd(double b, double a) { - return a == b; - } - - static int runtime_cmp_ne_dd(double b, double a) { - return a != b; - } - - static int runtime_cmp_lt_dd(double b, double a) { - return a < b; - } - - static int runtime_cmp_le_dd(double b, double a) { - return a <= b; - } - - static int runtime_cmp_ge_dd(double b, double a) { - return a >= b; - } - - static int runtime_cmp_gt_dd(double b, double a) { - return a > b; - } - - // Math float - - static float runtime_op_add_ff(float b, float a) { - return a + b; - } - - static float runtime_op_sub_ff(float b, float a) { - return a - b; - } - - static float runtime_op_mul_ff(float b, float a) { - return a * b; - } - - static float runtime_op_div_ff(float b, float a) { - return a / b; - } - - static float runtime_op_neg_f(float a) { - return -a; - } - - // Math double - - static double runtime_op_add_dd(double b, double a) { - return a + b; - } - - static double runtime_op_sub_dd(double b, double a) { - return a - b; - } - - static double runtime_op_mul_dd(double b, double a) { - return a * b; - } - - static double runtime_op_div_dd(double b, double a) { - return a / b; - } - - static double runtime_op_neg_d(double a) { - return -a; - } - -#endif - - static const int STACK_ALIGNMENT = 8; - int mStackUse; - // This variable holds the amount we adjusted the stack in the most - // recent endFunctionCallArguments call. It's examined by the - // following adjustStackAfterCall call. - int mStackAlignmentAdjustment; - }; - -#endif // PROVIDE_ARM_CODEGEN - -#ifdef PROVIDE_X86_CODEGEN - - class X86CodeGenerator : public CodeGenerator { - public: - X86CodeGenerator() {} - virtual ~X86CodeGenerator() {} - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - o(0xe58955); /* push %ebp, mov %esp, %ebp */ - return oad(0xec81, 0); /* sub $xxx, %esp */ - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - o(0xc3c9); /* leave, ret */ - *(int *) localVariableAddress = localVariableSize; /* save local variables */ - } - - /* load immediate value */ - virtual void li(int i) { - oad(0xb8, i); /* mov $xx, %eax */ - setR0Type(mkpInt); - } - - virtual void loadFloat(int address, Type* pType) { - setR0Type(pType); - switch (pType->tag) { - case TY_FLOAT: - oad(0x05D9, address); // flds - break; - case TY_DOUBLE: - oad(0x05DD, address); // fldl - break; - default: - assert(false); - break; - } - } - - virtual void addStructOffsetR0(int offset, Type* pType) { - if (offset) { - oad(0x05, offset); // addl offset, %eax - } - setR0Type(pType, ET_LVALUE); - } - - virtual int gjmp(int t) { - return psym(0xe9, t); - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - Type* pR0Type = getR0Type(); - TypeTag tagR0 = pR0Type->tag; - bool isFloatR0 = isFloatTag(tagR0); - if (isFloatR0) { - o(0xeed9); // fldz - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - } else { - o(0xc085); // test %eax, %eax - } - // Use two output statements to generate one instruction. - o(0x0f); // je/jne xxx - return psym(0x84 + l, t); - } - - virtual void gcmp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - int t = decodeOp(op); - o(0x59); /* pop %ecx */ - o(0xc139); /* cmp %eax,%ecx */ - li(0); - o(0x0f); /* setxx %al */ - o(t + 0x90); - o(0xc0); - popType(); - } else { - setupFloatOperands(); - switch (op) { - case OP_EQUALS: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0940f); // sete %al - o(0xc29b0f); // setnp %dl - o(0xd021); // andl %edx, %eax - break; - case OP_NOT_EQUALS: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0950f); // setne %al - o(0xc29a0f); // setp %dl - o(0xd009); // orl %edx, %eax - break; - case OP_GREATER_EQUAL: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x05c4f6); // testb $5, %ah - o(0xc0940f); // sete %al - break; - case OP_LESS: - o(0xc9d9); // fxch %st(1) - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0970f); // seta %al - break; - case OP_LESS_EQUAL: - o(0xc9d9); // fxch %st(1) - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0930f); // setea %al - break; - case OP_GREATER: - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x45c4f6); // testb $69, %ah - o(0xc0940f); // sete %al - break; - default: - error("Unknown comparison op"); - } - o(0xc0b60f); // movzbl %al, %eax - } - setR0Type(mkpInt); - } - - virtual void genOp(int op) { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (!isFloatR0 && !isFloatTOS) { - bool isPtrR0 = isPointerTag(tagR0); - bool isPtrTOS = isPointerTag(tagTOS); - if (isPtrR0 || isPtrTOS) { - if (isPtrR0 && isPtrTOS) { - if (op != OP_MINUS) { - error("Unsupported pointer-pointer operation %d.", op); - } - if (! typeEqual(pR0Type, pTOSType)) { - error("Incompatible pointer types for subtraction."); - } - o(0x59); /* pop %ecx */ - o(decodeOp(op)); - popType(); - setR0Type(mkpInt); - int size = sizeOf(pR0Type->pHead); - if (size != 1) { - pushR0(); - li(size); - // TODO: Optimize for power-of-two. - genOp(OP_DIV); - } - } else { - if (! (op == OP_PLUS || (op == OP_MINUS && isPtrR0))) { - error("Unsupported pointer-scalar operation %d", op); - } - Type* pPtrType = getPointerArithmeticResultType( - pR0Type, pTOSType); - o(0x59); /* pop %ecx */ - int size = sizeOf(pPtrType->pHead); - if (size != 1) { - // TODO: Optimize for power-of-two. - if (isPtrR0) { - oad(0xC969, size); // imull $size, %ecx - } else { - oad(0xC069, size); // mul $size, %eax - } - } - o(decodeOp(op)); - popType(); - setR0Type(pPtrType); - } - } else { - o(0x59); /* pop %ecx */ - o(decodeOp(op)); - if (op == OP_MOD) - o(0x92); /* xchg %edx, %eax */ - popType(); - } - } else { - Type* pResultType = tagR0 > tagTOS ? pR0Type : pTOSType; - setupFloatOperands(); - // Both float. x87 R0 == left hand, x87 R1 == right hand - switch (op) { - case OP_MUL: - o(0xc9de); // fmulp - break; - case OP_DIV: - o(0xf1de); // fdivp - break; - case OP_PLUS: - o(0xc1de); // faddp - break; - case OP_MINUS: - o(0xe1de); // fsubp - break; - default: - error("Unsupported binary floating operation."); - break; - } - setR0Type(pResultType); - } - } - - virtual void gUnaryCmp(int op) { - if (op != OP_LOGICAL_NOT) { - error("Unknown unary cmp %d", op); - } else { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: { - oad(0xb9, 0); /* movl $0, %ecx */ - int t = decodeOp(op); - o(0xc139); /* cmp %eax,%ecx */ - li(0); - o(0x0f); /* setxx %al */ - o(t + 0x90); - o(0xc0); - } - break; - case TY_FLOAT: - case TY_DOUBLE: - o(0xeed9); // fldz - o(0xe9da); // fucompp - o(0xe0df); // fnstsw %ax - o(0x9e); // sahf - o(0xc0950f); // setne %al - o(0xc29a0f); // setp %dl - o(0xd009); // orl %edx, %eax - o(0xc0b60f); // movzbl %al, %eax - o(0x01f083); // xorl $1, %eax - break; - default: - error("gUnaryCmp unsupported type"); - break; - } - } - setR0Type(mkpInt); - } - - virtual void genUnaryOp(int op) { - Type* pR0Type = getR0Type(); - TypeTag tag = collapseType(pR0Type->tag); - switch(tag) { - case TY_INT: - oad(0xb9, 0); /* movl $0, %ecx */ - o(decodeOp(op)); - break; - case TY_FLOAT: - case TY_DOUBLE: - switch (op) { - case OP_MINUS: - o(0xe0d9); // fchs - break; - case OP_BIT_NOT: - error("Can't apply '~' operator to a float or double."); - break; - default: - error("Unknown unary op %d\n", op); - break; - } - break; - default: - error("genUnaryOp unsupported type"); - break; - } - } - - virtual void pushR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - o(0x50); /* push %eax */ - break; - case TY_FLOAT: - o(0x50); /* push %eax */ - o(0x241cd9); // fstps 0(%esp) - break; - case TY_DOUBLE: - o(0x50); /* push %eax */ - o(0x50); /* push %eax */ - o(0x241cdd); // fstpl 0(%esp) - break; - default: - error("pushR0 unsupported type %d", r0ct); - break; - } - pushType(); - } - - virtual void over() { - // We know it's only used for int-ptr ops (++/--) - - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - - Type* pTOSType = getTOSType(); - TypeTag tosct = collapseType(pTOSType->tag); - - assert (r0ct == TY_INT && tosct == TY_INT); - - o(0x59); /* pop %ecx */ - o(0x50); /* push %eax */ - o(0x51); /* push %ecx */ - - overType(); - } - - virtual void popR0() { - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - o(0x58); /* popl %eax */ - break; - case TY_FLOAT: - o(0x2404d9); // flds (%esp) - o(0x58); /* popl %eax */ - break; - case TY_DOUBLE: - o(0x2404dd); // fldl (%esp) - o(0x58); /* popl %eax */ - o(0x58); /* popl %eax */ - break; - default: - error("popR0 unsupported type %d", r0ct); - break; - } - popType(); - } - - virtual void storeR0ToTOS() { - Type* pPointerType = getTOSType(); - assert(pPointerType->tag == TY_POINTER); - Type* pTargetType = pPointerType->pHead; - convertR0(pTargetType); - o(0x59); /* pop %ecx */ - popType(); - switch (pTargetType->tag) { - case TY_POINTER: - case TY_INT: - o(0x0189); /* movl %eax/%al, (%ecx) */ - break; - case TY_SHORT: - o(0x018966); /* movw %ax, (%ecx) */ - break; - case TY_CHAR: - o(0x0188); /* movl %eax/%al, (%ecx) */ - break; - case TY_FLOAT: - o(0x19d9); /* fstps (%ecx) */ - break; - case TY_DOUBLE: - o(0x19dd); /* fstpl (%ecx) */ - break; - case TY_STRUCT: - { - // TODO: use alignment information to use movsw/movsl instead of movsb - int size = sizeOf(pTargetType); - if (size > 0) { - o(0x9c); // pushf - o(0x57); // pushl %edi - o(0x56); // pushl %esi - o(0xcf89); // movl %ecx, %edi - o(0xc689); // movl %eax, %esi - oad(0xb9, size); // mov #size, %ecx - o(0xfc); // cld - o(0xf3); // rep - o(0xa4); // movsb - o(0x5e); // popl %esi - o(0x5f); // popl %edi - o(0x9d); // popf - } - } - break; - default: - error("storeR0ToTOS: unsupported type %d", - pTargetType->tag); - break; - } - setR0Type(pTargetType); - } - - virtual void loadR0FromR0() { - Type* pPointerType = getR0Type(); - assert(pPointerType->tag == TY_POINTER); - Type* pNewType = pPointerType->pHead; - TypeTag tag = pNewType->tag; - switch (tag) { - case TY_POINTER: - case TY_INT: - o2(0x008b); /* mov (%eax), %eax */ - break; - case TY_SHORT: - o(0xbf0f); /* movswl (%eax), %eax */ - ob(0); - break; - case TY_CHAR: - o(0xbe0f); /* movsbl (%eax), %eax */ - ob(0); /* add zero in code */ - break; - case TY_FLOAT: - o2(0x00d9); // flds (%eax) - break; - case TY_DOUBLE: - o2(0x00dd); // fldl (%eax) - break; - case TY_ARRAY: - pNewType = pNewType->pTail; - break; - case TY_STRUCT: - break; - default: - error("loadR0FromR0: unsupported type %d", tag); - break; - } - setR0Type(pNewType); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - gmov(10, ea); /* leal EA, %eax */ - setR0Type(pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - oad(0xb8, ea); /* mov $xx, %eax */ - setR0Type(pPointerType); - return getPC() - 4; - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - Type* pR0Type = getR0Type(); - if (pR0Type == NULL) { - assert(false); - setR0Type(pType); - return; - } - if (isPointerType(pType) && isPointerType(pR0Type)) { - Type* pA = pR0Type; - Type* pB = pType; - // Array decays to pointer - if (pA->tag == TY_ARRAY && pB->tag == TY_POINTER) { - pA = pA->pTail; - } - if (! (typeEqual(pA, pB) - || pB->pHead->tag == TY_VOID - || (pA->tag == TY_POINTER && pB->tag == TY_POINTER && isCast) - )) { - error("Incompatible pointer or array types"); - } - } else if (bitsSame(pType, pR0Type)) { - // do nothing special - } else if (isFloatType(pType) && isFloatType(pR0Type)) { - // do nothing special, both held in same register on x87. - } else { - TypeTag r0Tag = collapseType(pR0Type->tag); - TypeTag destTag = collapseType(pType->tag); - if (r0Tag == TY_INT && isFloatTag(destTag)) { - // Convert R0 from int to float - o(0x50); // push %eax - o(0x2404DB); // fildl 0(%esp) - o(0x58); // pop %eax - } else if (isFloatTag(r0Tag) && destTag == TY_INT) { - // Convert R0 from float to int. Complicated because - // need to save and restore the rounding mode. - o(0x50); // push %eax - o(0x50); // push %eax - o(0x02247cD9); // fnstcw 2(%esp) - o(0x2444b70f); // movzwl 2(%esp), %eax - o(0x02); - o(0x0cb4); // movb $12, %ah - o(0x24048966); // movw %ax, 0(%esp) - o(0x242cd9); // fldcw 0(%esp) - o(0x04245cdb); // fistpl 4(%esp) - o(0x02246cd9); // fldcw 2(%esp) - o(0x58); // pop %eax - o(0x58); // pop %eax - } else { - error("Incompatible types old: %d new: %d", - pR0Type->tag, pType->tag); - } - } - setR0Type(pType); - } - - virtual int beginFunctionCallArguments() { - return oad(0xec81, 0); /* sub $xxx, %esp */ - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - convertR0(pArgType); - Type* pR0Type = getR0Type(); - TypeTag r0ct = collapseType(pR0Type->tag); - switch(r0ct) { - case TY_INT: - oad(0x248489, l); /* movl %eax, xxx(%esp) */ - return 4; - case TY_FLOAT: - oad(0x249CD9, l); /* fstps xxx(%esp) */ - return 4; - case TY_DOUBLE: - oad(0x249CDD, l); /* fstpl xxx(%esp) */ - return 8; - default: - assert(false); - return 0; - } - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - * (int*) a = l; - } - - virtual int callForward(int symbol, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - setR0Type(pFunc->pHead); - return psym(0xe8, symbol); /* call xxx */ - } - - virtual void callIndirect(int l, Type* pFunc) { - assert(pFunc->tag == TY_FUNC); - popType(); // Get rid of indirect fn pointer type - setR0Type(pFunc->pHead); - oad(0x2494ff, l); /* call *xxx(%esp) */ - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - assert(pDecl->tag == TY_FUNC); - if (isIndirect) { - l += 4; - } - if (l > 0) { - oad(0xc481, l); /* add $xxx, %esp */ - } - } - - virtual int jumpOffset() { - return 5; - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - int n; - int pc = getPC(); - while (t) { - n = *(int *) t; /* next value */ - *(int *) t = pc - t - 4; - t = n; - } - } - - /* output a symbol and patch all calls to it, using absolute address */ - virtual void resolveForward(int t) { - int n; - int pc = getPC(); - while (t) { - n = *(int *) t; /* next value */ - *(int *) t = pc; - t = n; - } - } - - virtual int finishCompile() { - size_t pagesize = 4096; - size_t base = (size_t) getBase() & ~ (pagesize - 1); - size_t top = ((size_t) getPC() + pagesize - 1) & ~ (pagesize - 1); - int err = mprotect((void*) base, top - base, PROT_READ | PROT_WRITE | PROT_EXEC); - if (err) { - error("mprotect() failed: %d", errno); - } - return err; - } - - /** - * Alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - switch (pType->tag) { - case TY_CHAR: - return 1; - case TY_SHORT: - return 2; - case TY_ARRAY: - return alignmentOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->alignment & 0x7fffffff; - case TY_FUNC: - error("alignment of func not supported"); - return 1; - default: - return 4; - } - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - switch(pType->tag) { - case TY_INT: - return 4; - case TY_SHORT: - return 2; - case TY_CHAR: - return 1; - case TY_FLOAT: - return 4; - case TY_DOUBLE: - return 8; - case TY_POINTER: - return 4; - case TY_ARRAY: - return pType->length * sizeOf(pType->pHead); - case TY_STRUCT: - return pType->pHead->length; - default: - error("Unsupported type %d", pType->tag); - return 0; - } - } - - private: - - /** Output 1 to 4 bytes. - * - */ - void o(int n) { - /* cannot use unsigned, so we must do a hack */ - while (n && n != -1) { - ob(n & 0xff); - n = n >> 8; - } - } - - /* Output exactly 2 bytes - */ - void o2(int n) { - ob(n & 0xff); - ob(0xff & (n >> 8)); - } - - /* 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 result = getPC(); - o4(t); - return result; - } - - static const int operatorHelper[]; - - int decodeOp(int op) { - if (op < 0 || op > OP_COUNT) { - error("Out-of-range operator: %d\n", op); - op = 0; - } - return operatorHelper[op]; - } - - void gmov(int l, int t) { - o(l + 0x83); - oad((t > -LOCAL && t < LOCAL) << 7 | 5, t); - } - - void setupFloatOperands() { - Type* pR0Type = getR0Type(); - Type* pTOSType = getTOSType(); - TypeTag tagR0 = pR0Type->tag; - TypeTag tagTOS = pTOSType->tag; - bool isFloatR0 = isFloatTag(tagR0); - bool isFloatTOS = isFloatTag(tagTOS); - if (! isFloatR0) { - // Convert R0 from int to float - o(0x50); // push %eax - o(0x2404DB); // fildl 0(%esp) - o(0x58); // pop %eax - } - if (! isFloatTOS){ - o(0x2404DB); // fildl 0(%esp); - o(0x58); // pop %eax - } else { - if (tagTOS == TY_FLOAT) { - o(0x2404d9); // flds (%esp) - o(0x58); // pop %eax - } else { - o(0x2404dd); // fldl (%esp) - o(0x58); // pop %eax - o(0x58); // pop %eax - } - } - popType(); - } - }; - -#endif // PROVIDE_X86_CODEGEN - -#ifdef PROVIDE_TRACE_CODEGEN - class TraceCodeGenerator : public CodeGenerator { - private: - CodeGenerator* mpBase; - - public: - TraceCodeGenerator(CodeGenerator* pBase) { - mpBase = pBase; - } - - virtual ~TraceCodeGenerator() { - delete mpBase; - } - - virtual void init(ICodeBuf* pCodeBuf) { - mpBase->init(pCodeBuf); - } - - void setErrorSink(ErrorSink* pErrorSink) { - mpBase->setErrorSink(pErrorSink); - } - - /* returns address to patch with local variable size - */ - virtual int functionEntry(Type* pDecl) { - int result = mpBase->functionEntry(pDecl); - fprintf(stderr, "functionEntry(pDecl) -> %d\n", result); - return result; - } - - virtual void functionExit(Type* pDecl, int localVariableAddress, int localVariableSize) { - fprintf(stderr, "functionExit(pDecl, %d, %d)\n", - localVariableAddress, localVariableSize); - mpBase->functionExit(pDecl, localVariableAddress, localVariableSize); - } - - /* load immediate value */ - virtual void li(int t) { - fprintf(stderr, "li(%d)\n", t); - mpBase->li(t); - } - - virtual void loadFloat(int address, Type* pType) { - fprintf(stderr, "loadFloat(%d, type=%d)\n", address, pType->tag); - mpBase->loadFloat(address, pType); - } - - virtual void addStructOffsetR0(int offset, Type* pType) { - fprintf(stderr, "addStructOffsetR0(%d, type=%d)\n", offset, pType->tag); - mpBase->addStructOffsetR0(offset, pType); - } - - virtual int gjmp(int t) { - int result = mpBase->gjmp(t); - fprintf(stderr, "gjmp(%d) = %d\n", t, result); - return result; - } - - /* l = 0: je, l == 1: jne */ - virtual int gtst(bool l, int t) { - int result = mpBase->gtst(l, t); - fprintf(stderr, "gtst(%d,%d) = %d\n", l, t, result); - return result; - } - - virtual void gcmp(int op) { - fprintf(stderr, "gcmp(%d)\n", op); - mpBase->gcmp(op); - } - - virtual void genOp(int op) { - fprintf(stderr, "genOp(%d)\n", op); - mpBase->genOp(op); - } - - - virtual void gUnaryCmp(int op) { - fprintf(stderr, "gUnaryCmp(%d)\n", op); - mpBase->gUnaryCmp(op); - } - - virtual void genUnaryOp(int op) { - fprintf(stderr, "genUnaryOp(%d)\n", op); - mpBase->genUnaryOp(op); - } - - virtual void pushR0() { - fprintf(stderr, "pushR0()\n"); - mpBase->pushR0(); - } - - virtual void over() { - fprintf(stderr, "over()\n"); - mpBase->over(); - } - - virtual void popR0() { - fprintf(stderr, "popR0()\n"); - mpBase->popR0(); - } - - virtual void storeR0ToTOS() { - fprintf(stderr, "storeR0ToTOS()\n"); - mpBase->storeR0ToTOS(); - } - - virtual void loadR0FromR0() { - fprintf(stderr, "loadR0FromR0()\n"); - mpBase->loadR0FromR0(); - } - - virtual void leaR0(int ea, Type* pPointerType, ExpressionType et) { - fprintf(stderr, "leaR0(%d, %d, %d)\n", ea, - pPointerType->pHead->tag, et); - mpBase->leaR0(ea, pPointerType, et); - } - - virtual int leaForward(int ea, Type* pPointerType) { - fprintf(stderr, "leaForward(%d)\n", ea); - return mpBase->leaForward(ea, pPointerType); - } - - virtual void convertR0Imp(Type* pType, bool isCast){ - fprintf(stderr, "convertR0(pType tag=%d, %d)\n", pType->tag, isCast); - mpBase->convertR0Imp(pType, isCast); - } - - virtual int beginFunctionCallArguments() { - int result = mpBase->beginFunctionCallArguments(); - fprintf(stderr, "beginFunctionCallArguments() = %d\n", result); - return result; - } - - virtual size_t storeR0ToArg(int l, Type* pArgType) { - fprintf(stderr, "storeR0ToArg(%d, pArgType=%d)\n", l, - pArgType->tag); - return mpBase->storeR0ToArg(l, pArgType); - } - - virtual void endFunctionCallArguments(Type* pDecl, int a, int l) { - fprintf(stderr, "endFunctionCallArguments(%d, %d)\n", a, l); - mpBase->endFunctionCallArguments(pDecl, a, l); - } - - virtual int callForward(int symbol, Type* pFunc) { - int result = mpBase->callForward(symbol, pFunc); - fprintf(stderr, "callForward(%d) = %d\n", symbol, result); - return result; - } - - virtual void callIndirect(int l, Type* pFunc) { - fprintf(stderr, "callIndirect(%d returntype = %d)\n", l, - pFunc->pHead->tag); - mpBase->callIndirect(l, pFunc); - } - - virtual void adjustStackAfterCall(Type* pDecl, int l, bool isIndirect) { - fprintf(stderr, "adjustStackAfterCall(pType, %d, %d)\n", l, isIndirect); - mpBase->adjustStackAfterCall(pDecl, l, isIndirect); - } - - virtual int jumpOffset() { - return mpBase->jumpOffset(); - } - - /* output a symbol and patch all calls to it */ - virtual void gsym(int t) { - fprintf(stderr, "gsym(%d)\n", t); - mpBase->gsym(t); - } - - virtual void resolveForward(int t) { - mpBase->resolveForward(t); - } - - virtual int finishCompile() { - int result = mpBase->finishCompile(); - fprintf(stderr, "finishCompile() = %d\n", result); - return result; - } - - /** - * Alignment (in bytes) for this type of data - */ - virtual size_t alignmentOf(Type* pType){ - return mpBase->alignmentOf(pType); - } - - /** - * Array element alignment (in bytes) for this type of data. - */ - virtual size_t sizeOf(Type* pType){ - return mpBase->sizeOf(pType); - } - - virtual Type* getR0Type() { - return mpBase->getR0Type(); - } - - virtual ExpressionType getR0ExpressionType() { - return mpBase->getR0ExpressionType(); - } - - virtual void setR0ExpressionType(ExpressionType et) { - mpBase->setR0ExpressionType(et); - } - - virtual size_t getExpressionStackDepth() { - return mpBase->getExpressionStackDepth(); - } - - virtual void forceR0RVal() { - return mpBase->forceR0RVal(); - } - }; - -#endif // PROVIDE_TRACE_CODEGEN - - class Arena { - public: - // Used to record a given allocation amount. - // Used: - // Mark mark = arena.mark(); - // ... lots of arena.allocate() - // arena.free(mark); - - struct Mark { - size_t chunk; - size_t offset; - }; - - Arena() { - mCurrentChunk = 0; - Chunk start(CHUNK_SIZE); - mData.push_back(start); - } - - ~Arena() { - for(size_t i = 0; i < mData.size(); i++) { - mData[i].free(); - } - } - - // Alloc using the standard alignment size safe for any variable - void* alloc(size_t size) { - return alloc(size, 8); - } - - Mark mark(){ - Mark result; - result.chunk = mCurrentChunk; - result.offset = mData[mCurrentChunk].mOffset; - return result; - } - - void freeToMark(const Mark& mark) { - mCurrentChunk = mark.chunk; - mData[mCurrentChunk].mOffset = mark.offset; - } - - private: - // Allocate memory aligned to a given size - // and a given power-of-two-sized alignment (e.g. 1,2,4,8,...) - // Memory is not zero filled. - - void* alloc(size_t size, size_t alignment) { - while (size > mData[mCurrentChunk].remainingCapacity(alignment)) { - if (mCurrentChunk + 1 < mData.size()) { - mCurrentChunk++; - } else { - size_t allocSize = CHUNK_SIZE; - if (allocSize < size + alignment - 1) { - allocSize = size + alignment - 1; - } - Chunk chunk(allocSize); - mData.push_back(chunk); - mCurrentChunk++; - } - } - return mData[mCurrentChunk].allocate(size, alignment); - } - - static const size_t CHUNK_SIZE = 128*1024; - // Note: this class does not deallocate its - // memory when it's destroyed. It depends upon - // its parent to deallocate the memory. - struct Chunk { - Chunk() { - mpData = 0; - mSize = 0; - mOffset = 0; - } - - Chunk(size_t size) { - mSize = size; - mpData = (char*) malloc(size); - mOffset = 0; - } - - ~Chunk() { - // Doesn't deallocate memory. - } - - void* allocate(size_t size, size_t alignment) { - size_t alignedOffset = aligned(mOffset, alignment); - void* result = mpData + alignedOffset; - mOffset = alignedOffset + size; - return result; - } - - void free() { - if (mpData) { - ::free(mpData); - mpData = 0; - } - } - - size_t remainingCapacity(size_t alignment) { - return aligned(mSize, alignment) - aligned(mOffset, alignment); - } - - // Assume alignment is a power of two - inline size_t aligned(size_t v, size_t alignment) { - size_t mask = alignment-1; - return (v + mask) & ~mask; - } - - char* mpData; - size_t mSize; - size_t mOffset; - }; - - size_t mCurrentChunk; - - Vector<Chunk> mData; - }; - - struct VariableInfo; - - struct Token { - int hash; - size_t length; - char* pText; - tokenid_t id; - - // Current values for the token - char* mpMacroDefinition; - VariableInfo* mpVariableInfo; - VariableInfo* mpStructInfo; - }; - - class TokenTable { - public: - // Don't use 0..0xff, allows characters and operators to be tokens too. - - static const int TOKEN_BASE = 0x100; - TokenTable() { - mpMap = hashmapCreate(128, hashFn, equalsFn); - } - - ~TokenTable() { - hashmapFree(mpMap); - } - - void setArena(Arena* pArena) { - mpArena = pArena; - } - - // Returns a token for a given string of characters. - tokenid_t intern(const char* pText, size_t length) { - Token probe; - int hash = hashmapHash((void*) pText, length); - { - Token probe; - probe.hash = hash; - probe.length = length; - probe.pText = (char*) pText; - Token* pValue = (Token*) hashmapGet(mpMap, &probe); - if (pValue) { - return pValue->id; - } - } - - Token* pToken = (Token*) mpArena->alloc(sizeof(Token)); - memset(pToken, 0, sizeof(*pToken)); - pToken->hash = hash; - pToken->length = length; - pToken->pText = (char*) mpArena->alloc(length + 1); - memcpy(pToken->pText, pText, length); - pToken->pText[length] = 0; - pToken->id = mTokens.size() + TOKEN_BASE; - mTokens.push_back(pToken); - hashmapPut(mpMap, pToken, pToken); - return pToken->id; - } - - // Return the Token for a given tokenid. - Token& operator[](tokenid_t id) { - return *mTokens[id - TOKEN_BASE]; - } - - inline size_t size() { - return mTokens.size(); - } - - private: - - static int hashFn(void* pKey) { - Token* pToken = (Token*) pKey; - return pToken->hash; - } - - static bool equalsFn(void* keyA, void* keyB) { - Token* pTokenA = (Token*) keyA; - Token* pTokenB = (Token*) keyB; - // Don't need to compare hash values, they should always be equal - return pTokenA->length == pTokenB->length - && strcmp(pTokenA->pText, pTokenB->pText) == 0; - } - - Hashmap* mpMap; - Vector<Token*> mTokens; - Arena* mpArena; - }; - - class InputStream { - public: - virtual ~InputStream() {} - virtual int getChar() = 0; - }; - - class TextInputStream : public InputStream { - public: - TextInputStream(const char* text, size_t textLength) - : pText(text), mTextLength(textLength), mPosition(0) { - } - - virtual int getChar() { - return mPosition < mTextLength ? pText[mPosition++] : EOF; - } - - private: - const char* pText; - size_t mTextLength; - size_t mPosition; - }; - - class String { - public: - String() { - mpBase = 0; - mUsed = 0; - mSize = 0; - } - - String(const char* item, int len, bool adopt) { - if (len < 0) { - len = strlen(item); - } - if (adopt) { - mpBase = (char*) item; - mUsed = len; - mSize = len + 1; - } else { - mpBase = 0; - mUsed = 0; - mSize = 0; - appendBytes(item, len); - } - } - - String(const String& other) { - mpBase = 0; - mUsed = 0; - mSize = 0; - appendBytes(other.getUnwrapped(), other.len()); - } - - ~String() { - if (mpBase) { - free(mpBase); - } - } - - String& operator=(const String& other) { - clear(); - appendBytes(other.getUnwrapped(), other.len()); - return *this; - } - - inline char* getUnwrapped() const { - return mpBase; - } - - void clear() { - mUsed = 0; - if (mSize > 0) { - mpBase[0] = 0; - } - } - - void appendCStr(const char* s) { - appendBytes(s, strlen(s)); - } - - void appendBytes(const char* s, int n) { - memcpy(ensure(n), s, n + 1); - } - - void append(char c) { - * ensure(1) = c; - } - - void append(String& other) { - appendBytes(other.getUnwrapped(), other.len()); - } - - char* orphan() { - char* result = mpBase; - mpBase = 0; - mUsed = 0; - mSize = 0; - return result; - } - - void printf(const char* fmt,...) { - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); - } - - void vprintf(const char* fmt, va_list ap) { - char* temp; - int numChars = vasprintf(&temp, fmt, ap); - memcpy(ensure(numChars), temp, numChars+1); - free(temp); - } - - inline size_t len() const { - return mUsed; - } - - private: - char* ensure(int n) { - size_t newUsed = mUsed + n; - if (newUsed > mSize) { - size_t newSize = mSize * 2 + 10; - if (newSize < newUsed) { - newSize = newUsed; - } - mpBase = (char*) realloc(mpBase, newSize + 1); - mSize = newSize; - } - mpBase[newUsed] = '\0'; - char* result = mpBase + mUsed; - mUsed = newUsed; - return result; - } - - char* mpBase; - size_t mUsed; - size_t mSize; - }; - - void internKeywords() { - // Note: order has to match TOK_ constants - static const char* keywords[] = { - "int", - "char", - "void", - "if", - "else", - "while", - "break", - "return", - "for", - "auto", - "case", - "const", - "continue", - "default", - "do", - "double", - "enum", - "extern", - "float", - "goto", - "long", - "register", - "short", - "signed", - "sizeof", - "static", - "struct", - "switch", - "typedef", - "union", - "unsigned", - "volatile", - "_Bool", - "_Complex", - "_Imaginary", - "inline", - "restrict", - - // predefined tokens that can also be symbols start here: - "pragma", - "define", - "line", - 0}; - - for(int i = 0; keywords[i]; i++) { - mTokenTable.intern(keywords[i], strlen(keywords[i])); - } - } - - struct InputState { - InputStream* pStream; - int oldCh; - }; - - struct VariableInfo { - void* pAddress; - void* pForward; // For a forward direction, linked list of data to fix up - tokenid_t tok; - size_t level; - VariableInfo* pOldDefinition; - Type* pType; - bool isStructTag; - }; - - class SymbolStack { - public: - SymbolStack() { - mpArena = 0; - mpTokenTable = 0; - } - - void setArena(Arena* pArena) { - mpArena = pArena; - } - - void setTokenTable(TokenTable* pTokenTable) { - mpTokenTable = pTokenTable; - } - - void pushLevel() { - Mark mark; - mark.mArenaMark = mpArena->mark(); - mark.mSymbolHead = mStack.size(); - mLevelStack.push_back(mark); - } - - void popLevel() { - // Undo any shadowing that was done: - Mark mark = mLevelStack.back(); - mLevelStack.pop_back(); - while (mStack.size() > mark.mSymbolHead) { - VariableInfo* pV = mStack.back(); - mStack.pop_back(); - if (pV->isStructTag) { - (*mpTokenTable)[pV->tok].mpStructInfo = pV->pOldDefinition; - } else { - (*mpTokenTable)[pV->tok].mpVariableInfo = pV->pOldDefinition; - } - } - mpArena->freeToMark(mark.mArenaMark); - } - - bool isDefinedAtCurrentLevel(tokenid_t tok) { - VariableInfo* pV = (*mpTokenTable)[tok].mpVariableInfo; - return pV && pV->level == level(); - } - - bool isStructTagDefinedAtCurrentLevel(tokenid_t tok) { - VariableInfo* pV = (*mpTokenTable)[tok].mpStructInfo; - return pV && pV->level == level(); - } - - VariableInfo* add(tokenid_t tok) { - Token& token = (*mpTokenTable)[tok]; - VariableInfo* pOldV = token.mpVariableInfo; - VariableInfo* pNewV = - (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); - memset(pNewV, 0, sizeof(VariableInfo)); - pNewV->tok = tok; - pNewV->level = level(); - pNewV->pOldDefinition = pOldV; - token.mpVariableInfo = pNewV; - mStack.push_back(pNewV); - return pNewV; - } - - VariableInfo* addStructTag(tokenid_t tok) { - Token& token = (*mpTokenTable)[tok]; - VariableInfo* pOldS = token.mpStructInfo; - VariableInfo* pNewS = - (VariableInfo*) mpArena->alloc(sizeof(VariableInfo)); - memset(pNewS, 0, sizeof(VariableInfo)); - pNewS->tok = tok; - pNewS->level = level(); - pNewS->isStructTag = true; - pNewS->pOldDefinition = pOldS; - token.mpStructInfo = pNewS; - mStack.push_back(pNewS); - return pNewS; - } - - VariableInfo* add(Type* pType) { - VariableInfo* pVI = add(pType->id); - pVI->pType = pType; - return pVI; - } - - void forEach(bool (*fn)(VariableInfo*, void*), void* context) { - for (size_t i = 0; i < mStack.size(); i++) { - if (! fn(mStack[i], context)) { - break; - } - } - } - - private: - inline size_t level() { - return mLevelStack.size(); - } - - struct Mark { - Arena::Mark mArenaMark; - size_t mSymbolHead; - }; - - Arena* mpArena; - TokenTable* mpTokenTable; - Vector<VariableInfo*> mStack; - Vector<Mark> mLevelStack; - }; - - struct MacroState { - tokenid_t name; // Name of the current macro we are expanding - char* dptr; // point to macro text during macro playback - int dch; // Saves old value of ch during a macro playback - }; - -#define MACRO_NESTING_MAX 32 - MacroState macroState[MACRO_NESTING_MAX]; - int macroLevel; // -1 means not playing any macro. - - int ch; // Current input character, or EOF - tokenid_t tok; // token - intptr_t tokc; // token extra info - double tokd; // floating point constant value - int tokl; // token operator level - intptr_t rsym; // return symbol - Type* pReturnType; // type of the current function's return. - intptr_t loc; // local variable index - char* glo; // global variable index - String mTokenString; - bool mbSuppressMacroExpansion; - char* pGlobalBase; - ACCSymbolLookupFn mpSymbolLookupFn; - void* mpSymbolLookupContext; - - // Arena for the duration of the compile - Arena mGlobalArena; - // Arena for data that's only needed when compiling a single function - Arena mLocalArena; - - Arena* mpCurrentArena; - - TokenTable mTokenTable; - SymbolStack mGlobals; - SymbolStack mLocals; - - SymbolStack* mpCurrentSymbolStack; - - // Prebuilt types, makes things slightly faster. - Type* mkpInt; // int - Type* mkpShort; // short - Type* mkpChar; // char - Type* mkpVoid; // void - Type* mkpFloat; - Type* mkpDouble; - Type* mkpIntFn; - Type* mkpIntPtr; - Type* mkpCharPtr; - Type* mkpFloatPtr; - Type* mkpDoublePtr; - Type* mkpPtrIntFn; - - InputStream* file; - int mLineNumber; - bool mbBumpLine; - - ICodeBuf* pCodeBuf; - CodeGenerator* pGen; - - String mErrorBuf; - - String mPragmas; - int mPragmaStringCount; - int mCompileResult; - - static const int ALLOC_SIZE = 99999; - - static const int TOK_DUMMY = 1; - static const int TOK_NUM = 2; - static const int TOK_NUM_FLOAT = 3; - static const int TOK_NUM_DOUBLE = 4; - static const int TOK_OP_ASSIGNMENT = 5; - static const int TOK_OP_ARROW = 6; - - // 3..255 are character and/or operators - - // Keywords start at 0x100 and increase by 1 - // Order has to match string list in "internKeywords". - enum { - TOK_KEYWORD = TokenTable::TOKEN_BASE, - TOK_INT = TOK_KEYWORD, - TOK_CHAR, - TOK_VOID, - TOK_IF, - TOK_ELSE, - TOK_WHILE, - TOK_BREAK, - TOK_RETURN, - TOK_FOR, - TOK_AUTO, - TOK_CASE, - TOK_CONST, - TOK_CONTINUE, - TOK_DEFAULT, - TOK_DO, - TOK_DOUBLE, - TOK_ENUM, - TOK_EXTERN, - TOK_FLOAT, - TOK_GOTO, - TOK_LONG, - TOK_REGISTER, - TOK_SHORT, - TOK_SIGNED, - TOK_SIZEOF, - TOK_STATIC, - TOK_STRUCT, - TOK_SWITCH, - TOK_TYPEDEF, - TOK_UNION, - TOK_UNSIGNED, - TOK_VOLATILE, - TOK__BOOL, - TOK__COMPLEX, - TOK__IMAGINARY, - TOK_INLINE, - TOK_RESTRICT, - - // Symbols start after keywords - - TOK_SYMBOL, - TOK_PRAGMA = TOK_SYMBOL, - TOK_DEFINE, - TOK_LINE - }; - - static const int LOCAL = 0x200; - - /* tokens in string heap */ - static const int TAG_TOK = ' '; - - 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[]; - - /* Called when we detect an internal problem. Does nothing in production. - * - */ - void internalError() { - * (char*) 0 = 0; - } - - void assertImpl(bool isTrue, int line) { - if (!isTrue) { - LOGD("%d: assertion failed at line %s:%d.", mLineNumber, __FILE__, line); - internalError(); - } - } - - bool isSymbol(tokenid_t t) { - return t >= TOK_SYMBOL && - ((size_t) (t-TOK_SYMBOL)) < mTokenTable.size(); - } - - bool isSymbolOrKeyword(tokenid_t t) { - return t >= TOK_KEYWORD && - ((size_t) (t-TOK_KEYWORD)) < mTokenTable.size(); - } - - VariableInfo* VI(tokenid_t t) { - assert(isSymbol(t)); - VariableInfo* pV = mTokenTable[t].mpVariableInfo; - if (pV && pV->tok != t) { - internalError(); - } - return pV; - } - - inline bool isDefined(tokenid_t t) { - return t >= TOK_SYMBOL && VI(t) != 0; - } - - const char* nameof(tokenid_t t) { - assert(isSymbolOrKeyword(t)); - return mTokenTable[t].pText; - } - - void pdef(int t) { - mTokenString.append(t); - } - - void inp() { - // Close any totally empty macros. We leave them on the stack until now - // so that we know which macros are being expanded when checking if the - // last token in the macro is a macro that's already being expanded. - while (macroLevel >= 0 && macroState[macroLevel].dptr == NULL) { - macroLevel--; - } - if (macroLevel >= 0) { - ch = *macroState[macroLevel].dptr++; - if (ch == 0) { - ch = macroState[macroLevel].dch; - macroState[macroLevel].dptr = NULL; // This macro's done - } - } else { - if (mbBumpLine) { - mLineNumber++; - mbBumpLine = false; - } - ch = file->getChar(); - if (ch == '\n') { - mbBumpLine = true; - } - } -#if 0 - printf("ch='%c' 0x%x\n", ch, ch); -#endif - } - - int isid() { - return isalnum(ch) | (ch == '_'); - } - - int decodeHex(int c) { - if (isdigit(c)) { - c -= '0'; - } else if (c <= 'F') { - c = c - 'A' + 10; - } else { - c =c - 'a' + 10; - } - return c; - } - - /* read a character constant, advances ch to after end of constant */ - int getq() { - int val = ch; - if (ch == '\\') { - inp(); - if (isoctal(ch)) { - // 1 to 3 octal characters. - val = 0; - for(int i = 0; i < 3; i++) { - if (isoctal(ch)) { - val = (val << 3) + ch - '0'; - inp(); - } - } - return val; - } else if (ch == 'x' || ch == 'X') { - // N hex chars - inp(); - if (! isxdigit(ch)) { - error("'x' character escape requires at least one digit."); - } else { - val = 0; - while (isxdigit(ch)) { - val = (val << 4) + decodeHex(ch); - inp(); - } - } - } else { - int val = ch; - switch (ch) { - case 'a': - val = '\a'; - break; - case 'b': - val = '\b'; - break; - case 'f': - val = '\f'; - break; - case 'n': - val = '\n'; - break; - case 'r': - val = '\r'; - break; - case 't': - val = '\t'; - break; - case 'v': - val = '\v'; - break; - case '\\': - val = '\\'; - break; - case '\'': - val = '\''; - break; - case '"': - val = '"'; - break; - case '?': - val = '?'; - break; - default: - error("Undefined character escape %c", ch); - break; - } - inp(); - return val; - } - } else { - inp(); - } - return val; - } - - static bool isoctal(int ch) { - return ch >= '0' && ch <= '7'; - } - - bool acceptCh(int c) { - bool result = c == ch; - if (result) { - pdef(ch); - inp(); - } - return result; - } - - bool acceptDigitsCh() { - bool result = false; - while (isdigit(ch)) { - result = true; - pdef(ch); - inp(); - } - return result; - } - - void parseFloat() { - tok = TOK_NUM_DOUBLE; - // mTokenString already has the integral part of the number. - if(mTokenString.len() == 0) { - mTokenString.append('0'); - } - acceptCh('.'); - acceptDigitsCh(); - if (acceptCh('e') || acceptCh('E')) { - acceptCh('-') || acceptCh('+'); - acceptDigitsCh(); - } - if (ch == 'f' || ch == 'F') { - tok = TOK_NUM_FLOAT; - inp(); - } else if (ch == 'l' || ch == 'L') { - inp(); - error("Long floating point constants not supported."); - } - char* pText = mTokenString.getUnwrapped(); - char* pEnd = pText + strlen(pText); - char* pEndPtr = 0; - errno = 0; - if (tok == TOK_NUM_FLOAT) { - tokd = strtof(pText, &pEndPtr); - } else { - tokd = strtod(pText, &pEndPtr); - } - if (errno || pEndPtr != pEnd) { - error("Can't parse constant: %s", pText); - } - // fprintf(stderr, "float constant: %s (%d) %g\n", pText, tok, tokd); - } - - bool currentlyBeingExpanded(tokenid_t id) { - for (int i = 0; i <= macroLevel; i++) { - if (macroState[macroLevel].name == id) { - return true; - } - } - return false; - } - - void next() { - int l, a; - - while (isspace(ch) | (ch == '#')) { - if (ch == '#') { - inp(); - next(); - if (tok == TOK_DEFINE) { - doDefine(); - } else if (tok == TOK_PRAGMA) { - doPragma(); - } else if (tok == TOK_LINE) { - doLine(); - } else { - error("Unsupported preprocessor directive \"%s\"", - mTokenString.getUnwrapped()); - } - } - inp(); - } - tokl = 0; - tok = ch; - /* encode identifiers & numbers */ - if (isdigit(ch) || ch == '.') { - // Start of a numeric constant. Could be integer, float, or - // double, won't know until we look further. - mTokenString.clear(); - pdef(ch); - inp(); - if (tok == '.' && !isdigit(ch)) { - goto done; - } - int base = 10; - if (tok == '0') { - if (ch == 'x' || ch == 'X') { - base = 16; - tok = TOK_NUM; - tokc = 0; - inp(); - while ( isxdigit(ch) ) { - tokc = (tokc << 4) + decodeHex(ch); - inp(); - } - } else if (isoctal(ch)){ - base = 8; - tok = TOK_NUM; - tokc = 0; - while ( isoctal(ch) ) { - tokc = (tokc << 3) + (ch - '0'); - inp(); - } - } - } else if (isdigit(tok)){ - acceptDigitsCh(); - } - if (base == 10) { - if (tok == '.' || ch == '.' || ch == 'e' || ch == 'E') { - parseFloat(); - } else { - // It's an integer constant - char* pText = mTokenString.getUnwrapped(); - char* pEnd = pText + strlen(pText); - char* pEndPtr = 0; - errno = 0; - tokc = strtol(pText, &pEndPtr, base); - if (errno || pEndPtr != pEnd) { - error("Can't parse constant: %s %d %d", pText, base, errno); - } - tok = TOK_NUM; - } - } - } else if (isid()) { - mTokenString.clear(); - while (isid()) { - pdef(ch); - inp(); - } - tok = mTokenTable.intern(mTokenString.getUnwrapped(), mTokenString.len()); - if (! mbSuppressMacroExpansion) { - // Is this a macro? - char* pMacroDefinition = mTokenTable[tok].mpMacroDefinition; - if (pMacroDefinition && !currentlyBeingExpanded(tok)) { - // Yes, it is a macro -#if 0 - printf("Expanding macro %s -> %s", - mTokenString.getUnwrapped(), pMacroDefinition); -#endif - if (macroLevel >= MACRO_NESTING_MAX-1) { - error("Too many levels of macro recursion."); - } else { - macroLevel++; - macroState[macroLevel].name = tok; - macroState[macroLevel].dptr = pMacroDefinition; - macroState[macroLevel].dch = ch; - inp(); - next(); - } - } - } - } else { - inp(); - if (tok == '\'') { - tok = TOK_NUM; - tokc = getq(); - if (ch != '\'') { - error("Expected a ' character, got %c", ch); - } else { - inp(); - } - } else if ((tok == '/') & (ch == '*')) { - inp(); - while (ch && ch != EOF) { - while (ch != '*' && ch != EOF) - inp(); - inp(); - if (ch == '/') - ch = 0; - } - if (ch == EOF) { - error("End of file inside comment."); - } - inp(); - next(); - } else if ((tok == '/') & (ch == '/')) { - inp(); - while (ch && (ch != '\n') && (ch != EOF)) { - inp(); - } - inp(); - next(); - } else if ((tok == '-') & (ch == '>')) { - inp(); - tok = TOK_OP_ARROW; - } else { - const char* t = operatorChars; - int opIndex = 0; - while ((l = *t++) != 0) { - 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 */ - } - /* check for op=, valid for * / % + - << >> & ^ | */ - if (ch == '=' && - ((tokl >= 1 && tokl <= 3) - || (tokl >=6 && tokl <= 8)) ) { - inp(); - tok = TOK_OP_ASSIGNMENT; - } - break; - } - opIndex++; - } - if (l == 0) { - tokl = 0; - tokc = 0; - } - } - } - - done: ; -#if 0 - { - String buf; - decodeToken(buf, tok, true); - fprintf(stderr, "%s\n", buf.getUnwrapped()); - } -#endif - } - - void doDefine() { - mbSuppressMacroExpansion = true; - next(); - mbSuppressMacroExpansion = false; - tokenid_t name = tok; - if (ch == '(') { - error("Defines with arguments not supported"); - return; - } - while (isspace(ch)) { - inp(); - } - String value; - bool appendToValue = true; - while (ch != '\n' && ch != EOF) { - // Check for '//' comments. - if (appendToValue && ch == '/') { - inp(); - if (ch == '/') { - appendToValue = false; - } else { - value.append('/'); - } - } - if (appendToValue && ch != EOF) { - value.append(ch); - } - inp(); - } - char* pDefn = (char*)mGlobalArena.alloc(value.len() + 1); - memcpy(pDefn, value.getUnwrapped(), value.len()); - pDefn[value.len()] = 0; - mTokenTable[name].mpMacroDefinition = pDefn; -#if 0 - { - String buf; - decodeToken(buf, name, true); - fprintf(stderr, "define %s = \"%s\"\n", buf.getUnwrapped(), pDefn); - } -#endif - } - - void doPragma() { - // # pragma name(val) - int state = 0; - while(ch != EOF && ch != '\n' && state < 10) { - switch(state) { - case 0: - if (isspace(ch)) { - inp(); - } else { - state++; - } - break; - case 1: - if (isalnum(ch)) { - mPragmas.append(ch); - inp(); - } else if (ch == '(') { - mPragmas.append(0); - inp(); - state++; - } else { - state = 11; - } - break; - case 2: - if (isalnum(ch)) { - mPragmas.append(ch); - inp(); - } else if (ch == ')') { - mPragmas.append(0); - inp(); - state = 10; - } else { - state = 11; - } - break; - } - } - if(state != 10) { - error("Unexpected pragma syntax"); - } - mPragmaStringCount += 2; - } - - void doLine() { - // # line number { "filename "} - next(); - if (tok != TOK_NUM) { - error("Expected a line-number"); - } else { - mLineNumber = tokc-1; // The end-of-line will increment it. - } - while(ch != EOF && ch != '\n') { - inp(); - } - } - - virtual void verror(const char* fmt, va_list ap) { - mErrorBuf.printf("%ld: ", mLineNumber); - mErrorBuf.vprintf(fmt, ap); - mErrorBuf.printf("\n"); - } - - void skip(intptr_t c) { - if (!accept(c)) { - error("'%c' expected", c); - } - } - - bool accept(intptr_t c) { - if (tok == c) { - next(); - return true; - } - return false; - } - - bool acceptStringLiteral() { - if (tok == '"') { - pGen->leaR0((int) glo, mkpCharPtr, ET_RVALUE); - // This while loop merges multiple adjacent string constants. - while (tok == '"') { - while (ch != '"' && ch != EOF) { - *allocGlobalSpace(1,1) = getq(); - } - if (ch != '"') { - error("Unterminated string constant."); - } - inp(); - next(); - } - /* Null terminate */ - *glo = 0; - /* align heap */ - allocGlobalSpace(1,(char*) (((intptr_t) glo + 4) & -4) - glo); - - return true; - } - return false; - } - - void linkGlobal(tokenid_t t, bool isFunction) { - VariableInfo* pVI = VI(t); - void* n = NULL; - if (mpSymbolLookupFn) { - n = mpSymbolLookupFn(mpSymbolLookupContext, nameof(t)); - } - if (pVI->pType == NULL) { - if (isFunction) { - pVI->pType = mkpIntFn; - } else { - pVI->pType = mkpInt; - } - } - pVI->pAddress = n; - } - - void unaryOrAssignment() { - unary(); - if (accept('=')) { - checkLVal(); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->storeR0ToTOS(); - } else if (tok == TOK_OP_ASSIGNMENT) { - int t = tokc; - next(); - checkLVal(); - pGen->pushR0(); - pGen->forceR0RVal(); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->genOp(t); - pGen->storeR0ToTOS(); - } - } - - /* Parse and evaluate a unary expression. - */ - void unary() { - tokenid_t t; - intptr_t a; - t = 0; - if (acceptStringLiteral()) { - // Nothing else to do. - } else { - int c = tokl; - a = tokc; - double ad = tokd; - t = tok; - next(); - if (t == TOK_NUM) { - pGen->li(a); - } else if (t == TOK_NUM_FLOAT) { - // Align to 4-byte boundary - glo = (char*) (((intptr_t) glo + 3) & -4); - * (float*) glo = (float) ad; - pGen->loadFloat((int) glo, mkpFloat); - glo += 4; - } else if (t == TOK_NUM_DOUBLE) { - // Align to 8-byte boundary - glo = (char*) (((intptr_t) glo + 7) & -8); - * (double*) glo = ad; - pGen->loadFloat((int) glo, mkpDouble); - glo += 8; - } else if (c == 2) { - /* -, +, !, ~ */ - unary(); - pGen->forceR0RVal(); - if (t == '!') - pGen->gUnaryCmp(a); - else if (t == '+') { - // ignore unary plus. - } else { - pGen->genUnaryOp(a); - } - } else if (c == 11) { - // pre increment / pre decrement - unary(); - doIncDec(a == OP_INCREMENT, 0); - } - else if (t == '(') { - // It's either a cast or an expression - Type* pCast = acceptCastTypeDeclaration(); - if (pCast) { - skip(')'); - unary(); - pGen->forceR0RVal(); - pGen->castR0(pCast); - } else { - commaExpr(); - skip(')'); - } - } else if (t == '*') { - /* This is a pointer dereference. - */ - unary(); - doPointer(); - } else if (t == '&') { - unary(); - doAddressOf(); - } else if (t == EOF ) { - error("Unexpected EOF."); - } else if (t == ';') { - error("Unexpected ';'"); - } else if (!checkSymbol(t)) { - // Don't have to do anything special here, the error - // message was printed by checkSymbol() above. - } else { - if (!isDefined(t)) { - mGlobals.add(t); - // printf("Adding new global function %s\n", nameof(t)); - } - VariableInfo* pVI = VI(t); - int n = (intptr_t) pVI->pAddress; - /* forward reference: try our lookup function */ - if (!n) { - linkGlobal(t, tok == '('); - n = (intptr_t) pVI->pAddress; - if (!n && tok != '(') { - error("Undeclared variable %s", nameof(t)); - } - } - if (tok != '(') { - /* variable or function name */ - if (!n) { - linkGlobal(t, false); - n = (intptr_t) pVI->pAddress; - if (!n) { - error("Undeclared variable %s", nameof(t)); - } - } - } - // load a variable - Type* pVal; - ExpressionType et; - if (pVI->pType->tag == TY_ARRAY) { - pVal = pVI->pType; - et = ET_RVALUE; - } else { - pVal = createPtrType(pVI->pType); - et = ET_LVALUE; - } - if (n) { - int tag = pVal->pHead->tag; - if (tag == TY_FUNC) { - et = ET_RVALUE; - } - pGen->leaR0(n, pVal, et); - } else { - pVI->pForward = (void*) pGen->leaForward( - (int) pVI->pForward, pVal); - } - } - } - - /* Now handle postfix operators */ - for(;;) { - if (tokl == 11) { - // post inc / post dec - doIncDec(tokc == OP_INCREMENT, true); - next(); - } else if (accept('[')) { - // Array reference - pGen->forceR0RVal(); - pGen->pushR0(); - commaExpr(); - pGen->forceR0RVal(); - pGen->genOp(OP_PLUS); - doPointer(); - skip(']'); - } else if (accept('.')) { - // struct element - pGen->forceR0RVal(); - Type* pStruct = pGen->getR0Type(); - if (pStruct->tag == TY_STRUCT) { - doStructMember(pStruct, true); - } else { - error("expected a struct value to the left of '.'"); - } - } else if (accept(TOK_OP_ARROW)) { - pGen->forceR0RVal(); - Type* pPtr = pGen->getR0Type(); - if (pPtr->tag == TY_POINTER && pPtr->pHead->tag == TY_STRUCT) { - pGen->loadR0FromR0(); - doStructMember(pPtr->pHead, false); - } else { - error("Expected a pointer to a struct to the left of '->'"); - } - } else if (accept('(')) { - /* function call */ - Type* pDecl = NULL; - VariableInfo* pVI = NULL; - Type* pFn = pGen->getR0Type(); - if (pFn->tag == TY_POINTER && pFn->pHead->tag == TY_FUNC) { - pDecl = pFn->pHead; - pGen->pushR0(); - Type* pArgList = pDecl->pTail; - bool varArgs = pArgList == NULL; - /* push args and invert order */ - a = pGen->beginFunctionCallArguments(); - int l = 0; - int argCount = 0; - while (tok != ')' && tok != EOF) { - if (! varArgs && !pArgList) { - error("Unexpected argument."); - } - expr(); - pGen->forceR0RVal(); - Type* pTargetType; - if (pArgList) { - pTargetType = pArgList->pHead; - pArgList = pArgList->pTail; - } else { - // This is a ... function, just pass arguments in their - // natural type. - pTargetType = pGen->getR0Type(); - if (pTargetType->tag == TY_FLOAT) { - pTargetType = mkpDouble; - } else if (pTargetType->tag == TY_ARRAY) { - // Pass arrays by pointer. - pTargetType = pTargetType->pTail; - } - } - if (pTargetType->tag == TY_VOID) { - error("Can't pass void value for argument %d", - argCount + 1); - } else { - l += pGen->storeR0ToArg(l, pTargetType); - } - if (accept(',')) { - // fine - } else if ( tok != ')') { - error("Expected ',' or ')'"); - } - argCount += 1; - } - if (! varArgs && pArgList) { - error("Expected more argument(s). Saw %d", argCount); - } - pGen->endFunctionCallArguments(pDecl, a, l); - skip(')'); - pGen->callIndirect(l, pDecl); - pGen->adjustStackAfterCall(pDecl, l, true); - } else { - error("Expected a function value to left of '('."); - } - } else { - break; - } - } - } - - void doStructMember(Type* pStruct, bool isDot) { - Type* pStructElement = lookupStructMember(pStruct, tok); - if (pStructElement) { - next(); - pGen->addStructOffsetR0(pStructElement->length, createPtrType(pStructElement->pHead)); - } else { - String buf; - decodeToken(buf, tok, true); - error("Expected a struct member to the right of '%s', got %s", - isDot ? "." : "->", buf.getUnwrapped()); - } - } - - void doIncDec(int isInc, int isPost) { - // R0 already has the lval - checkLVal(); - int lit = isInc ? 1 : -1; - pGen->pushR0(); - pGen->loadR0FromR0(); - int tag = pGen->getR0Type()->tag; - if (!(tag == TY_INT || tag == TY_SHORT || tag == TY_CHAR || - tag == TY_POINTER)) { - error("++/-- illegal for this type. %d", tag); - } - if (isPost) { - pGen->over(); - pGen->pushR0(); - pGen->li(lit); - pGen->genOp(OP_PLUS); - pGen->storeR0ToTOS(); - pGen->popR0(); - } else { - pGen->pushR0(); - pGen->li(lit); - pGen->genOp(OP_PLUS); - pGen->over(); - pGen->storeR0ToTOS(); - pGen->popR0(); - } - } - - void doPointer() { - pGen->forceR0RVal(); - Type* pR0Type = pGen->getR0Type(); - if (pR0Type->tag != TY_POINTER) { - error("Expected a pointer type."); - } else { - if (pR0Type->pHead->tag != TY_FUNC) { - pGen->setR0ExpressionType(ET_LVALUE); - } - } - } - - void doAddressOf() { - Type* pR0 = pGen->getR0Type(); - bool isFuncPtr = pR0->tag == TY_POINTER && pR0->pHead->tag == TY_FUNC; - if ((! isFuncPtr) && pGen->getR0ExpressionType() != ET_LVALUE) { - error("Expected an lvalue"); - } - Type* pR0Type = pGen->getR0Type(); - pGen->setR0ExpressionType(ET_RVALUE); - } - - /* Recursive descent parser for binary operations. - */ - void binaryOp(int level) { - intptr_t t, a; - t = 0; - if (level-- == 1) - unaryOrAssignment(); - else { - binaryOp(level); - a = 0; - while (level == tokl) { - t = tokc; - next(); - pGen->forceR0RVal(); - if (level > 8) { - a = pGen->gtst(t == OP_LOGICAL_OR, a); /* && and || output code generation */ - binaryOp(level); - } else { - pGen->pushR0(); - binaryOp(level); - // Check for syntax error. - if (pGen->getR0Type() == NULL) { - // We failed to parse a right-hand argument. - // Push a dummy value so we don't fail - pGen->li(0); - } - pGen->forceR0RVal(); - if ((level == 4) | (level == 5)) { - pGen->gcmp(t); - } else { - pGen->genOp(t); - } - } - } - /* && and || output code generation */ - if (a && level > 8) { - pGen->forceR0RVal(); - a = pGen->gtst(t == OP_LOGICAL_OR, a); - pGen->li(t != OP_LOGICAL_OR); - int b = pGen->gjmp(0); - pGen->gsym(a); - pGen->li(t == OP_LOGICAL_OR); - pGen->gsym(b); - } - } - } - - void commaExpr() { - for(;;) { - expr(); - if (!accept(',')) { - break; - } - } - } - - void expr() { - binaryOp(11); - } - - int test_expr() { - commaExpr(); - pGen->forceR0RVal(); - return pGen->gtst(0, 0); - } - - void block(intptr_t* breakLabel, intptr_t continueAddress, bool outermostFunctionBlock) { - intptr_t a, n, t; - - Type* pBaseType; - if ((pBaseType = acceptPrimitiveType(true))) { - /* declarations */ - localDeclarations(pBaseType); - } else if (tok == TOK_IF) { - next(); - skip('('); - a = test_expr(); - skip(')'); - block(breakLabel, continueAddress, false); - if (tok == TOK_ELSE) { - next(); - n = pGen->gjmp(0); /* jmp */ - pGen->gsym(a); - block(breakLabel, continueAddress, false); - 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 = pCodeBuf->getPC(); // top of loop, target of "next" iteration - a = test_expr(); - } else { - if (tok != ';') - commaExpr(); - skip(';'); - n = pCodeBuf->getPC(); - a = 0; - if (tok != ';') - a = test_expr(); - skip(';'); - if (tok != ')') { - t = pGen->gjmp(0); - commaExpr(); - pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); - pGen->gsym(t); - n = t + 4; - } - } - skip(')'); - block(&a, n, false); - pGen->gjmp(n - pCodeBuf->getPC() - pGen->jumpOffset()); /* jmp */ - pGen->gsym(a); - } else if (tok == '{') { - if (! outermostFunctionBlock) { - mLocals.pushLevel(); - } - next(); - while (tok != '}' && tok != EOF) - block(breakLabel, continueAddress, false); - skip('}'); - if (! outermostFunctionBlock) { - mLocals.popLevel(); - } - } else { - if (accept(TOK_RETURN)) { - if (tok != ';') { - commaExpr(); - pGen->forceR0RVal(); - if (pReturnType->tag == TY_VOID) { - error("Must not return a value from a void function"); - } else { - pGen->convertR0(pReturnType); - } - } else { - if (pReturnType->tag != TY_VOID) { - error("Must specify a value here"); - } - } - rsym = pGen->gjmp(rsym); /* jmp */ - } else if (accept(TOK_BREAK)) { - if (breakLabel) { - *breakLabel = pGen->gjmp(*breakLabel); - } else { - error("break statement must be within a for, do, while, or switch statement"); - } - } else if (accept(TOK_CONTINUE)) { - if (continueAddress) { - pGen->gjmp(continueAddress - pCodeBuf->getPC() - pGen->jumpOffset()); - } else { - error("continue statement must be within a for, do, or while statement"); - } - } else if (tok != ';') - commaExpr(); - skip(';'); - } - } - - static bool typeEqual(Type* a, Type* b) { - if (a == b) { - return true; - } - if (a == NULL || b == NULL) { - return false; - } - TypeTag at = a->tag; - if (at != b->tag) { - return false; - } - if (at == TY_POINTER) { - return typeEqual(a->pHead, b->pHead); - } else if (at == TY_ARRAY) { - return a->length == b->length && typeEqual(a->pHead, b->pHead); - } else if (at == TY_FUNC || at == TY_PARAM) { - return typeEqual(a->pHead, b->pHead) - && typeEqual(a->pTail, b->pTail); - } else if (at == TY_STRUCT) { - return a->pHead == b->pHead; - } - return true; - } - - Type* createType(TypeTag tag, Type* pHead, Type* pTail) { - assert(tag >= TY_UNKNOWN && tag <= TY_PARAM); - Type* pType = (Type*) mpCurrentArena->alloc(sizeof(Type)); - memset(pType, 0, sizeof(*pType)); - pType->storageClass = SC_DEFAULT; - pType->tag = tag; - pType->pHead = pHead; - pType->pTail = pTail; - return pType; - } - - Type* createPtrType(Type* pType) { - return createType(TY_POINTER, pType, NULL); - } - - /** - * Try to print a type in declaration order - */ - void decodeType(String& buffer, Type* pType) { - buffer.clear(); - if (pType == NULL) { - buffer.appendCStr("null"); - return; - } - decodeTypeImp(buffer, pType); - } - - void decodeTypeImp(String& buffer, Type* pType) { - decodeTypeImpPrefix(buffer, pType); - decodeId(buffer, pType->id); - decodeTypeImpPostfix(buffer, pType); - } - - void decodeId(String& buffer, tokenid_t id) { - if (id) { - String temp; - decodeToken(temp, id, false); - buffer.append(temp); - } - } - - void decodeTypeImpPrefix(String& buffer, Type* pType) { - TypeTag tag = pType->tag; - - if ((tag >= TY_INT && tag <= TY_DOUBLE) || tag == TY_STRUCT) { - switch (tag) { - case TY_INT: - buffer.appendCStr("int"); - break; - case TY_SHORT: - buffer.appendCStr("short"); - break; - case TY_CHAR: - buffer.appendCStr("char"); - break; - case TY_VOID: - buffer.appendCStr("void"); - break; - case TY_FLOAT: - buffer.appendCStr("float"); - break; - case TY_DOUBLE: - buffer.appendCStr("double"); - break; - case TY_STRUCT: - { - bool isStruct = (pType->pHead->alignment & 0x80000000) != 0; - buffer.appendCStr(isStruct ? "struct" : "union"); - if (pType->pHead && pType->pHead->structTag) { - buffer.append(' '); - decodeId(buffer, pType->pHead->structTag); - } - } - break; - default: - break; - } - buffer.append(' '); - } - - switch (tag) { - case TY_INT: - break; - case TY_SHORT: - break; - case TY_CHAR: - break; - case TY_VOID: - break; - case TY_FLOAT: - break; - case TY_DOUBLE: - break; - case TY_POINTER: - decodeTypeImpPrefix(buffer, pType->pHead); - if(pType->pHead && pType->pHead->tag == TY_FUNC) { - buffer.append('('); - } - buffer.append('*'); - break; - case TY_ARRAY: - decodeTypeImpPrefix(buffer, pType->pHead); - break; - case TY_STRUCT: - break; - case TY_FUNC: - decodeTypeImp(buffer, pType->pHead); - break; - case TY_PARAM: - decodeTypeImp(buffer, pType->pHead); - break; - default: - String temp; - temp.printf("Unknown tag %d", pType->tag); - buffer.append(temp); - break; - } - } - - void decodeTypeImpPostfix(String& buffer, Type* pType) { - TypeTag tag = pType->tag; - - switch(tag) { - case TY_POINTER: - if(pType->pHead && pType->pHead->tag == TY_FUNC) { - buffer.append(')'); - } - decodeTypeImpPostfix(buffer, pType->pHead); - break; - case TY_ARRAY: - { - String temp; - temp.printf("[%d]", pType->length); - buffer.append(temp); - } - break; - case TY_STRUCT: - if (pType->pHead->length >= 0) { - buffer.appendCStr(" {"); - for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { - decodeTypeImp(buffer, pArg->pHead); - buffer.appendCStr(";"); - } - buffer.append('}'); - } - break; - case TY_FUNC: - buffer.append('('); - for(Type* pArg = pType->pTail; pArg; pArg = pArg->pTail) { - decodeTypeImp(buffer, pArg); - if (pArg->pTail) { - buffer.appendCStr(", "); - } - } - buffer.append(')'); - break; - default: - break; - } - } - - void printType(Type* pType) { - String buffer; - decodeType(buffer, pType); - fprintf(stderr, "%s\n", buffer.getUnwrapped()); - } - - void insertTypeSpecifier(Type** ppType, TypeTag tag) { - if (! *ppType) { - *ppType = createType(tag, NULL, NULL); - } else { - if ((*ppType)->tag != TY_UNKNOWN) { - error("Only one type specifier allowed."); - } else { - (*ppType)->tag = tag; - } - } - } - - void insertStorageClass(Type** ppType, StorageClass storageClass) { - if (! *ppType) { - *ppType = createType(TY_UNKNOWN, NULL, NULL); - } - if ((*ppType)->storageClass != SC_DEFAULT) { - error("Only one storage class allowed."); - } else { - (*ppType)->storageClass = storageClass; - } - } - - Type* acceptPrimitiveType(bool allowStorageClass) { - Type* pType = NULL; - for (bool keepGoing = true; keepGoing;) { - switch(tok) { - case TOK_AUTO: - insertStorageClass(&pType, SC_AUTO); - break; - case TOK_REGISTER: - insertStorageClass(&pType, SC_REGISTER); - break; - case TOK_STATIC: - insertStorageClass(&pType, SC_STATIC); - break; - case TOK_EXTERN: - insertStorageClass(&pType, SC_EXTERN); - break; - case TOK_TYPEDEF: - insertStorageClass(&pType, SC_TYPEDEF); - break; - case TOK_INT: - insertTypeSpecifier(&pType, TY_INT); - break; - case TOK_SHORT: - insertTypeSpecifier(&pType, TY_SHORT); - break; - case TOK_CHAR: - insertTypeSpecifier(&pType, TY_CHAR); - break; - case TOK_VOID: - insertTypeSpecifier(&pType, TY_VOID); - break; - case TOK_FLOAT: - insertTypeSpecifier(&pType, TY_FLOAT); - break; - case TOK_DOUBLE: - insertTypeSpecifier(&pType, TY_DOUBLE); - break; - case TOK_STRUCT: - case TOK_UNION: - { - insertTypeSpecifier(&pType, TY_STRUCT); - bool isStruct = (tok == TOK_STRUCT); - next(); - pType = acceptStruct(pType, isStruct); - keepGoing = false; - } - break; - default: - // Is it a typedef? - if (isSymbol(tok)) { - VariableInfo* pV = VI(tok); - if (pV && pV->pType->storageClass == SC_TYPEDEF) { - if (! pType) { - pType = createType(TY_UNKNOWN, NULL, NULL); - } - StorageClass storageClass = pType->storageClass; - *pType = *pV->pType; - pType->storageClass = storageClass; - } else { - keepGoing = false; - } - } else { - keepGoing = false; - } - } - if (keepGoing) { - next(); - } - } - if (pType) { - if (pType->tag == TY_UNKNOWN) { - pType->tag = TY_INT; - } - if (allowStorageClass) { - switch(pType->storageClass) { - case SC_AUTO: error("auto not supported."); break; - case SC_REGISTER: error("register not supported."); break; - case SC_STATIC: error("static not supported."); break; - case SC_EXTERN: error("extern not supported."); break; - default: break; - } - } else { - if (pType->storageClass != SC_DEFAULT) { - error("An explicit storage class is not allowed in this type declaration"); - } - } - } - return pType; - } - - Type* acceptStruct(Type* pStructType, bool isStruct) { - tokenid_t structTag = acceptSymbol(); - bool isDeclaration = accept('{'); - bool fail = false; - - if (structTag) { - Token* pToken = &mTokenTable[structTag]; - VariableInfo* pStructInfo = pToken->mpStructInfo; - bool needToDeclare = !pStructInfo; - if (pStructInfo) { - if (isDeclaration) { - if (mpCurrentSymbolStack->isStructTagDefinedAtCurrentLevel(structTag)) { - if (pStructInfo->pType->pHead->length == -1) { - // we're filling in a forward declaration. - needToDeclare = false; - } else { - error("A struct with the same name is already defined at this level."); - fail = true; - } - } else { - needToDeclare = true; - } - } - if (!fail) { - assert(pStructInfo->isStructTag); - pStructType->pHead = pStructInfo->pType; - pStructType->pTail = pStructType->pHead->pTail; - } - } - - if (needToDeclare) { - // This is a new struct name - pToken->mpStructInfo = mpCurrentSymbolStack->addStructTag(structTag); - StorageClass storageClass = pStructType->storageClass; - pStructType = createType(TY_STRUCT, NULL, NULL); - pStructType->structTag = structTag; - pStructType->pHead = pStructType; - pStructType->storageClass = storageClass; - if (! isDeclaration) { - // A forward declaration - pStructType->length = -1; - } - pToken->mpStructInfo->pType = pStructType; - } - } else { - // An anonymous struct - pStructType->pHead = pStructType; - } - - if (isDeclaration) { - size_t offset = 0; - size_t structSize = 0; - size_t structAlignment = 0; - Type** pParamHolder = & pStructType->pHead->pTail; - while (tok != '}' && tok != EOF) { - Type* pPrimitiveType = expectPrimitiveType(false); - if (pPrimitiveType) { - while (tok != ';' && tok != EOF) { - Type* pItem = acceptDeclaration(pPrimitiveType, true, false); - if (!pItem) { - break; - } - if (lookupStructMember(pStructType, pItem->id)) { - String buf; - decodeToken(buf, pItem->id, false); - error("Duplicate struct member %s", buf.getUnwrapped()); - } - Type* pStructElement = createType(TY_PARAM, pItem, NULL); - size_t alignment = pGen->alignmentOf(pItem); - if (alignment > structAlignment) { - structAlignment = alignment; - } - size_t alignmentMask = alignment - 1; - offset = (offset + alignmentMask) & ~alignmentMask; - pStructElement->length = offset; - size_t size = pGen->sizeOf(pItem); - if (isStruct) { - offset += size; - structSize = offset; - } else { - if (size >= structSize) { - structSize = size; - } - } - *pParamHolder = pStructElement; - pParamHolder = &pStructElement->pTail; - accept(','); - } - skip(';'); - } else { - // Some sort of syntax error, skip token and keep trying - next(); - } - } - if (!fail) { - pStructType->pHead->length = structSize; - pStructType->pHead->alignment = structAlignment | (isStruct << 31); - } - skip('}'); - } - if (fail) { - pStructType = NULL; - } - return pStructType; - } - - Type* lookupStructMember(Type* pStruct, tokenid_t memberId) { - for(Type* pStructElement = pStruct->pHead->pTail; pStructElement; pStructElement = pStructElement->pTail) { - if (pStructElement->pHead->id == memberId) { - return pStructElement; - } - } - return NULL; - } - - Type* acceptDeclaration(Type* pType, bool nameAllowed, bool nameRequired) { - tokenid_t declName = 0; - bool reportFailure = false; - StorageClass storageClass = pType->storageClass; - pType = acceptDecl2(pType, declName, nameAllowed, - nameRequired, reportFailure); - if (declName) { - // Clone the parent type so we can set a unique ID - Type* pOldType = pType; - pType = createType(pType->tag, pType->pHead, pType->pTail); - *pType = *pOldType; - pType->id = declName; - pType->storageClass = storageClass; - } else if (nameRequired) { - error("Expected a variable name"); - } -#if 0 - fprintf(stderr, "Parsed a declaration: "); - printType(pType); -#endif - if (reportFailure) { - return NULL; - } - return pType; - } - - Type* expectDeclaration(Type* pBaseType) { - bool nameRequired = pBaseType->tag != TY_STRUCT; - Type* pType = acceptDeclaration(pBaseType, true, nameRequired); - if (! pType) { - error("Expected a declaration"); - } - return pType; - } - - /* Used for accepting types that appear in casts */ - Type* acceptCastTypeDeclaration() { - Type* pType = acceptPrimitiveType(false); - if (pType) { - pType = acceptDeclaration(pType, false, false); - } - return pType; - } - - Type* expectCastTypeDeclaration() { - Type* pType = acceptCastTypeDeclaration(); - if (! pType) { - error("Expected a declaration"); - } - return pType; - } - - Type* acceptDecl2(Type* pType, tokenid_t& declName, - bool nameAllowed, bool nameRequired, - bool& reportFailure) { - while (accept('*')) { - pType = createType(TY_POINTER, pType, NULL); - } - pType = acceptDecl3(pType, declName, nameAllowed, nameRequired, - reportFailure); - return pType; - } - - Type* acceptDecl3(Type* pType, tokenid_t& declName, - bool nameAllowed, bool nameRequired, - bool& reportFailure) { - // direct-dcl : - // name - // (dcl) - // direct-dcl() - // direct-dcl[] - Type* pNewHead = NULL; - if (accept('(')) { - pNewHead = acceptDecl2(pNewHead, declName, nameAllowed, - nameRequired, reportFailure); - skip(')'); - } else if ((declName = acceptSymbol()) != 0) { - if (nameAllowed == false && declName) { - error("Symbol %s not allowed here", nameof(declName)); - reportFailure = true; - } - } else if (nameRequired && ! declName) { - String temp; - decodeToken(temp, tok, true); - error("Expected name. Got %s", temp.getUnwrapped()); - reportFailure = true; - } - for(;;) { - if (accept('(')) { - // Function declaration - Type* pTail = acceptArgs(nameAllowed); - pType = createType(TY_FUNC, pType, pTail); - skip(')'); - } if (accept('[')) { - if (tok != ']') { - if (tok != TOK_NUM || tokc <= 0) { - error("Expected positive integer constant"); - } else { - Type* pDecayType = createPtrType(pType); - pType = createType(TY_ARRAY, pType, pDecayType); - pType->length = tokc; - } - next(); - } - skip(']'); - } else { - break; - } - } - - if (pNewHead) { - Type* pA = pNewHead; - while (pA->pHead) { - pA = pA->pHead; - } - pA->pHead = pType; - pType = pNewHead; - } - return pType; - } - - Type* acceptArgs(bool nameAllowed) { - Type* pHead = NULL; - Type* pTail = NULL; - for(;;) { - Type* pBaseArg = acceptPrimitiveType(false); - if (pBaseArg) { - Type* pArg = acceptDeclaration(pBaseArg, nameAllowed, false); - if (pArg) { - Type* pParam = createType(TY_PARAM, pArg, NULL); - if (!pHead) { - pHead = pParam; - pTail = pParam; - } else { - pTail->pTail = pParam; - pTail = pParam; - } - } - } - if (! accept(',')) { - break; - } - } - return pHead; - } - - Type* expectPrimitiveType(bool allowStorageClass) { - Type* pType = acceptPrimitiveType(allowStorageClass); - if (!pType) { - String buf; - decodeToken(buf, tok, true); - error("Expected a type, got %s", buf.getUnwrapped()); - } - return pType; - } - - void checkLVal() { - if (pGen->getR0ExpressionType() != ET_LVALUE) { - error("Expected an lvalue"); - } - } - - void addGlobalSymbol(Type* pDecl) { - tokenid_t t = pDecl->id; - VariableInfo* pVI = VI(t); - if(pVI && pVI->pAddress) { - reportDuplicate(t); - } - mGlobals.add(pDecl); - } - - void reportDuplicate(tokenid_t t) { - error("Duplicate definition of %s", nameof(t)); - } - - void addLocalSymbol(Type* pDecl) { - tokenid_t t = pDecl->id; - if (mLocals.isDefinedAtCurrentLevel(t)) { - reportDuplicate(t); - } - mLocals.add(pDecl); - } - - bool checkUndeclaredStruct(Type* pBaseType) { - if (pBaseType->tag == TY_STRUCT && pBaseType->length < 0) { - String temp; - decodeToken(temp, pBaseType->structTag, false); - error("Undeclared struct %s", temp.getUnwrapped()); - return true; - } - return false; - } - - void localDeclarations(Type* pBaseType) { - intptr_t a; - - while (pBaseType) { - while (tok != ';' && tok != EOF) { - Type* pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (!pDecl->id) { - break; - } - if (checkUndeclaredStruct(pDecl)) { - break; - } - addLocalSymbol(pDecl); - if (pDecl->tag == TY_FUNC) { - if (tok == '{') { - error("Nested functions are not allowed. Did you forget a '}' ?"); - break; - } - // Else it's a forward declaration of a function. - } else if (pDecl->storageClass != SC_TYPEDEF) { - int variableAddress = 0; - size_t alignment = pGen->alignmentOf(pDecl); - assert(alignment > 0); - size_t alignmentMask = ~ (alignment - 1); - size_t sizeOf = pGen->sizeOf(pDecl); - assert(sizeOf > 0); - loc = (loc + alignment - 1) & alignmentMask; - size_t alignedSize = (sizeOf + alignment - 1) & alignmentMask; - loc = loc + alignedSize; - variableAddress = -loc; - VI(pDecl->id)->pAddress = (void*) variableAddress; - if (accept('=')) { - /* assignment */ - pGen->leaR0(variableAddress, createPtrType(pDecl), ET_LVALUE); - pGen->pushR0(); - expr(); - pGen->forceR0RVal(); - pGen->storeR0ToTOS(); - } - } - if (tok == ',') - next(); - } - skip(';'); - pBaseType = acceptPrimitiveType(true); - } - } - - bool checkSymbol() { - return checkSymbol(tok); - } - - void decodeToken(String& buffer, tokenid_t token, bool quote) { - if (token == EOF ) { - buffer.printf("EOF"); - } else if (token == TOK_NUM) { - buffer.printf("numeric constant %d(0x%x)", tokc, tokc); - } else if (token == TOK_NUM_FLOAT) { - buffer.printf("numeric constant float %g", tokd); - } else if (token == TOK_NUM_DOUBLE) { - buffer.printf("numeric constant double %g", tokd); - } else if (token >= 0 && token < 256) { - if (token < 32) { - buffer.printf("'\\x%02x'", token); - } else { - buffer.printf("'%c'", token); - } - } else { - if (quote) { - if (token >= TOK_KEYWORD && token < TOK_SYMBOL) { - buffer.printf("keyword \"%s\"", nameof(token)); - } else { - buffer.printf("symbol \"%s\"", nameof(token)); - } - } else { - buffer.printf("%s", nameof(token)); - } - } - } - - void printToken(tokenid_t token) { - String buffer; - decodeToken(buffer, token, true); - fprintf(stderr, "%s\n", buffer.getUnwrapped()); - } - - bool checkSymbol(tokenid_t token) { - bool result = token >= TOK_SYMBOL; - if (!result) { - String temp; - decodeToken(temp, token, true); - error("Expected symbol. Got %s", temp.getUnwrapped()); - } - return result; - } - - tokenid_t acceptSymbol() { - tokenid_t result = 0; - if (tok >= TOK_SYMBOL) { - result = tok; - next(); - } - return result; - } - - void globalDeclarations() { - mpCurrentSymbolStack = &mGlobals; - while (tok != EOF) { - Type* pBaseType = expectPrimitiveType(true); - if (!pBaseType) { - break; - } - Type* pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (!pDecl->id) { - skip(';'); - continue; - } - - if (checkUndeclaredStruct(pDecl)) { - skip(';'); - continue; - } - if (! isDefined(pDecl->id)) { - addGlobalSymbol(pDecl); - } - VariableInfo* name = VI(pDecl->id); - if (name && name->pAddress) { - error("Already defined global %s", nameof(pDecl->id)); - } - if (pDecl->tag < TY_FUNC) { - // it's a variable declaration - for(;;) { - if (pDecl->storageClass == SC_TYPEDEF) { - // Do not allocate storage. - } else { - if (name && !name->pAddress) { - name->pAddress = (int*) allocGlobalSpace( - pGen->alignmentOf(name->pType), - pGen->sizeOf(name->pType)); - } - if (accept('=')) { - if (tok == TOK_NUM) { - if (name) { - * (int*) name->pAddress = tokc; - } - next(); - } else { - error("Expected an integer constant"); - } - } - } - if (!accept(',')) { - break; - } - pDecl = expectDeclaration(pBaseType); - if (!pDecl) { - break; - } - if (! isDefined(pDecl->id)) { - addGlobalSymbol(pDecl); - } - name = VI(pDecl->id); - } - skip(';'); - } else { - // Function declaration - if (accept(';')) { - // forward declaration. - } else if (tok != '{') { - error("expected '{'"); - } else { - mpCurrentArena = &mLocalArena; - mpCurrentSymbolStack = &mLocals; - if (name) { - /* patch forward references */ - pGen->resolveForward((int) name->pForward); - /* put function address */ - name->pAddress = (void*) pCodeBuf->getPC(); - } - // Calculate stack offsets for parameters - mLocals.pushLevel(); - intptr_t a = 8; - int argCount = 0; - for (Type* pP = pDecl->pTail; pP; pP = pP->pTail) { - Type* pArg = pP->pHead; - if (pArg->id) { - addLocalSymbol(pArg); - } - /* read param name and compute offset */ - Type* pPassingType = passingType(pArg); - size_t alignment = pGen->alignmentOf(pPassingType); - a = (a + alignment - 1) & ~ (alignment-1); - if (pArg->id) { - VI(pArg->id)->pAddress = (void*) a; - } - a = a + pGen->sizeOf(pPassingType); - argCount++; - } - rsym = loc = 0; - pReturnType = pDecl->pHead; - a = pGen->functionEntry(pDecl); - block(0, 0, true); - pGen->gsym(rsym); - pGen->functionExit(pDecl, a, loc); - mLocals.popLevel(); - mpCurrentArena = &mGlobalArena; - mpCurrentSymbolStack = &mGlobals; - } - } - } - } - - Type* passingType(Type* pType) { - switch (pType->tag) { - case TY_CHAR: - case TY_SHORT: - return mkpInt; - default: - return pType; - } - } - - char* allocGlobalSpace(size_t alignment, size_t bytes) { - size_t base = (((size_t) glo) + alignment - 1) & ~(alignment-1); - size_t end = base + bytes; - if ((end - (size_t) pGlobalBase) > (size_t) ALLOC_SIZE) { - error("Global space exhausted"); - assert(false); - return NULL; - } - char* result = (char*) base; - glo = (char*) end; - return result; - } - - void cleanup() { - if (pGlobalBase != 0) { - free(pGlobalBase); - pGlobalBase = 0; - } - if (pGen) { - delete pGen; - pGen = 0; - } - if (pCodeBuf) { - delete pCodeBuf; - pCodeBuf = 0; - } - if (file) { - delete file; - file = 0; - } - } - - // One-time initialization, when class is constructed. - void init() { - mpSymbolLookupFn = 0; - mpSymbolLookupContext = 0; - } - - void clear() { - tok = 0; - tokc = 0; - tokl = 0; - ch = 0; - rsym = 0; - loc = 0; - glo = 0; - macroLevel = -1; - file = 0; - pGlobalBase = 0; - pCodeBuf = 0; - pGen = 0; - mPragmaStringCount = 0; - mCompileResult = 0; - mLineNumber = 1; - mbBumpLine = false; - mbSuppressMacroExpansion = false; - } - - void setArchitecture(const char* architecture) { - delete pGen; - pGen = 0; - - delete pCodeBuf; - pCodeBuf = new CodeBuf(); - - if (architecture != NULL) { -#ifdef PROVIDE_ARM_CODEGEN - if (! pGen && strcmp(architecture, "arm") == 0) { - pGen = new ARMCodeGenerator(); - pCodeBuf = new ARMCodeBuf(pCodeBuf); - } -#endif -#ifdef PROVIDE_X86_CODEGEN - if (! pGen && strcmp(architecture, "x86") == 0) { - pGen = new X86CodeGenerator(); - } -#endif - if (!pGen ) { - error("Unknown architecture %s\n", architecture); - } - } - - if (pGen == NULL) { -#if defined(DEFAULT_ARM_CODEGEN) - pGen = new ARMCodeGenerator(); - pCodeBuf = new ARMCodeBuf(pCodeBuf); -#elif defined(DEFAULT_X86_CODEGEN) - pGen = new X86CodeGenerator(); -#endif - } - if (pGen == NULL) { - error("No code generator defined."); - } else { - pGen->setErrorSink(this); - pGen->setTypes(mkpInt); - } - } - -public: - struct args { - args() { - architecture = 0; - } - const char* architecture; - }; - - Compiler() { - init(); - clear(); - } - - ~Compiler() { - cleanup(); - } - - void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { - mpSymbolLookupFn = pFn; - mpSymbolLookupContext = pContext; - } - - int compile(const char* text, size_t textLength) { - int result; - - mpCurrentArena = &mGlobalArena; - createPrimitiveTypes(); - cleanup(); - clear(); - mTokenTable.setArena(&mGlobalArena); - mGlobals.setArena(&mGlobalArena); - mGlobals.setTokenTable(&mTokenTable); - mLocals.setArena(&mLocalArena); - mLocals.setTokenTable(&mTokenTable); - - internKeywords(); - setArchitecture(NULL); - if (!pGen) { - return -1; - } -#ifdef PROVIDE_TRACE_CODEGEN - pGen = new TraceCodeGenerator(pGen); -#endif - pGen->setErrorSink(this); - - if (pCodeBuf) { - pCodeBuf->init(ALLOC_SIZE); - } - pGen->init(pCodeBuf); - file = new TextInputStream(text, textLength); - pGlobalBase = (char*) calloc(1, ALLOC_SIZE); - glo = pGlobalBase; - inp(); - next(); - globalDeclarations(); - checkForUndefinedForwardReferences(); - result = pGen->finishCompile(); - if (result == 0) { - if (mErrorBuf.len()) { - result = -2; - } - } - mCompileResult = result; - return result; - } - - void createPrimitiveTypes() { - mkpInt = createType(TY_INT, NULL, NULL); - mkpShort = createType(TY_SHORT, NULL, NULL); - mkpChar = createType(TY_CHAR, NULL, NULL); - mkpVoid = createType(TY_VOID, NULL, NULL); - mkpFloat = createType(TY_FLOAT, NULL, NULL); - mkpDouble = createType(TY_DOUBLE, NULL, NULL); - mkpIntFn = createType(TY_FUNC, mkpInt, NULL); - mkpIntPtr = createPtrType(mkpInt); - mkpCharPtr = createPtrType(mkpChar); - mkpFloatPtr = createPtrType(mkpFloat); - mkpDoublePtr = createPtrType(mkpDouble); - mkpPtrIntFn = createPtrType(mkpIntFn); - } - - void checkForUndefinedForwardReferences() { - mGlobals.forEach(static_ufrcFn, this); - } - - static bool static_ufrcFn(VariableInfo* value, void* context) { - Compiler* pCompiler = (Compiler*) context; - return pCompiler->undefinedForwardReferenceCheck(value); - } - - bool undefinedForwardReferenceCheck(VariableInfo* value) { - if (!value->pAddress && value->pForward) { - error("Undefined forward reference: %s", - mTokenTable[value->tok].pText); - } - return true; - } - - /* Look through the symbol table to find a symbol. - * If found, return its value. - */ - void* lookup(const char* name) { - if (mCompileResult == 0) { - tokenid_t tok = mTokenTable.intern(name, strlen(name)); - VariableInfo* pVariableInfo = VI(tok); - if (pVariableInfo) { - return pVariableInfo->pAddress; - } - } - return NULL; - } - - void getPragmas(ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings) { - int stringCount = mPragmaStringCount; - if (actualStringCount) { - *actualStringCount = stringCount; - } - if (stringCount > maxStringCount) { - stringCount = maxStringCount; - } - if (strings) { - char* pPragmas = mPragmas.getUnwrapped(); - while (stringCount-- > 0) { - *strings++ = pPragmas; - pPragmas += strlen(pPragmas) + 1; - } - } - } - - void getProgramBinary(ACCvoid** base, ACCsizei* length) { - *base = pCodeBuf->getBase(); - *length = (ACCsizei) pCodeBuf->getSize(); - } - - char* getErrorMessage() { - return mErrorBuf.getUnwrapped(); - } -}; - -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 /* ~ ! */ - }; - -#ifdef PROVIDE_X86_CODEGEN -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 // ! -}; -#endif - -struct ACCscript { - ACCscript() { - text = 0; - textLength = 0; - accError = ACC_NO_ERROR; - } - - ~ACCscript() { - delete text; - } - - void registerSymbolCallback(ACCSymbolLookupFn pFn, ACCvoid* pContext) { - compiler.registerSymbolCallback(pFn, pContext); - } - - void setError(ACCenum error) { - if (accError == ACC_NO_ERROR && error != ACC_NO_ERROR) { - accError = error; - } - } - - ACCenum getError() { - ACCenum result = accError; - accError = ACC_NO_ERROR; - return result; - } - - 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 accRegisterSymbolCallback(ACCscript* script, ACCSymbolLookupFn pFn, - ACCvoid* pContext) { - script->registerSymbolCallback(pFn, pContext); -} - -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; - } - 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; - } - text[totalLength] = '\0'; - -#ifdef DEBUG_SAVE_INPUT_TO_FILE - LOGD("Saving input to file..."); - int counter; - char path[PATH_MAX]; - for (counter = 0; counter < 4096; counter++) { - sprintf(path, DEBUG_DUMP_PATTERN, counter); - if(access(path, F_OK) != 0) { - break; - } - } - if (counter < 4096) { - LOGD("Saving input to file %s", path); - FILE* fd = fopen(path, "w"); - if (fd) { - fwrite(text, totalLength, 1, fd); - fclose(fd); - LOGD("Saved input to file %s", path); - } else { - LOGD("Could not save. errno: %d", errno); - } - } -#endif -} - -extern "C" -void accCompileScript(ACCscript* script) { - int result = script->compiler.compile(script->text, script->textLength); - if (result) { - script->setError(ACC_INVALID_OPERATION); - } -} - -extern "C" -void accGetScriptiv(ACCscript* script, - ACCenum pname, - ACCint * params) { - switch (pname) { - case ACC_INFO_LOG_LENGTH: - *params = 0; - break; - } -} - -extern "C" -void accGetScriptInfoLog(ACCscript* script, - ACCsizei maxLength, - ACCsizei * length, - ACCchar * infoLog) { - char* message = script->compiler.getErrorMessage(); - int messageLength = strlen(message) + 1; - if (length) { - *length = messageLength; - } - if (infoLog && maxLength > 0) { - int trimmedLength = maxLength < messageLength ? - maxLength : messageLength; - memcpy(infoLog, message, trimmedLength); - infoLog[trimmedLength] = 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); - } -} - -extern "C" -void accGetPragmas(ACCscript* script, ACCsizei* actualStringCount, - ACCsizei maxStringCount, ACCchar** strings){ - script->compiler.getPragmas(actualStringCount, maxStringCount, strings); -} - -extern "C" -void accGetProgramBinary(ACCscript* script, - ACCvoid** base, ACCsizei* length) { - script->compiler.getProgramBinary(base, length); -} - - -} // namespace acc - diff --git a/libacc/tests/.gitignore b/libacc/tests/.gitignore deleted file mode 100644 index a26b298..0000000 --- a/libacc/tests/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -test-acc -*.out diff --git a/libacc/tests/Android.mk b/libacc/tests/Android.mk deleted file mode 100644 index 6ddfa74..0000000 --- a/libacc/tests/Android.mk +++ /dev/null @@ -1,75 +0,0 @@ -LOCAL_PATH:= $(call my-dir) - -# Executable for host -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= acc - -LOCAL_SRC_FILES:= \ - main.cpp - -LOCAL_STATIC_LIBRARIES := \ - libacc \ - libcutils - -LOCAL_LDLIBS := -ldl - - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_HOST_EXECUTABLE) - -# Executable for target -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= acc - -LOCAL_SRC_FILES:= \ - main.cpp \ - disassem.cpp - -LOCAL_SHARED_LIBRARIES := \ - libacc \ - libdl - -LOCAL_CFLAGS := -O0 -g - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) - -# Runtime tests for host -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= accRuntimeTest - -LOCAL_SRC_FILES:= \ - runtimeTest.cpp - -LOCAL_STATIC_LIBRARIES := \ - libacc \ - libcutils - -LOCAL_LDLIBS := -ldl - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_HOST_EXECUTABLE) - -# Runtime tests for target -# ======================================================== -include $(CLEAR_VARS) -LOCAL_MODULE:= accRuntimeTest - -LOCAL_SRC_FILES:= \ - runtimeTest.cpp - -LOCAL_SHARED_LIBRARIES := \ - libacc \ - libdl - -LOCAL_CFLAGS := -O0 -g - -LOCAL_MODULE_TAGS := tests - -include $(BUILD_EXECUTABLE) diff --git a/libacc/tests/accarm b/libacc/tests/accarm deleted file mode 100755 index 6b1bf66..0000000 --- a/libacc/tests/accarm +++ /dev/null @@ -1,69 +0,0 @@ -#!/usr/bin/python -# -# Run a test on the ARM version of acc. - -import unittest -import subprocess -import os -import sys - -def compile(args): - proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - result = proc.communicate() - return result - -def runCmd(args): - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result = proc.communicate() - return result[0].strip() - -def uname(): - return runCmd(["uname"]) - -def unameM(): - return runCmd(["uname", "-m"]) - -def which(item): - return runCmd(["which", item]) - -def adb(args): - return runCmd(["adb"] + args) - -def setupArm(file): - print "Setting up arm" - adb(["remount"]) - adb(["shell", "rm", "/system/bin/acc"]) - adb(["shell", "mkdir", "/system/bin/accdata"]) - adb(["shell", "mkdir", "/system/bin/accdata/data"]) - - remoteFileName = os.path.join("/system/bin/accdata", file) - adb(["push", file, remoteFileName]) - - # Copy over compiler - adb(["sync"]) - return remoteFileName - -def compileArm(args): - remoteArgs = [] - fileName = "" - for arg in sys.argv[1:]: - if arg.startswith('-'): - remoteArgs.append(arg) - else: - fileName = arg - - remoteFileName = setupArm(fileName) - remoteArgs.append(remoteFileName) - remoteCmdLine = ["adb", "shell", "/system/bin/acc"] + remoteArgs - proc = subprocess.Popen(remoteCmdLine, stdout=subprocess.PIPE) - result = proc.communicate() - return result[0].replace("\r","") - - -def main(): - print compileArm(sys.argv[1:]) - -if __name__ == '__main__': - main() - - diff --git a/libacc/tests/armreg.h b/libacc/tests/armreg.h deleted file mode 100644 index fde81ba..0000000 --- a/libacc/tests/armreg.h +++ /dev/null @@ -1,300 +0,0 @@ -/* $NetBSD: armreg.h,v 1.28 2003/10/31 16:30:15 scw Exp $ */ - -/*- - * Copyright (c) 1998, 2001 Ben Harris - * Copyright (c) 1994-1996 Mark Brinicombe. - * Copyright (c) 1994 Brini. - * All rights reserved. - * - * This code is derived from software written for Brini by Mark Brinicombe - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/armreg.h,v 1.3 2005/11/21 19:06:25 cognet Exp $ - */ - -#ifndef MACHINE_ARMREG_H -#define MACHINE_ARMREG_H -#define INSN_SIZE 4 -#define INSN_COND_MASK 0xf0000000 /* Condition mask */ -#define PSR_MODE 0x0000001f /* mode mask */ -#define PSR_USR26_MODE 0x00000000 -#define PSR_FIQ26_MODE 0x00000001 -#define PSR_IRQ26_MODE 0x00000002 -#define PSR_SVC26_MODE 0x00000003 -#define PSR_USR32_MODE 0x00000010 -#define PSR_FIQ32_MODE 0x00000011 -#define PSR_IRQ32_MODE 0x00000012 -#define PSR_SVC32_MODE 0x00000013 -#define PSR_ABT32_MODE 0x00000017 -#define PSR_UND32_MODE 0x0000001b -#define PSR_SYS32_MODE 0x0000001f -#define PSR_32_MODE 0x00000010 -#define PSR_FLAGS 0xf0000000 /* flags */ - -#define PSR_C_bit (1 << 29) /* carry */ - -/* The high-order byte is always the implementor */ -#define CPU_ID_IMPLEMENTOR_MASK 0xff000000 -#define CPU_ID_ARM_LTD 0x41000000 /* 'A' */ -#define CPU_ID_DEC 0x44000000 /* 'D' */ -#define CPU_ID_INTEL 0x69000000 /* 'i' */ -#define CPU_ID_TI 0x54000000 /* 'T' */ - -/* How to decide what format the CPUID is in. */ -#define CPU_ID_ISOLD(x) (((x) & 0x0000f000) == 0x00000000) -#define CPU_ID_IS7(x) (((x) & 0x0000f000) == 0x00007000) -#define CPU_ID_ISNEW(x) (!CPU_ID_ISOLD(x) && !CPU_ID_IS7(x)) - -/* On ARM3 and ARM6, this byte holds the foundry ID. */ -#define CPU_ID_FOUNDRY_MASK 0x00ff0000 -#define CPU_ID_FOUNDRY_VLSI 0x00560000 - -/* On ARM7 it holds the architecture and variant (sub-model) */ -#define CPU_ID_7ARCH_MASK 0x00800000 -#define CPU_ID_7ARCH_V3 0x00000000 -#define CPU_ID_7ARCH_V4T 0x00800000 -#define CPU_ID_7VARIANT_MASK 0x007f0000 - -/* On more recent ARMs, it does the same, but in a different format */ -#define CPU_ID_ARCH_MASK 0x000f0000 -#define CPU_ID_ARCH_V3 0x00000000 -#define CPU_ID_ARCH_V4 0x00010000 -#define CPU_ID_ARCH_V4T 0x00020000 -#define CPU_ID_ARCH_V5 0x00030000 -#define CPU_ID_ARCH_V5T 0x00040000 -#define CPU_ID_ARCH_V5TE 0x00050000 -#define CPU_ID_VARIANT_MASK 0x00f00000 - -/* Next three nybbles are part number */ -#define CPU_ID_PARTNO_MASK 0x0000fff0 - -/* Intel XScale has sub fields in part number */ -#define CPU_ID_XSCALE_COREGEN_MASK 0x0000e000 /* core generation */ -#define CPU_ID_XSCALE_COREREV_MASK 0x00001c00 /* core revision */ -#define CPU_ID_XSCALE_PRODUCT_MASK 0x000003f0 /* product number */ - -/* And finally, the revision number. */ -#define CPU_ID_REVISION_MASK 0x0000000f - -/* Individual CPUs are probably best IDed by everything but the revision. */ -#define CPU_ID_CPU_MASK 0xfffffff0 - -/* Fake CPU IDs for ARMs without CP15 */ -#define CPU_ID_ARM2 0x41560200 -#define CPU_ID_ARM250 0x41560250 - -/* Pre-ARM7 CPUs -- [15:12] == 0 */ -#define CPU_ID_ARM3 0x41560300 -#define CPU_ID_ARM600 0x41560600 -#define CPU_ID_ARM610 0x41560610 -#define CPU_ID_ARM620 0x41560620 - -/* ARM7 CPUs -- [15:12] == 7 */ -#define CPU_ID_ARM700 0x41007000 /* XXX This is a guess. */ -#define CPU_ID_ARM710 0x41007100 -#define CPU_ID_ARM7500 0x41027100 /* XXX This is a guess. */ -#define CPU_ID_ARM710A 0x41047100 /* inc ARM7100 */ -#define CPU_ID_ARM7500FE 0x41077100 -#define CPU_ID_ARM710T 0x41807100 -#define CPU_ID_ARM720T 0x41807200 -#define CPU_ID_ARM740T8K 0x41807400 /* XXX no MMU, 8KB cache */ -#define CPU_ID_ARM740T4K 0x41817400 /* XXX no MMU, 4KB cache */ - -/* Post-ARM7 CPUs */ -#define CPU_ID_ARM810 0x41018100 -#define CPU_ID_ARM920T 0x41129200 -#define CPU_ID_ARM920T_ALT 0x41009200 -#define CPU_ID_ARM922T 0x41029220 -#define CPU_ID_ARM940T 0x41029400 /* XXX no MMU */ -#define CPU_ID_ARM946ES 0x41049460 /* XXX no MMU */ -#define CPU_ID_ARM966ES 0x41049660 /* XXX no MMU */ -#define CPU_ID_ARM966ESR1 0x41059660 /* XXX no MMU */ -#define CPU_ID_ARM1020E 0x4115a200 /* (AKA arm10 rev 1) */ -#define CPU_ID_ARM1022ES 0x4105a220 -#define CPU_ID_SA110 0x4401a100 -#define CPU_ID_SA1100 0x4401a110 -#define CPU_ID_TI925T 0x54029250 -#define CPU_ID_SA1110 0x6901b110 -#define CPU_ID_IXP1200 0x6901c120 -#define CPU_ID_80200 0x69052000 -#define CPU_ID_PXA250 0x69052100 /* sans core revision */ -#define CPU_ID_PXA210 0x69052120 -#define CPU_ID_PXA250A 0x69052100 /* 1st version Core */ -#define CPU_ID_PXA210A 0x69052120 /* 1st version Core */ -#define CPU_ID_PXA250B 0x69052900 /* 3rd version Core */ -#define CPU_ID_PXA210B 0x69052920 /* 3rd version Core */ -#define CPU_ID_PXA250C 0x69052d00 /* 4th version Core */ -#define CPU_ID_PXA210C 0x69052d20 /* 4th version Core */ -#define CPU_ID_80321_400 0x69052420 -#define CPU_ID_80321_600 0x69052430 -#define CPU_ID_80321_400_B0 0x69052c20 -#define CPU_ID_80321_600_B0 0x69052c30 -#define CPU_ID_IXP425_533 0x690541c0 -#define CPU_ID_IXP425_400 0x690541d0 -#define CPU_ID_IXP425_266 0x690541f0 - -/* ARM3-specific coprocessor 15 registers */ -#define ARM3_CP15_FLUSH 1 -#define ARM3_CP15_CONTROL 2 -#define ARM3_CP15_CACHEABLE 3 -#define ARM3_CP15_UPDATEABLE 4 -#define ARM3_CP15_DISRUPTIVE 5 - -/* ARM3 Control register bits */ -#define ARM3_CTL_CACHE_ON 0x00000001 -#define ARM3_CTL_SHARED 0x00000002 -#define ARM3_CTL_MONITOR 0x00000004 - -/* - * Post-ARM3 CP15 registers: - * - * 1 Control register - * - * 2 Translation Table Base - * - * 3 Domain Access Control - * - * 4 Reserved - * - * 5 Fault Status - * - * 6 Fault Address - * - * 7 Cache/write-buffer Control - * - * 8 TLB Control - * - * 9 Cache Lockdown - * - * 10 TLB Lockdown - * - * 11 Reserved - * - * 12 Reserved - * - * 13 Process ID (for FCSE) - * - * 14 Reserved - * - * 15 Implementation Dependent - */ - -/* Some of the definitions below need cleaning up for V3/V4 architectures */ - -/* CPU control register (CP15 register 1) */ -#define CPU_CONTROL_MMU_ENABLE 0x00000001 /* M: MMU/Protection unit enable */ -#define CPU_CONTROL_AFLT_ENABLE 0x00000002 /* A: Alignment fault enable */ -#define CPU_CONTROL_DC_ENABLE 0x00000004 /* C: IDC/DC enable */ -#define CPU_CONTROL_WBUF_ENABLE 0x00000008 /* W: Write buffer enable */ -#define CPU_CONTROL_32BP_ENABLE 0x00000010 /* P: 32-bit exception handlers */ -#define CPU_CONTROL_32BD_ENABLE 0x00000020 /* D: 32-bit addressing */ -#define CPU_CONTROL_LABT_ENABLE 0x00000040 /* L: Late abort enable */ -#define CPU_CONTROL_BEND_ENABLE 0x00000080 /* B: Big-endian mode */ -#define CPU_CONTROL_SYST_ENABLE 0x00000100 /* S: System protection bit */ -#define CPU_CONTROL_ROM_ENABLE 0x00000200 /* R: ROM protection bit */ -#define CPU_CONTROL_CPCLK 0x00000400 /* F: Implementation defined */ -#define CPU_CONTROL_BPRD_ENABLE 0x00000800 /* Z: Branch prediction enable */ -#define CPU_CONTROL_IC_ENABLE 0x00001000 /* I: IC enable */ -#define CPU_CONTROL_VECRELOC 0x00002000 /* V: Vector relocation */ -#define CPU_CONTROL_ROUNDROBIN 0x00004000 /* RR: Predictable replacement */ -#define CPU_CONTROL_V4COMPAT 0x00008000 /* L4: ARMv4 compat LDR R15 etc */ - -#define CPU_CONTROL_IDC_ENABLE CPU_CONTROL_DC_ENABLE - -/* XScale Auxillary Control Register (CP15 register 1, opcode2 1) */ -#define XSCALE_AUXCTL_K 0x00000001 /* dis. write buffer coalescing */ -#define XSCALE_AUXCTL_P 0x00000002 /* ECC protect page table access */ -#define XSCALE_AUXCTL_MD_WB_RA 0x00000000 /* mini-D$ wb, read-allocate */ -#define XSCALE_AUXCTL_MD_WB_RWA 0x00000010 /* mini-D$ wb, read/write-allocate */ -#define XSCALE_AUXCTL_MD_WT 0x00000020 /* mini-D$ wt, read-allocate */ -#define XSCALE_AUXCTL_MD_MASK 0x00000030 - -/* Cache type register definitions */ -#define CPU_CT_ISIZE(x) ((x) & 0xfff) /* I$ info */ -#define CPU_CT_DSIZE(x) (((x) >> 12) & 0xfff) /* D$ info */ -#define CPU_CT_S (1U << 24) /* split cache */ -#define CPU_CT_CTYPE(x) (((x) >> 25) & 0xf) /* cache type */ - -#define CPU_CT_CTYPE_WT 0 /* write-through */ -#define CPU_CT_CTYPE_WB1 1 /* write-back, clean w/ read */ -#define CPU_CT_CTYPE_WB2 2 /* w/b, clean w/ cp15,7 */ -#define CPU_CT_CTYPE_WB6 6 /* w/b, cp15,7, lockdown fmt A */ -#define CPU_CT_CTYPE_WB7 7 /* w/b, cp15,7, lockdown fmt B */ - -#define CPU_CT_xSIZE_LEN(x) ((x) & 0x3) /* line size */ -#define CPU_CT_xSIZE_M (1U << 2) /* multiplier */ -#define CPU_CT_xSIZE_ASSOC(x) (((x) >> 3) & 0x7) /* associativity */ -#define CPU_CT_xSIZE_SIZE(x) (((x) >> 6) & 0x7) /* size */ - -/* Fault status register definitions */ - -#define FAULT_TYPE_MASK 0x0f -#define FAULT_USER 0x10 - -#define FAULT_WRTBUF_0 0x00 /* Vector Exception */ -#define FAULT_WRTBUF_1 0x02 /* Terminal Exception */ -#define FAULT_BUSERR_0 0x04 /* External Abort on Linefetch -- Section */ -#define FAULT_BUSERR_1 0x06 /* External Abort on Linefetch -- Page */ -#define FAULT_BUSERR_2 0x08 /* External Abort on Non-linefetch -- Section */ -#define FAULT_BUSERR_3 0x0a /* External Abort on Non-linefetch -- Page */ -#define FAULT_BUSTRNL1 0x0c /* External abort on Translation -- Level 1 */ -#define FAULT_BUSTRNL2 0x0e /* External abort on Translation -- Level 2 */ -#define FAULT_ALIGN_0 0x01 /* Alignment */ -#define FAULT_ALIGN_1 0x03 /* Alignment */ -#define FAULT_TRANS_S 0x05 /* Translation -- Section */ -#define FAULT_TRANS_P 0x07 /* Translation -- Page */ -#define FAULT_DOMAIN_S 0x09 /* Domain -- Section */ -#define FAULT_DOMAIN_P 0x0b /* Domain -- Page */ -#define FAULT_PERM_S 0x0d /* Permission -- Section */ -#define FAULT_PERM_P 0x0f /* Permission -- Page */ - -#define FAULT_IMPRECISE 0x400 /* Imprecise exception (XSCALE) */ - -/* - * Address of the vector page, low and high versions. - */ -#define ARM_VECTORS_LOW 0x00000000U -#define ARM_VECTORS_HIGH 0xffff0000U - -/* - * ARM Instructions - * - * 3 3 2 2 2 - * 1 0 9 8 7 0 - * +-------+-------------------------------------------------------+ - * | cond | instruction dependant | - * |c c c c| | - * +-------+-------------------------------------------------------+ - */ - -#define INSN_SIZE 4 /* Always 4 bytes */ -#define INSN_COND_MASK 0xf0000000 /* Condition mask */ -#define INSN_COND_AL 0xe0000000 /* Always condition */ - -#endif /* !MACHINE_ARMREG_H */ diff --git a/libacc/tests/data/addressOf.c b/libacc/tests/data/addressOf.c deleted file mode 100644 index e7acde5..0000000 --- a/libacc/tests/data/addressOf.c +++ /dev/null @@ -1,31 +0,0 @@ -void testStruct() { - struct str { - float x; - float y; - }; - - struct str base; - int index = 0; - - base.x = 10.0; - struct str *s = &base; - - float *v = &(*s).x; - float *v2 = &s[index].x; - printf("testStruct: %g %g %g\n",base.x, *v, *v2); -} - -void testArray() { - int a[2]; - a[0] = 1; - a[1] = 2; - int* p = &a[0]; - int* p2 = a; - printf("testArray: %d %d %d\n", a[0], *p, *p2); -} - -int main() { - testStruct(); - testArray(); - return 0; -} diff --git a/libacc/tests/data/array.c b/libacc/tests/data/array.c deleted file mode 100644 index ca4a728..0000000 --- a/libacc/tests/data/array.c +++ /dev/null @@ -1,107 +0,0 @@ -// Array allocation tests - -void testLocalInt() -{ - int a[3]; - a[0] = 1; - a[1] = 2; - a[2] = a[0] + a[1]; - printf("localInt: %d\n", a[2]); -} - -char a[3]; -double d[3]; - -void testGlobalChar() -{ - a[0] = 1; - a[1] = 2; - a[2] = a[0] + a[1]; - printf("globalChar: %d\n", a[2]); -} - -void testGlobalDouble() -{ - d[0] = 1; - d[1] = 2; - d[2] = d[0] + d[1]; - printf("globalDouble: %g\n", d[2]); -} - -void testLocalDouble() -{ - double d[3]; - float m[12]; - m[0] = 1.0f; - m[1] = 2.0f; - d[0] = 1.0; - d[1] = 2.0; - d[2] = d[0] + d[1]; - m[2] = m[0] + m[1]; - printf("localDouble: %g %g\n", d[2], m[2]); -} - -void vectorAdd(int* a, int* b, float* c, int len) { - int i; - for(i = 0; i < len; i++) { - c[i] = a[i] + b[i]; - } -} - -void testArgs() { - int a[3], b[3]; - float c[3]; - int i; - int len = 3; - for(i = 0; i < len; i++) { - a[i] = i; - b[i] = i; - c[i] = 0; - } - vectorAdd(a,b,c, len); - printf("testArgs:"); - for(i = 0; i < len; i++) { - printf(" %g", c[i]); - } - printf("\n"); -} - -void testDecay() { - char c[4]; - c[0] = 'H'; - c[1] = 'i'; - c[2] = '!'; - c[3] = 0; - printf("testDecay: %s\n", c); -} - -void test2D() { - char c[10][20]; - int x; - int y; - printf("test2D:\n"); - for(y = 0; y < 10; y++) { - for(x = 0; x < 20; x++) { - c[y][x] = 'a' + (15 & (y * 19 + x)); - } - } - for(y = 0; y < 10; y++) { - for(x = 0; x < 20; x++) { - printf("%c", c[y][x]); - } - printf("\n"); - } - -} - -int main() -{ - testLocalInt(); - testLocalDouble(); - testGlobalChar(); - testGlobalDouble(); - testArgs(); - testDecay(); - test2D(); - return 0; -} diff --git a/libacc/tests/data/assignment.c b/libacc/tests/data/assignment.c deleted file mode 100644 index 4fc7801..0000000 --- a/libacc/tests/data/assignment.c +++ /dev/null @@ -1,9 +0,0 @@ -int main() { - int a = 0; - int b = 1; - a = b = 2; // Test that "b = 2" generates an rvalue. - if (a = 7) { // Test that a = 7 generates an rvalue. - b = 3; - } - return a; -} diff --git a/libacc/tests/data/assignmentop.c b/libacc/tests/data/assignmentop.c deleted file mode 100644 index 649edf9..0000000 --- a/libacc/tests/data/assignmentop.c +++ /dev/null @@ -1,62 +0,0 @@ -// Test assignment operations - -void testAssignment() { - int a = 2; - a *= 5; - printf("2 *= 5 %d\n", a); - a = 20; - a /= 5; - printf("20 /= 5 %d\n", a); - a = 17; - a %= 5; - printf("17 %%= 5 %d\n", a); - a = 17; - a += 5; - printf("17 += 5 %d\n", a); - a = 17; - a-=5; - printf("17 -= 5 %d\n", a); - a = 17; - a<<=1; - printf("17<<= 1 %d\n", a); - a = 17; - a>>=1; - printf("17>>= 1 %d\n", a); - a = 17; - a&=1; - printf("17&= 1 %d\n", a); - a = 17; - a^=1; - printf("17^= 1 %d\n", a); - a = 16; - a^=1; - printf("16|= 1 %d\n", a); -} - -int a; - -int* f() { - printf("f()\n"); - return &a; -} - -void testEval() { - a = 0; - printf("*f() = *f() + 10;\n"); - *f() = *f() + 10; - printf("a = %d\n", a); -} - -void testOpEval() { - a = 0; - printf("*f() += 10;\n"); - *f() += 10; - printf("a = %d\n", a); -} - -int main() { - testAssignment(); - testEval(); - testOpEval(); - return 0; -} diff --git a/libacc/tests/data/b2071670.c b/libacc/tests/data/b2071670.c deleted file mode 100644 index 311bc4f..0000000 --- a/libacc/tests/data/b2071670.c +++ /dev/null @@ -1,9 +0,0 @@ -// See http://b/2071670 - -int main() { - float f = 10.0f; - float* floatPointer = &f; - // The following line used to incorrectly error: "Incompatible pointer or array types" - int* buffer = (int*) floatPointer; - return *buffer; -} diff --git a/libacc/tests/data/bellard.otccex.c b/libacc/tests/data/bellard.otccex.c deleted file mode 100644 index e8f0989..0000000 --- a/libacc/tests/data/bellard.otccex.c +++ /dev/null @@ -1,126 +0,0 @@ -/* #!/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/data/brackets.c b/libacc/tests/data/brackets.c deleted file mode 100644 index bab88a2..0000000 --- a/libacc/tests/data/brackets.c +++ /dev/null @@ -1,61 +0,0 @@ -void testBrackets(int* ar, int len) { - int i; - int errors = 0; - for (i = 0; i < len; i++) { - ar[i] = i; - } - for (i = 0; i < len; i++) { - if (ar[i] != i) { - printf("error: [%d] %d != %d\n", i, ar[i], i); - errors++; - } - } - printf("Errors: %d\n", errors); -} - -void testBrackets2D(int** ar2D, int lenX, int lenY) { - int x, y; - int errors = 0; - for (x = 0; x < lenX; x++) { - for (y = 0; y < lenY; y++) { - ar2D[x][y] = x * lenY + y; - } - } - for (x = 0; x < lenX; x++) { - for (y = 0; y < lenY; y++) { - int expected = x * lenY + y; - int val = ar2D[x][y]; - if (val != expected) { - printf("error: [%d][%d] %d != %d\n", x, y, val, expected); - errors++; - } - } - } - printf("2D Errors: %d\n", errors); -} - -void testHeap() { - int* ar = (int*) malloc(100); - testBrackets(ar, 25); - free(ar); -} - -void testHeap2D() { - int lenX = 10; - int lenY = 5; - int* ar = (int*) malloc(lenX * lenY * 4); - int** ar2D = (int**) malloc(lenX * 4); - int i; - for(i = 0; i < lenX; i++) { - ar2D[i] = ar + lenY * i; - } - testBrackets2D(ar2D, lenX, lenY); - free(ar); - free(ar2D); -} - -int main() { - testHeap(); - testHeap2D(); - return 0; -} diff --git a/libacc/tests/data/casts.c b/libacc/tests/data/casts.c deleted file mode 100644 index d3a49b4..0000000 --- a/libacc/tests/data/casts.c +++ /dev/null @@ -1,85 +0,0 @@ -void test1() { - int a = 3; - int* pb = &a; - int c = *pb; - printf("Reading from a pointer: %d %d\n", a, c); - *pb = 4; - printf("Writing to a pointer: %d\n", a); - printf("Testing casts: %d %g %g %d\n", 3, (float) 3, 4.5, (int) 4.5); -} - -void test2() { - int x = 4; - int px = &x; - // int z = * px; // An error, expected a pointer type - int y = * (int*) px; - printf("Testing reading (int*): %d\n", y); -} - -void test3() { - int px = (int) malloc(120); - * (int*) px = 8; - * (int*) (px + 4) = 9; - printf("Testing writing (int*): %d %d\n", * (int*) px, * (int*) (px + 4)); - free((void*) px); -} - -void test4() { - int x = 0x12345678; - int px = &x; - int a = * (char*) px; - int b = * (char*) (px + 1); - int c = * (char*) (px + 2); - int d = * (char*) (px + 3); - printf("Testing reading (char*): 0x%02x 0x%02x 0x%02x 0x%02x\n", a, b, c, d); -} - -void test5() { - int x = 0xFFFFFFFF; - int px = &x; - * (char*) px = 0x21; - * (char*) (px + 1) = 0x43; - * (char*) (px + 2) = 0x65; - * (char*) (px + 3) = 0x87; - printf("Testing writing (char*): 0x%08x\n", x); -} - -int f(int b) { - printf("f(%d)\n", b); - return 7 * b; -} - -void test6() { - int fp = &f; - int x = (*(int(*)()) fp)(10); - printf("Function pointer result: %d\n", x); -} - -void test7() { - int px = (int) malloc(120); - * (float*) px = 8.8f; - * (float*) (px + 4) = 9.9f; - printf("Testing read/write (float*): %g %g\n", * (float*) px, * (float*) (px + 4)); - free((void*) px); -} - -void test8() { - int px = (int) malloc(120); - * (double*) px = 8.8; - * (double*) (px + 8) = 9.9; - printf("Testing read/write (double*): %g %g\n", * (double*) px, * (double*) (px + 8)); - free((void*) px); -} - - -int main() { - test1(); - test2(); - test3(); - test4(); - test5(); - test6(); - test7(); - test8(); - return 0; -} diff --git a/libacc/tests/data/char.c b/libacc/tests/data/char.c deleted file mode 100644 index 8c63ba2..0000000 --- a/libacc/tests/data/char.c +++ /dev/null @@ -1,13 +0,0 @@ -char ga; -char gb; - -int main() { - char a = 'c'; - char b = a * 3; - printf("a = %d, b = %d\n", a, b); - ga = 'd'; - gb = ga * 3; - printf("ga = %d, gb = %d\n", ga, gb); - return 0; -} - diff --git a/libacc/tests/data/comma.c b/libacc/tests/data/comma.c deleted file mode 100644 index 496944c..0000000 --- a/libacc/tests/data/comma.c +++ /dev/null @@ -1,35 +0,0 @@ -int testReturn() { - return 10, 20, 30; -} - -int testArg(int a) { - return a; -} - -void testComma() { - int a; - 0, a = 10,20; - printf("statement: %d\n", a); - a = 1; - if (a = 0, 1) { - printf("if: a = %d\n", a); - } - int b = 0; - a = 10; - while(b++,a--) {} - printf("while: b = %d\n", b); - b = 0; - for(b++,a = 0;b++, a < 10; b++, a++) {} - printf("for: b = %d\n", b); - b = testReturn(); - printf("return: %d\n", b); - b = testArg((a,12)); - printf("arg: %d\n", b); -} - - - -int main() { - testComma(); - return 0; -} diff --git a/libacc/tests/data/constants.c b/libacc/tests/data/constants.c deleted file mode 100644 index 230109a..0000000 --- a/libacc/tests/data/constants.c +++ /dev/null @@ -1,30 +0,0 @@ -#define FOO 0x10 - -int main() { - printf("0 = %d\n", 0); - printf("010 = %d\n", 010); - printf("0x10 = %d\n", FOO); - printf("'\\a' = %d\n", '\a'); - printf("'\\b' = %d\n", '\b'); - printf("'\\f' = %d\n", '\f'); - printf("'\\n' = %d\n", '\n'); - printf("'\\r' = %d\n", '\r'); - printf("'\\t' = %d\n", '\t'); - printf("'\\v' = %d\n", '\v'); - // Undefined - // printf("'\\z' = %d\n", '\z'); - printf("'\\\\' = %d\n", '\\'); - printf("'\\'' = %d\n", '\''); - printf("'\\\"' = %d\n", '\"'); - printf("'\\?' = %d\n", '\?'); - printf("'\\0' = %d\n", '\0'); - printf("'\\1' = %d\n", '\1'); - printf("'\\12' = %d\n", '\12'); - printf("'\\123' = %d\n", '\123'); - printf("'\\x0' = %d\n", '\x0'); - printf("'\\x1' = %d\n", '\x1'); - printf("'\\x12' = %d\n", '\x12'); - printf("'\\x123' = %d\n", '\x123'); - printf("'\\x1f' = %d\n", '\x1f'); - printf("'\\x1F' = %d\n", '\x1F'); -} diff --git a/libacc/tests/data/continue.c b/libacc/tests/data/continue.c deleted file mode 100644 index d8b8e36..0000000 --- a/libacc/tests/data/continue.c +++ /dev/null @@ -1,13 +0,0 @@ -int main() { - int i, j, sum; - sum = 0; - for (i = 0; i < 10; i++) { - if (i & 1) continue; - for (j = 0; j < 10; j++) { - if (j & 1) continue; - sum += i * j; - } - } - return sum; -} - diff --git a/libacc/tests/data/defines.c b/libacc/tests/data/defines.c deleted file mode 100644 index 6cb6f7e..0000000 --- a/libacc/tests/data/defines.c +++ /dev/null @@ -1,9 +0,0 @@ -// Simple tests of the C preprocessor - -#define A 1 -#define A (4 / 2) -#define B 1 // This is a comment. With a / in it. - -int main() { - return A + B; -} diff --git a/libacc/tests/data/double.c b/libacc/tests/data/double.c deleted file mode 100644 index 5bc20a3..0000000 --- a/libacc/tests/data/double.c +++ /dev/null @@ -1,7 +0,0 @@ -double atof(char *nptr); - -int main() { - printf("Value = %g\n", atof("10.42")); - return 0; -} - diff --git a/libacc/tests/data/error.c b/libacc/tests/data/error.c deleted file mode 100644 index 2e08dcc..0000000 --- a/libacc/tests/data/error.c +++ /dev/null @@ -1,2 +0,0 @@ -void foo; - diff --git a/libacc/tests/data/expr-ansi.c b/libacc/tests/data/expr-ansi.c deleted file mode 100644 index d463659..0000000 --- a/libacc/tests/data/expr-ansi.c +++ /dev/null @@ -1,60 +0,0 @@ -/* Test operators */ - -void testInc() { int a, b; a = 3; b = a++; printf("3++ = %d %d\n", b, a); } -void testDec() { int a, b; a = 3; b = a--; printf("3-- = %d %d\n", b, a); } -void testTimes(){ printf("%d * %d = %d\n", 10, 4, 10 * 4); } -void testDiv(){ printf("%d / %d = %d\n", 11, 4, 11 / 4); } -void testMod(){ printf("%d %% %d = %d\n", 11, 4, 11 % 4); } -void testPlus(){ printf("%d + %d = %d\n", 10, 4, 10 + 4); } -void testMinus(){ printf("%d - %d = %d\n", 10, 4, 10 - 4); } -void testShiftLeft(){ printf("%d << %d = %d\n", 10, 4, 10 << 4); } -void testShiftRight(){ printf("%d >> %d = %d\n", 100, 4, 100 >> 4); } -void testLess(){ printf("%d < %d = %d\n", 10, 4, 10 < 4); } -void testLesEqual(){ printf("%d <= %d = %d\n", 10, 4, 10 <= 4); } -void testGreater(){ printf("%d > %d = %d\n", 10, 4, 10 > 4); } -void testGreaterEqual(){ printf("%d >= %d = %d\n", 10, 4, 10 >= 4); } -void testEqualTo(){ printf("%d == %d = %d\n", 10, 4, 10 == 4); } -void testNotEqualTo(){ printf("%d != %d = %d\n", 10, 4, 10 != 4); } -void testBitAnd(){ printf("%d & %d = %d\n", 10, 7, 10 & 7); } -void testBitXor(){ printf("%d ^ %d = %d\n", 10, 7, 10 ^ 7); } -void testBitOr(){ printf("%d | %d = %d\n", 10, 4, 10 | 4); } -void testAssignment(){ int a, b; a = 3; b = a; printf("b == %d\n", b); } -void testLogicalAnd(){ printf("%d && %d = %d\n", 10, 4, 10 && 4); } -void testLogicalOr(){ printf("%d || %d = %d\n", 10, 4, 10 || 4); } -void testAddressOf(){ int a; printf("&a is %d\n", &a); } -void testPointerIndirection(){ int a, b; a = &b; b = 17; printf("*%d = %d =?= %d\n", a, * (int*) a, b); } -void testNegation(){ printf("-%d = %d\n", 10, -10); } -void testUnaryPlus(){ printf("+%d = %d\n", 10, +10); } -void testUnaryNot(){ printf("!%d = %d\n", 10, !10); } -void testBitNot(){ printf("~%d = %d\n", 10, ~10); } - -int main(int a, char** 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; -} diff --git a/libacc/tests/data/expr.c b/libacc/tests/data/expr.c deleted file mode 100644 index 4f2d2e7..0000000 --- a/libacc/tests/data/expr.c +++ /dev/null @@ -1,60 +0,0 @@ -/* 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/data/expr2.c b/libacc/tests/data/expr2.c deleted file mode 100644 index 04b6a38..0000000 --- a/libacc/tests/data/expr2.c +++ /dev/null @@ -1,6 +0,0 @@ -/* Test operators */ - -main() { - int a; - a = a++; -} diff --git a/libacc/tests/data/film.c b/libacc/tests/data/film.c deleted file mode 100644 index 00c2d36..0000000 --- a/libacc/tests/data/film.c +++ /dev/null @@ -1,53 +0,0 @@ -// Test logical and bitwise AND and OR - -int test(int x, int y) { - int v = x || y; - return v; -} - -int test2(int x, int y) { - if(x | y) { - return 1; - } else { - return 0; - } -} - -int test3(int x, int y) { - int v = x && y; - return v; -} - -int test4(int x, int y) { - if(x & y) { - return 1; - } else { - return 0; - } -} - -int main(int index) -{ - int x,y; - printf("testing...\n"); - int totalBad = 0; - for(y = 0; y < 2; y++) { - for(x = 0; x < 2; x++) { - int a = test(x,y); - int b = test2(x,y); - if (a != b) { - printf("Results differ: OR x=%d y=%d a=%d b=%d\n", x, y, a, b); - totalBad++; - } - a = test3(x,y); - b = test4(x,y); - if (a != b) { - printf("Results differ: AND x=%d y=%d a=%d b=%d\n", x, y, a, b); - totalBad++; - } - } - } - printf("Total bad: %d\n", totalBad); - return 0; -} - diff --git a/libacc/tests/data/float.c b/libacc/tests/data/float.c deleted file mode 100644 index f48b3d1..0000000 --- a/libacc/tests/data/float.c +++ /dev/null @@ -1,57 +0,0 @@ -int ftoi(float f) { - return f; -} - -int dtoi(double d) { - return d; -} - -float itof(int i) { - return i; -} - -double itod(int i) { - return i; -} - -float f0, f1; -double d0, d1; - -void testParseConsts() { - printf("Constants: %g %g %g %g %g %g %g %g %g\n", 0e1, 0E1, 0.f, .01f, - .01e0f, 1.0e-1, 1.0e1, 1.0e+1, - .1f); -} -void testVars(float arg0, float arg1, double arg2, double arg3) { - float local0, local1; - double local2, local3; - f0 = arg0; - f1 = arg1; - d0 = arg2; - d1 = arg3; - local0 = arg0; - local1 = arg1; - local2 = arg2; - local3 = arg3; - printf("globals: %g %g %g %g\n", f0, f1, d0, d1); - printf("args: %g %g %g %g\n", arg0, arg1, arg2, arg3); - printf("locals: %g %g %g %g\n", local0, local1, local2, local3); - - - printf("cast rval: %g %g\n", * (float*) & f1, * (double*) & d1); - - * (float*) & f0 = 1.1f; - * (double*) & d0 = 3.3; - printf("cast lval: %g %g %g %g\n", f0, f1, d0, d1); -} - -int main() { - testParseConsts(); - printf("int: %d float: %g double: %g\n", 1, 2.2f, 3.3); - printf(" ftoi(1.4f)=%d\n", ftoi(1.4f)); - printf(" dtoi(2.4)=%d\n", dtoi(2.4)); - printf(" itof(3)=%g\n", itof(3)); - printf(" itod(4)=%g\n", itod(4)); - testVars(1.0f, 2.0f, 3.0, 4.0); - return 0; -} diff --git a/libacc/tests/data/floatdouble.c b/libacc/tests/data/floatdouble.c deleted file mode 100644 index 264c641..0000000 --- a/libacc/tests/data/floatdouble.c +++ /dev/null @@ -1,9 +0,0 @@ -int main() -{ - // Test coercing values when storing. - float a = 0.002; - double b = 0.1f; - int c = 10.002; - printf("%g %g %d\n", a, b, c); - return 0; -} diff --git a/libacc/tests/data/flops.c b/libacc/tests/data/flops.c deleted file mode 100644 index 40b1b28..0000000 --- a/libacc/tests/data/flops.c +++ /dev/null @@ -1,158 +0,0 @@ -// Test floating point operations. - -void unaryOps() { - // Unary ops - printf("-%g = %g\n", 1.1, -1.1); - printf("!%g = %d\n", 1.2, !1.2); - printf("!%g = %d\n", 0.0, !0.0); -} - -void binaryOps() { - printf("double op double:\n"); - printf("%g + %g = %g\n", 1.0, 2.0, 1.0 + 2.0); - printf("%g - %g = %g\n", 1.0, 2.0, 1.0 - 2.0); - printf("%g * %g = %g\n", 1.0, 2.0, 1.0 * 2.0); - printf("%g / %g = %g\n", 1.0, 2.0, 1.0 / 2.0); - - printf("float op float:\n"); - printf("%g + %g = %g\n", 1.0f, 2.0f, 1.0f + 2.0f); - printf("%g - %g = %g\n", 1.0f, 2.0f, 1.0f - 2.0f); - printf("%g * %g = %g\n", 1.0f, 2.0f, 1.0f * 2.0f); - printf("%g / %g = %g\n", 1.0f, 2.0f, 1.0f / 2.0f); - - printf("double op float:\n"); - printf("%g + %g = %g\n", 1.0, 2.0f, 1.0 + 2.0f); - printf("%g - %g = %g\n", 1.0, 2.0f, 1.0 - 2.0f); - printf("%g * %g = %g\n", 1.0, 2.0f, 1.0 * 2.0f); - printf("%g / %g = %g\n", 1.0, 2.0f, 1.0 / 2.0f); - - printf("double op int:\n"); - printf("%g + %d = %g\n", 1.0, 2, 1.0 + 2); - printf("%g - %d = %g\n", 1.0, 2, 1.0 - 2); - printf("%g * %d = %g\n", 1.0, 2, 1.0 * 2); - printf("%g / %d = %g\n", 1.0, 2, 1.0 / 2); - - printf("int op double:\n"); - printf("%d + %g = %g\n", 1, 2.0, 1 + 2.0); - printf("%d - %g = %g\n", 1, 2.0, 1 - 2.0); - printf("%d * %g = %g\n", 1, 2.0, 1 * 2.0); - printf("%d / %g = %g\n", 1, 2.0, 1 / 2.0); -} - -void comparisonTestdd(double a, double b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdd() { - printf("double op double:\n"); - comparisonTestdd(1.0, 2.0); - comparisonTestdd(1.0, 1.0); - comparisonTestdd(2.0, 1.0); -} - - -void comparisonTestdf(double a, float b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdf() { - printf("double op float:\n"); - comparisonTestdf(1.0, 2.0f); - comparisonTestdf(1.0, 1.0f); - comparisonTestdf(2.0, 1.0f); -} - -void comparisonTestff(float a, float b) { - printf("%g op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsff() { - printf("float op float:\n"); - comparisonTestff(1.0f, 2.0f); - comparisonTestff(1.0f, 1.0f); - comparisonTestff(2.0f, 1.0f); -} - -void comparisonTestid(int a, double b) { - printf("%d op %g: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsid() { - printf("int op double:\n"); - comparisonTestid(1, 2.0); - comparisonTestid(1, 1.0); - comparisonTestid(2, 1.0); -} -void comparisonTestdi(double a, int b) { - printf("%g op %d: < %d <= %d == %d >= %d > %d != %d\n", - a, b, a < b, a <= b, a == b, a >= b, a > b, a != b); -} - -void comparisonOpsdi() { - printf("double op int:\n"); - comparisonTestdi(1.0f, 2); - comparisonTestdi(1.0f, 1); - comparisonTestdi(2.0f, 1); -} - -void comparisonOps() { - comparisonOpsdd(); - comparisonOpsdf(); - comparisonOpsff(); - comparisonOpsid(); - comparisonOpsdi(); -} - -int branch(double d) { - if (d) { - return 1; - } - return 0; -} - -void testBranching() { - printf("branching: %d %d %d\n", branch(-1.0), branch(0.0), branch(1.0)); -} - -void testpassi(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j, int k, int l) { - printf("testpassi: %d %d %d %d %d %d %d %d %d %d %d %d\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassf(float a, float b, float c, float d, float e, float f, float g, float h, float i, float j, float k, float l) { - printf("testpassf: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassd(double a, double b, double c, double d, double e, double f, double g, double h, double i, double j, double k, double l) { - printf("testpassd: %g %g %g %g %g %g %g %g %g %g %g %g\n", a, b, c, d, e, f, g, h, i, j, k, l); -} - -void testpassidf(int i, double d, float f) { - printf("testpassidf: %d %g %g\n", i, d, f); -} - -void testParameterPassing() { - float x; - testpassi(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassf(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassd(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12); - testpassi(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassf(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassd(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, 8.0f, 9.0f, 10.0f, 11.0f, 12.0f); - testpassi(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassf(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassd(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0); - testpassidf(1, 2.0, 3.0f); -} - -int main() { - unaryOps(); - binaryOps(); - comparisonOps(); - testBranching(); - testParameterPassing(); - return 0; -} diff --git a/libacc/tests/data/funcargs.c b/libacc/tests/data/funcargs.c deleted file mode 100644 index 1dce226..0000000 --- a/libacc/tests/data/funcargs.c +++ /dev/null @@ -1,8 +0,0 @@ -int f(int a,int, int c) { - return a + c; -} - -int main() { - return f(1,2,3); -} - diff --git a/libacc/tests/data/hello.c b/libacc/tests/data/hello.c deleted file mode 100644 index 585ce6c..0000000 --- a/libacc/tests/data/hello.c +++ /dev/null @@ -1,3 +0,0 @@ -main(a,b) { - printf("Hello, world\n"); -} diff --git a/libacc/tests/data/inc.c b/libacc/tests/data/inc.c deleted file mode 100644 index 14c09d1..0000000 --- a/libacc/tests/data/inc.c +++ /dev/null @@ -1,14 +0,0 @@ -// Check integer operations - -int main() { - int a = 0; - printf("%d\n", a++); - printf("%d\n", a++); - printf("%d\n", a--); - printf("%d\n", a--); - printf("%d\n", ++a); - printf("%d\n", ++a); - printf("%d\n", --a); - printf("%d\n", --a); - return a; -} diff --git a/libacc/tests/data/iops.c b/libacc/tests/data/iops.c deleted file mode 100644 index 780e95d..0000000 --- a/libacc/tests/data/iops.c +++ /dev/null @@ -1,23 +0,0 @@ -// Check integer operations - -void loops() { - int y; - printf("++\n"); - for(y = 0; y < 10; y++) { - printf("%d\n", y); - } - printf("--\n"); - for(y = 10; y >= 0; y--) { - printf("%d\n", y); - } -} - -void checkLiterals() { - printf("Literals: %d %d\n", 1, -1); -} - -int main() { - checkLiterals(); - loops(); - return 0; -} diff --git a/libacc/tests/data/locals.c b/libacc/tests/data/locals.c deleted file mode 100644 index f1ef363..0000000 --- a/libacc/tests/data/locals.c +++ /dev/null @@ -1,71 +0,0 @@ -int a; - -int f() { - int a; - // Undefined variable b - // printf("f 0: a = %d b = %d\n", a, b); - printf("f 0: a = %d\n", a); - a = 2; - printf("f 1: a = %d\n", a); -} - -int g(int a) { - printf("g 0: a = %d\n", a); - a = 3; - printf("g 1: a = %d\n", a); -} - -int h(int a) { - // int a; // gcc 4.3 says error: 'a' redeclared as different kind of symbol - - printf("h 0: a = %d\n", a); - a = 4; - printf("h 1: a = %d\n", a); -} - -// Already defined global -// int h() {} -int globCheck() { - fprintf(stdout, "globCheck()\n"); -} - -int fwdCheck() { - b(); - // Undefined forward reference - // c(); -} - -int b() { - printf("b()\n"); -} - -int nested() { - int a; - printf("nested 0: a = %d\n", a); - a = 50; - printf("nested 1: a = %d\n", a); - { - int a; - printf("nested 2: a = %d\n", a); - a = 51; - printf("nested 3: a = %d\n", a); - } - printf("nested 4: a = %d\n", a); -} - -int main() { - globCheck(); - fwdCheck(); - printf("main 0: a = %d\n", a); - a = 5; - printf("main 1: a = %d\n", a); - f(); - printf("main 2: a = %d\n", a); - g(77); - printf("main 3: a = %d\n", a); - h(30); - printf("main 4: a = %d\n", a); - nested(); - printf("main 5: a = %d\n", a); - return 0; -} diff --git a/libacc/tests/data/macros.c b/libacc/tests/data/macros.c deleted file mode 100644 index 50e54dc..0000000 --- a/libacc/tests/data/macros.c +++ /dev/null @@ -1,10 +0,0 @@ -#define A B + B -#define B C - -int main() { - int C = 3; - printf("A = %d\n", A); -#define C 5 - printf("A = %d\n", A); - return 0; -} diff --git a/libacc/tests/data/missing-main.c b/libacc/tests/data/missing-main.c deleted file mode 100644 index e73eec4..0000000 --- a/libacc/tests/data/missing-main.c +++ /dev/null @@ -1,4 +0,0 @@ -/* No main. */ - -a() { -}
\ No newline at end of file diff --git a/libacc/tests/data/otcc-ansi.c b/libacc/tests/data/otcc-ansi.c deleted file mode 100644 index 72580e9..0000000 --- a/libacc/tests/data/otcc-ansi.c +++ /dev/null @@ -1,466 +0,0 @@ -// #include <stdio.h> -int d, z, C, h, P, K, ac, q, G, v, Q, R, D, L, W, M; - -void E(int e) { - *(char*) D++ = e; -} - -void o() { - if (L) { - h = *(char*) L++; - if (h == 2) { - L = 0; - h = W; - } - } else - h = fgetc(Q); -} - -int X() { - return isalnum(h) | h == 95; -} - -void Y() { - if (h == 92) { - o(); - if (h == 110) - h = 10; - } -} - -void ad() { - int e, j, m; - while (isspace(h) | h == 35) { - if (h == 35) { - o(); - ad(); - if (d == 536) { - ad(); - E(32); - *(int*) d = 1; - *(int*) (d + 4) = D; - } - while (h != 10) { - E(h); - o(); - } - E(h); - E(2); - } - o(); - } - C = 0; - d = h; - if (X()) { - E(32); - M = D; - while (X()) { - E(h); - o(); - } - if (isdigit(d)) { - z = strtol(M, 0, 0); - d = 2; - } else { - *(char*) D = 32; - d = strstr(R, M - 1) - R; - *(char*) D = 0; - d = d * 8 + 256; - if (d > 536) { - d = P + d; - if (*(int*) d == 1) { - L = *(int*) (d + 4); - W = h; - o(); - ad(); - } - } - } - } else { - o(); - if (d == 39) { - d = 2; - Y(); - z = h; - o(); - o(); - } else if (d == 47 & h == 42) { - o(); - while (h) { - while (h != 42) - o(); - o(); - if (h == 47) - h = 0; - } - o(); - ad(); - } else { - 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"; - while (j = *(char*) e++) { - m = *(char*) e++; - z = 0; - while ((C = *(char*) e++ - 98) < 0) - z = z * 64 + C + 64; - if (j == d & (m == h | m == 64)) { - if (m == h) { - o(); - d = 1; - } - break; - } - } - } - } -} - -void ae(int g) { - while( g&&g!=-1) { - *(char*) q++=g; - g=g>>8; - } -} - -void A(int e) { - int g; - while( e) { - g=*(int*) e; - *(int*) e=q-e-4; - e=g; - } -} - -int s(int g, int e) { - ae(g); - *(int*) q = e; - e = q; - q = q + 4; - return e; -} - -void H(int e) { - s(184,e); -} - -int B(int e) { - return s(233,e); -} - -int S(int j, int e) { - ae(1032325); - return s(132 + j, e); -} - -void Z(int e) { - ae( 49465); - H(0); - ae( 15); - ae( e+144); - ae( 192); -} - -void N(int j, int e) { - ae(j + 131); - s((e > -512 && e < 512) << 7 | 5, e); -} - -void T (int j) { - int g,e,m,aa; - g=1; - if( d == 34) { - H(v); - while( h!=34) { - Y (); - *(char*) v++=h; - o (); - } - *(char*) v=0; - v=v +4&-4; - o (); - ad(); - } - else { - aa=C; - m= z; - e=d; - ad(); - if( e == 2) { - H(m); - } - else if( aa == 2) { - T(0); - s(185,0); - if( e == 33)Z(m); - else ae( m); - } - else if( e == 40) { - w (); - ad(); - } - else if( e == 42) { - ad(); - e=d; - ad(); - ad(); - if( d == 42) { - ad(); - ad(); - ad(); - ad(); - e=0; - } - ad(); - T(0); - if( d == 61) { - ad(); - ae( 80); - w (); - ae( 89); - ae( 392+(e == 256)); - } - else if( e) { - if( e == 256)ae( 139); - else ae( 48655); - q++; - } - } - else if( e == 38) { - N(10,*(int*) d); - ad(); - } - else { - g=*(int*) e; - if(!g)g=dlsym(0,M); - if( d == 61&j) { - ad(); - w (); - N(6,g); - } - else if( d!= 40) { - N(8,g); - if( C == 11) { - N(0,g); - ae( z); - ad(); - } - } - } - } - if( d == 40) { - if( g == 1)ae( 80); - m= s(60545,0); - ad(); - j=0; - while( d!= 41) { - w (); - s(2393225,j); - if( d == 44)ad(); - j=j +4; - } - *(int*) m= j; - ad(); - if(!g) { - e=e +4; - *(int*) e=s(232,*(int*) e); - } - else if( g == 1) { - s(2397439,j); - j=j +4; - } - else { - s(232,g-q-5); - } - if( j)s(50305,j); - } -} - -void O (int j) { - int e,g,m; - if( j--== 1)T(1); - else { - O (j); - m= 0; - while( j == C) { - g=d; - e=z; - ad(); - if( j>8) { - m= S(e,m); - O (j); - } - else { - ae( 80); - O (j); - ae( 89); - if( j == 4|j == 5) { - Z(e); - } - else { - ae( e); - if( g == 37)ae( 146); - } - } - } - if( m&&j>8) { - m= S(e,m); - H(e^1); - B(5); - A(m); - H(e); - } - } -} - -void w() { - O(11); -} - -int U() { - w(); - return S(0, 0); -} - -void I (int j) { - int m,g,e; - if( d == 288) { - ad(); - ad(); - m= U (); - ad(); - I (j); - if( d == 312) { - ad(); - g=B(0); - A(m); - I (j); - A(g); - } - else { - A(m); - } - } - else if( d == 352|d == 504) { - e=d; - ad(); - ad(); - if( e == 352) { - g=q; - m= U (); - } - else { - if( d!= 59)w (); - ad(); - g=q; - m= 0; - if( d!= 59)m= U (); - ad(); - if( d!= 41) { - e=B(0); - w (); - B(g-q-5); - A(e); - g=e +4; - } - } - ad(); - I(&m); - B(g-q-5); - A(m); - } - else if( d == 123) { - ad(); - ab(1); - while( d!= 125)I (j); - ad(); - } - else { - if( d == 448) { - ad(); - if( d!= 59)w (); - K=B(K); - } - else if( d == 400) { - ad(); - *(int*) j=B(*(int*) j); - } - else if( d!= 59)w (); - ad(); - } -} - -void ab (int j) { - int m; - while( d == 256|d!=-1&!j) { - if( d == 256) { - ad(); - while( d!= 59) { - if( j) { - G=G +4; - *(int*) d=-G; - } - else { - *(int*) d=v; - v=v +4; - } - ad(); - if( d == 44)ad() ; - } - ad(); - } - else { - A(*(int*)(d +4)); - *(int*) d=q; - ad(); - ad(); - m= 8; - while( d!= 41) { - *(int*) d=m; - m= m +4; - ad(); - if( d == 44)ad(); - } - ad(); - K=G=0; - ae( 15042901); - m= s(60545,0); - I(0); - A(K); - ae( 50121); - *(int*) m= G; - } - } -} - -int run(int g, int e) { - return (*(int(*)()) *(int*) (P + 592))(g, e); -} - -int main(int g, int e) { - int result; - Q = stdin; - if (g-- > 1) { - e = e + 4; - Q = fopen(*(int*) e, "r"); - if (!Q) { - fprintf(stderr, "otcc-ansi.c: could not open file %s\n", *(int*) e); - return -2; - } - } - D = strcpy(R = calloc(1, 99999), " int if else while break return for define main ") + 48; - v = calloc(1, 99999); - q = ac = calloc(1, 99999); - P = calloc(1, 99999); - o(); - ad(); - ab(0); - if (mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7)) { - printf("Mprotect failed. %d\n", errno); - return -1; - } - fprintf(stderr, "otcc-ansi.c: About to execute compiled code:\n"); - result = run(g, e); - fprintf(stderr, "atcc-ansi.c: result: %d\n", result); - return result; -} - diff --git a/libacc/tests/data/otcc-noinclude.c b/libacc/tests/data/otcc-noinclude.c deleted file mode 100644 index 530f9e2..0000000 --- a/libacc/tests/data/otcc-noinclude.c +++ /dev/null @@ -1,446 +0,0 @@ -// #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/data/otcc.c b/libacc/tests/data/otcc.c deleted file mode 100644 index 433ae2e..0000000 --- a/libacc/tests/data/otcc.c +++ /dev/null @@ -1,448 +0,0 @@ -#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); -mprotect(ac & (~ 4095), (99999 + 4095) & (~ 4095), 7); -fprintf(stderr, "otcc.c: about to execute compiled code.\n"); -J(*(int(*)f)k(P+592))(g,n; -} - diff --git a/libacc/tests/data/pointers.c b/libacc/tests/data/pointers.c deleted file mode 100644 index 461ebeb..0000000 --- a/libacc/tests/data/pointers.c +++ /dev/null @@ -1,15 +0,0 @@ -int main() { - int* pa = (int*) malloc(100); - int* pb = pa + 1; - int* pc = (int*) 0; - *pa = 1; - *pb = 2; - printf("Pointer difference: %d %d\n", pb - pa, ((int) pb) - ((int) pa)); - int c = * (pa + 1); - printf("Pointer addition: %d\n", c); - printf("Pointer comparison to zero: %d %d %d\n", pa == 0, pb == 0, pc == 0); - printf("Pointer comparison: %d %d %d %d %d\n", pa < pb, pa == pb, pa > pb, ! pb, ! pc); - free(pa); - return 0; -} - diff --git a/libacc/tests/data/pointers2.c b/libacc/tests/data/pointers2.c deleted file mode 100644 index 69e402f..0000000 --- a/libacc/tests/data/pointers2.c +++ /dev/null @@ -1,35 +0,0 @@ -// Test multiple levels of indirection - -void testsingle() { - int a = 0; - int* pa = &a; - printf("a = %d, *pa = %d\n", a, *pa); - *pa = 2; - printf("a = %d, *pa = %d\n", a, *pa); -} - -void testdouble() { - int a = 0; - int* pa = &a; - int** ppa = &pa; - printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa); - **ppa = 2; - printf("a = %d, *pa = %d **ppa = %d\n", a, *pa, **ppa); -} - -void testtripple() { - int a = 0; - int* pa = &a; - int** ppa = &pa; - int*** pppa = &ppa; - printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa); - ***pppa = 2; - printf("a = %d, *pa = %d **ppa = %d\n ***pppa = %d", a, *pa, **ppa, ***pppa); -} - -int main() { - testsingle(); - testdouble(); - testdouble(); - return 0; -} diff --git a/libacc/tests/data/returnval-ansi.c b/libacc/tests/data/returnval-ansi.c deleted file mode 100644 index 6b53fd5..0000000 --- a/libacc/tests/data/returnval-ansi.c +++ /dev/null @@ -1,8 +0,0 @@ - -int main(int argc, char** argv) { - return f(); -} - -int f() { - return 42; -} diff --git a/libacc/tests/data/returnval.c b/libacc/tests/data/returnval.c deleted file mode 100644 index 1cf5bae..0000000 --- a/libacc/tests/data/returnval.c +++ /dev/null @@ -1,4 +0,0 @@ -main() { - return 42; -} - diff --git a/libacc/tests/data/rollo3.c b/libacc/tests/data/rollo3.c deleted file mode 100644 index b21c12f..0000000 --- a/libacc/tests/data/rollo3.c +++ /dev/null @@ -1,9 +0,0 @@ - -float fabsf(float); - -int main(void* con, int ft, int launchID) -{ - float f = fabsf(-10.0f); - return f; -} - diff --git a/libacc/tests/data/short.c b/libacc/tests/data/short.c deleted file mode 100644 index 5e222f3..0000000 --- a/libacc/tests/data/short.c +++ /dev/null @@ -1,6 +0,0 @@ -short a = 3; -int main() { - short* b = &a; - *b = *b - 5; - return a; -} diff --git a/libacc/tests/data/simplest.c b/libacc/tests/data/simplest.c deleted file mode 100644 index bae895a..0000000 --- a/libacc/tests/data/simplest.c +++ /dev/null @@ -1 +0,0 @@ -main() {} diff --git a/libacc/tests/data/structs.c b/libacc/tests/data/structs.c deleted file mode 100644 index dd81af3..0000000 --- a/libacc/tests/data/structs.c +++ /dev/null @@ -1,95 +0,0 @@ -// struct definition and declaration -struct a { - int a; - int b; -} c; - -// Useless, but legal struct declaration -struct { - int x; -}; - -// Useful anonymous struct declaration -struct { - int y; -} anon1, anon2; - -// forward declarations -struct a; -struct b; -struct c; - -struct b {int a; int b; }; - -// struct c {b g; }; // syntax error. - -// struct s {float c,a,b,c;} s; // duplicate struct member - -struct c {struct b g; }; - -// struct a { int w; }; // error - -void testCopying() { - struct a {int a[10]; char c;} a, b; - a.c = 37; - b.c = 38; - b = a; - printf("testCopying: %d == %d\n", a.c, b.c); -} - -void testUnion() { - union u; - union u {float f;int i;} u; - u.f = 1.0f; - printf("testUnion: %g == 0x%08x\n", u.f, u.i); -} - -struct v {float x, y, z, w; }; - -void add(struct v* result, struct v* a, struct v* b) { - result->x = a->x + b->x; - result->y = a->y + b->y; - result->z = a->z + b->z; - result->w = a->w + b->w; -} - -void set(struct v* v, float x, float y, float z, float w) { - v->x = x; - v->y = y; - v->z = z; - v->w = w; -} - -void print(struct v* v) { - printf("(%g, %g, %g, %g)\n", v->x, v->y, v->z, v->w); -} - -void testArgs() { - struct v a, b, c; - set(&a, 1.0f, 2.0f, 3.0f, 4.0f); - set(&b, 5.0f, 6.0f, 7.0f, 8.0f); - add(&c, &a, &b); - printf("testArgs: "); - print(&c); -} - -int main() { - anon1.y = 3; - anon2.y = anon1.y; - - testCopying(); - testUnion(); - testArgs(); - - struct c cc; - cc.g.a = 3; - c.a = 1; - c.b = 3; - struct a {int x, y; } z; - // struct a {int x, y; } z2; - z.x = c.a; - struct a *pA; - pA = &z; - pA->x += 5; - return pA->x; -} diff --git a/libacc/tests/data/testStringConcat.c b/libacc/tests/data/testStringConcat.c deleted file mode 100644 index bf06ae1..0000000 --- a/libacc/tests/data/testStringConcat.c +++ /dev/null @@ -1,4 +0,0 @@ -int main() { - return printf("Hello" "," " world\n"); -} - diff --git a/libacc/tests/data/typedef.c b/libacc/tests/data/typedef.c deleted file mode 100644 index c392f6a..0000000 --- a/libacc/tests/data/typedef.c +++ /dev/null @@ -1,40 +0,0 @@ -typedef short COORD; -typedef struct Point { - COORD x; - COORD y; -} Point; - -void add(Point* result, Point* a, Point* b) { - result->x = a->x + b->x; - result->y = a->y + b->y; -} - -void print(Point* p) { - printf("(%d, %d)", p->x, p->y); -} - -void set(Point* p, int x, int y) { - p->x = x; - p->y = y; -} - -int main() { - typedef char* String; - String s = "x = %d\n"; - { - typedef int item; - item x = 3; - printf(s, x); - } - Point a, b, c; - set(&a, 1,2); - set(&b, 3,4); - add(&c, &a, &b); - print(&c); - printf(" = "); - print(&a); - printf(" + "); - print(&b); - printf("\n"); - return 0; -} diff --git a/libacc/tests/disassem.cpp b/libacc/tests/disassem.cpp deleted file mode 100644 index ac35342..0000000 --- a/libacc/tests/disassem.cpp +++ /dev/null @@ -1,711 +0,0 @@ -/* $NetBSD: disassem.c,v 1.14 2003/03/27 16:58:36 mycroft Exp $ */ - -/*- - * Copyright (c) 1996 Mark Brinicombe. - * Copyright (c) 1996 Brini. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Brini. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRINI ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL BRINI OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * RiscBSD kernel project - * - * db_disasm.c - * - * Kernel disassembler - * - * Created : 10/02/96 - * - * Structured after the sparc/sparc/db_disasm.c by David S. Miller & - * Paul Kranenburg - * - * This code is not complete. Not all instructions are disassembled. - */ - -#include <sys/cdefs.h> -//__FBSDID("$FreeBSD: /repoman/r/ncvs/src/sys/arm/arm/disassem.c,v 1.2 2005/01/05 21:58:47 imp Exp $"); -#include <sys/param.h> -#include <stdio.h> -#include <stdarg.h> - -#include "disassem.h" -#include "armreg.h" -//#include <ddb/ddb.h> - -/* - * General instruction format - * - * insn[cc][mod] [operands] - * - * Those fields with an uppercase format code indicate that the field - * follows directly after the instruction before the separator i.e. - * they modify the instruction rather than just being an operand to - * the instruction. The only exception is the writeback flag which - * follows a operand. - * - * - * 2 - print Operand 2 of a data processing instruction - * d - destination register (bits 12-15) - * n - n register (bits 16-19) - * s - s register (bits 8-11) - * o - indirect register rn (bits 16-19) (used by swap) - * m - m register (bits 0-3) - * a - address operand of ldr/str instruction - * e - address operand of ldrh/strh instruction - * l - register list for ldm/stm instruction - * f - 1st fp operand (register) (bits 12-14) - * g - 2nd fp operand (register) (bits 16-18) - * h - 3rd fp operand (register/immediate) (bits 0-4) - * b - branch address - * t - thumb branch address (bits 24, 0-23) - * k - breakpoint comment (bits 0-3, 8-19) - * X - block transfer type - * Y - block transfer type (r13 base) - * c - comment field bits(0-23) - * p - saved or current status register - * F - PSR transfer fields - * D - destination-is-r15 (P) flag on TST, TEQ, CMP, CMN - * L - co-processor transfer size - * S - set status flag - * P - fp precision - * Q - fp precision (for ldf/stf) - * R - fp rounding - * v - co-processor data transfer registers + addressing mode - * W - writeback flag - * x - instruction in hex - * # - co-processor number - * y - co-processor data processing registers - * z - co-processor register transfer registers - */ - -struct arm32_insn { - u_int mask; - u_int pattern; - const char* name; - const char* format; -}; - -static const struct arm32_insn arm32_i[] = { - { 0x0fffffff, 0x0ff00000, "imb", "c" }, /* Before swi */ - { 0x0fffffff, 0x0ff00001, "imbrange", "c" }, /* Before swi */ - { 0x0f000000, 0x0f000000, "swi", "c" }, - { 0xfe000000, 0xfa000000, "blx", "t" }, /* Before b and bl */ - { 0x0f000000, 0x0a000000, "b", "b" }, - { 0x0f000000, 0x0b000000, "bl", "b" }, - { 0x0fe000f0, 0x00000090, "mul", "Snms" }, - { 0x0fe000f0, 0x00200090, "mla", "Snmsd" }, - { 0x0fe000f0, 0x00800090, "umull", "Sdnms" }, - { 0x0fe000f0, 0x00c00090, "smull", "Sdnms" }, - { 0x0fe000f0, 0x00a00090, "umlal", "Sdnms" }, - { 0x0fe000f0, 0x00e00090, "smlal", "Sdnms" }, - { 0x0d700000, 0x04200000, "strt", "daW" }, - { 0x0d700000, 0x04300000, "ldrt", "daW" }, - { 0x0d700000, 0x04600000, "strbt", "daW" }, - { 0x0d700000, 0x04700000, "ldrbt", "daW" }, - { 0x0c500000, 0x04000000, "str", "daW" }, - { 0x0c500000, 0x04100000, "ldr", "daW" }, - { 0x0c500000, 0x04400000, "strb", "daW" }, - { 0x0c500000, 0x04500000, "ldrb", "daW" }, - { 0x0e1f0000, 0x080d0000, "stm", "YnWl" },/* separate out r13 base */ - { 0x0e1f0000, 0x081d0000, "ldm", "YnWl" },/* separate out r13 base */ - { 0x0e100000, 0x08000000, "stm", "XnWl" }, - { 0x0e100000, 0x08100000, "ldm", "XnWl" }, - { 0x0e1000f0, 0x00100090, "ldrb", "deW" }, - { 0x0e1000f0, 0x00000090, "strb", "deW" }, - { 0x0e1000f0, 0x001000d0, "ldrsb", "deW" }, - { 0x0e1000f0, 0x001000b0, "ldrh", "deW" }, - { 0x0e1000f0, 0x000000b0, "strh", "deW" }, - { 0x0e1000f0, 0x001000f0, "ldrsh", "deW" }, - { 0x0f200090, 0x00200090, "und", "x" }, /* Before data processing */ - { 0x0e1000d0, 0x000000d0, "und", "x" }, /* Before data processing */ - { 0x0ff00ff0, 0x01000090, "swp", "dmo" }, - { 0x0ff00ff0, 0x01400090, "swpb", "dmo" }, - { 0x0fbf0fff, 0x010f0000, "mrs", "dp" }, /* Before data processing */ - { 0x0fb0fff0, 0x0120f000, "msr", "pFm" },/* Before data processing */ - { 0x0fb0f000, 0x0320f000, "msr", "pF2" },/* Before data processing */ - { 0x0ffffff0, 0x012fff10, "bx", "m" }, - { 0x0fff0ff0, 0x016f0f10, "clz", "dm" }, - { 0x0ffffff0, 0x012fff30, "blx", "m" }, - { 0xfff000f0, 0xe1200070, "bkpt", "k" }, - { 0x0de00000, 0x00000000, "and", "Sdn2" }, - { 0x0de00000, 0x00200000, "eor", "Sdn2" }, - { 0x0de00000, 0x00400000, "sub", "Sdn2" }, - { 0x0de00000, 0x00600000, "rsb", "Sdn2" }, - { 0x0de00000, 0x00800000, "add", "Sdn2" }, - { 0x0de00000, 0x00a00000, "adc", "Sdn2" }, - { 0x0de00000, 0x00c00000, "sbc", "Sdn2" }, - { 0x0de00000, 0x00e00000, "rsc", "Sdn2" }, - { 0x0df00000, 0x01100000, "tst", "Dn2" }, - { 0x0df00000, 0x01300000, "teq", "Dn2" }, - { 0x0df00000, 0x01500000, "cmp", "Dn2" }, - { 0x0df00000, 0x01700000, "cmn", "Dn2" }, - { 0x0de00000, 0x01800000, "orr", "Sdn2" }, - { 0x0de00000, 0x01a00000, "mov", "Sd2" }, - { 0x0de00000, 0x01c00000, "bic", "Sdn2" }, - { 0x0de00000, 0x01e00000, "mvn", "Sd2" }, - { 0x0ff08f10, 0x0e000100, "adf", "PRfgh" }, - { 0x0ff08f10, 0x0e100100, "muf", "PRfgh" }, - { 0x0ff08f10, 0x0e200100, "suf", "PRfgh" }, - { 0x0ff08f10, 0x0e300100, "rsf", "PRfgh" }, - { 0x0ff08f10, 0x0e400100, "dvf", "PRfgh" }, - { 0x0ff08f10, 0x0e500100, "rdf", "PRfgh" }, - { 0x0ff08f10, 0x0e600100, "pow", "PRfgh" }, - { 0x0ff08f10, 0x0e700100, "rpw", "PRfgh" }, - { 0x0ff08f10, 0x0e800100, "rmf", "PRfgh" }, - { 0x0ff08f10, 0x0e900100, "fml", "PRfgh" }, - { 0x0ff08f10, 0x0ea00100, "fdv", "PRfgh" }, - { 0x0ff08f10, 0x0eb00100, "frd", "PRfgh" }, - { 0x0ff08f10, 0x0ec00100, "pol", "PRfgh" }, - { 0x0f008f10, 0x0e000100, "fpbop", "PRfgh" }, - { 0x0ff08f10, 0x0e008100, "mvf", "PRfh" }, - { 0x0ff08f10, 0x0e108100, "mnf", "PRfh" }, - { 0x0ff08f10, 0x0e208100, "abs", "PRfh" }, - { 0x0ff08f10, 0x0e308100, "rnd", "PRfh" }, - { 0x0ff08f10, 0x0e408100, "sqt", "PRfh" }, - { 0x0ff08f10, 0x0e508100, "log", "PRfh" }, - { 0x0ff08f10, 0x0e608100, "lgn", "PRfh" }, - { 0x0ff08f10, 0x0e708100, "exp", "PRfh" }, - { 0x0ff08f10, 0x0e808100, "sin", "PRfh" }, - { 0x0ff08f10, 0x0e908100, "cos", "PRfh" }, - { 0x0ff08f10, 0x0ea08100, "tan", "PRfh" }, - { 0x0ff08f10, 0x0eb08100, "asn", "PRfh" }, - { 0x0ff08f10, 0x0ec08100, "acs", "PRfh" }, - { 0x0ff08f10, 0x0ed08100, "atn", "PRfh" }, - { 0x0f008f10, 0x0e008100, "fpuop", "PRfh" }, - { 0x0e100f00, 0x0c000100, "stf", "QLv" }, - { 0x0e100f00, 0x0c100100, "ldf", "QLv" }, - { 0x0ff00f10, 0x0e000110, "flt", "PRgd" }, - { 0x0ff00f10, 0x0e100110, "fix", "PRdh" }, - { 0x0ff00f10, 0x0e200110, "wfs", "d" }, - { 0x0ff00f10, 0x0e300110, "rfs", "d" }, - { 0x0ff00f10, 0x0e400110, "wfc", "d" }, - { 0x0ff00f10, 0x0e500110, "rfc", "d" }, - { 0x0ff0ff10, 0x0e90f110, "cmf", "PRgh" }, - { 0x0ff0ff10, 0x0eb0f110, "cnf", "PRgh" }, - { 0x0ff0ff10, 0x0ed0f110, "cmfe", "PRgh" }, - { 0x0ff0ff10, 0x0ef0f110, "cnfe", "PRgh" }, - { 0xff100010, 0xfe000010, "mcr2", "#z" }, - { 0x0f100010, 0x0e000010, "mcr", "#z" }, - { 0xff100010, 0xfe100010, "mrc2", "#z" }, - { 0x0f100010, 0x0e100010, "mrc", "#z" }, - { 0xff000010, 0xfe000000, "cdp2", "#y" }, - { 0x0f000010, 0x0e000000, "cdp", "#y" }, - { 0xfe100090, 0xfc100000, "ldc2", "L#v" }, - { 0x0e100090, 0x0c100000, "ldc", "L#v" }, - { 0xfe100090, 0xfc000000, "stc2", "L#v" }, - { 0x0e100090, 0x0c000000, "stc", "L#v" }, - { 0xf550f000, 0xf550f000, "pld", "ne" }, - { 0x0ff00ff0, 0x01000050, "qaad", "dmn" }, - { 0x0ff00ff0, 0x01400050, "qdaad", "dmn" }, - { 0x0ff00ff0, 0x01600050, "qdsub", "dmn" }, - { 0x0ff00ff0, 0x01200050, "dsub", "dmn" }, - { 0x0ff000f0, 0x01000080, "smlabb", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000a0, "smlatb", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000c0, "smlabt", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x010000e0, "smlatt", "nmsd" }, // d & n inverted!! - { 0x0ff000f0, 0x01400080, "smlalbb","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000a0, "smlaltb","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000c0, "smlalbt","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x014000e0, "smlaltt","ndms" }, // d & n inverted!! - { 0x0ff000f0, 0x01200080, "smlawb", "nmsd" }, // d & n inverted!! - { 0x0ff0f0f0, 0x012000a0, "smulwb","nms" }, // d & n inverted!! - { 0x0ff000f0, 0x012000c0, "smlawt", "nmsd" }, // d & n inverted!! - { 0x0ff0f0f0, 0x012000e0, "smulwt","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x01600080, "smulbb","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000a0, "smultb","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000c0, "smulbt","nms" }, // d & n inverted!! - { 0x0ff0f0f0, 0x016000e0, "smultt","nms" }, // d & n inverted!! - { 0x00000000, 0x00000000, NULL, NULL } -}; - -static char const arm32_insn_conditions[][4] = { - "eq", "ne", "cs", "cc", - "mi", "pl", "vs", "vc", - "hi", "ls", "ge", "lt", - "gt", "le", "", "nv" -}; - -static char const insn_block_transfers[][4] = { - "da", "ia", "db", "ib" -}; - -static char const insn_stack_block_transfers[][4] = { - "ed", "ea", "fd", "fa" -}; - -static char const op_shifts[][4] = { - "lsl", "lsr", "asr", "ror" -}; - -static char const insn_fpa_rounding[][2] = { - "", "p", "m", "z" -}; - -static char const insn_fpa_precision[][2] = { - "s", "d", "e", "p" -}; - -static char const insn_fpaconstants[][8] = { - "0.0", "1.0", "2.0", "3.0", - "4.0", "5.0", "0.5", "10.0" -}; - -#define insn_condition(x) arm32_insn_conditions[(x >> 28) & 0x0f] -#define insn_blktrans(x) insn_block_transfers[(x >> 23) & 3] -#define insn_stkblktrans(x) insn_stack_block_transfers[(x >> 23) & 3] -#define op2_shift(x) op_shifts[(x >> 5) & 3] -#define insn_fparnd(x) insn_fpa_rounding[(x >> 5) & 0x03] -#define insn_fpaprec(x) insn_fpa_precision[(((x >> 18) & 2)|(x >> 7)) & 1] -#define insn_fpaprect(x) insn_fpa_precision[(((x >> 21) & 2)|(x >> 15)) & 1] -#define insn_fpaimm(x) insn_fpaconstants[x & 0x07] - -/* Local prototypes */ -static void disasm_register_shift(const disasm_interface_t *di, u_int insn); -static void disasm_print_reglist(const disasm_interface_t *di, u_int insn); -static void disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, - u_int loc); -static void disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, - u_int loc); -static void disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, - u_int loc); -static u_int disassemble_readword(u_int address); -static void disassemble_printaddr(u_int address); - -u_int -disasm(const disasm_interface_t *di, u_int loc, int altfmt) -{ - const struct arm32_insn *i_ptr = &arm32_i[0]; - - u_int insn; - int matchp; - int branch; - const char* f_ptr; - int fmt; - - fmt = 0; - matchp = 0; - insn = di->di_readword(loc); - -/* di->di_printf("loc=%08x insn=%08x : ", loc, insn);*/ - - while (i_ptr->name) { - if ((insn & i_ptr->mask) == i_ptr->pattern) { - matchp = 1; - break; - } - i_ptr++; - } - - if (!matchp) { - di->di_printf("und%s\t%08x\n", insn_condition(insn), insn); - return(loc + INSN_SIZE); - } - - /* If instruction forces condition code, don't print it. */ - if ((i_ptr->mask & 0xf0000000) == 0xf0000000) - di->di_printf("%s", i_ptr->name); - else - di->di_printf("%s%s", i_ptr->name, insn_condition(insn)); - - f_ptr = i_ptr->format; - - /* Insert tab if there are no instruction modifiers */ - - if (*(f_ptr) < 'A' || *(f_ptr) > 'Z') { - ++fmt; - di->di_printf("\t"); - } - - while (*f_ptr) { - switch (*f_ptr) { - /* 2 - print Operand 2 of a data processing instruction */ - case '2': - if (insn & 0x02000000) { - int rotate= ((insn >> 7) & 0x1e); - - di->di_printf("#0x%08x", - (insn & 0xff) << (32 - rotate) | - (insn & 0xff) >> rotate); - } else { - disasm_register_shift(di, insn); - } - break; - /* d - destination register (bits 12-15) */ - case 'd': - di->di_printf("r%d", ((insn >> 12) & 0x0f)); - break; - /* D - insert 'p' if Rd is R15 */ - case 'D': - if (((insn >> 12) & 0x0f) == 15) - di->di_printf("p"); - break; - /* n - n register (bits 16-19) */ - case 'n': - di->di_printf("r%d", ((insn >> 16) & 0x0f)); - break; - /* s - s register (bits 8-11) */ - case 's': - di->di_printf("r%d", ((insn >> 8) & 0x0f)); - break; - /* o - indirect register rn (bits 16-19) (used by swap) */ - case 'o': - di->di_printf("[r%d]", ((insn >> 16) & 0x0f)); - break; - /* m - m register (bits 0-4) */ - case 'm': - di->di_printf("r%d", ((insn >> 0) & 0x0f)); - break; - /* a - address operand of ldr/str instruction */ - case 'a': - disasm_insn_ldrstr(di, insn, loc); - break; - /* e - address operand of ldrh/strh instruction */ - case 'e': - disasm_insn_ldrhstrh(di, insn, loc); - break; - /* l - register list for ldm/stm instruction */ - case 'l': - disasm_print_reglist(di, insn); - break; - /* f - 1st fp operand (register) (bits 12-14) */ - case 'f': - di->di_printf("f%d", (insn >> 12) & 7); - break; - /* g - 2nd fp operand (register) (bits 16-18) */ - case 'g': - di->di_printf("f%d", (insn >> 16) & 7); - break; - /* h - 3rd fp operand (register/immediate) (bits 0-4) */ - case 'h': - if (insn & (1 << 3)) - di->di_printf("#%s", insn_fpaimm(insn)); - else - di->di_printf("f%d", insn & 7); - break; - /* b - branch address */ - case 'b': - branch = ((insn << 2) & 0x03ffffff); - if (branch & 0x02000000) - branch |= 0xfc000000; - di->di_printaddr(loc + 8 + branch); - break; - /* t - blx address */ - case 't': - branch = ((insn << 2) & 0x03ffffff) | - (insn >> 23 & 0x00000002); - if (branch & 0x02000000) - branch |= 0xfc000000; - di->di_printaddr(loc + 8 + branch); - break; - /* X - block transfer type */ - case 'X': - di->di_printf("%s", insn_blktrans(insn)); - break; - /* Y - block transfer type (r13 base) */ - case 'Y': - di->di_printf("%s", insn_stkblktrans(insn)); - break; - /* c - comment field bits(0-23) */ - case 'c': - di->di_printf("0x%08x", (insn & 0x00ffffff)); - break; - /* k - breakpoint comment (bits 0-3, 8-19) */ - case 'k': - di->di_printf("0x%04x", - (insn & 0x000fff00) >> 4 | (insn & 0x0000000f)); - break; - /* p - saved or current status register */ - case 'p': - if (insn & 0x00400000) - di->di_printf("spsr"); - else - di->di_printf("cpsr"); - break; - /* F - PSR transfer fields */ - case 'F': - di->di_printf("_"); - if (insn & (1 << 16)) - di->di_printf("c"); - if (insn & (1 << 17)) - di->di_printf("x"); - if (insn & (1 << 18)) - di->di_printf("s"); - if (insn & (1 << 19)) - di->di_printf("f"); - break; - /* B - byte transfer flag */ - case 'B': - if (insn & 0x00400000) - di->di_printf("b"); - break; - /* L - co-processor transfer size */ - case 'L': - if (insn & (1 << 22)) - di->di_printf("l"); - break; - /* S - set status flag */ - case 'S': - if (insn & 0x00100000) - di->di_printf("s"); - break; - /* P - fp precision */ - case 'P': - di->di_printf("%s", insn_fpaprec(insn)); - break; - /* Q - fp precision (for ldf/stf) */ - case 'Q': - break; - /* R - fp rounding */ - case 'R': - di->di_printf("%s", insn_fparnd(insn)); - break; - /* W - writeback flag */ - case 'W': - if (insn & (1 << 21)) - di->di_printf("!"); - break; - /* # - co-processor number */ - case '#': - di->di_printf("p%d", (insn >> 8) & 0x0f); - break; - /* v - co-processor data transfer registers+addressing mode */ - case 'v': - disasm_insn_ldcstc(di, insn, loc); - break; - /* x - instruction in hex */ - case 'x': - di->di_printf("0x%08x", insn); - break; - /* y - co-processor data processing registers */ - case 'y': - di->di_printf("%d, ", (insn >> 20) & 0x0f); - - di->di_printf("c%d, c%d, c%d", (insn >> 12) & 0x0f, - (insn >> 16) & 0x0f, insn & 0x0f); - - di->di_printf(", %d", (insn >> 5) & 0x07); - break; - /* z - co-processor register transfer registers */ - case 'z': - di->di_printf("%d, ", (insn >> 21) & 0x07); - di->di_printf("r%d, c%d, c%d, %d", - (insn >> 12) & 0x0f, (insn >> 16) & 0x0f, - insn & 0x0f, (insn >> 5) & 0x07); - -/* if (((insn >> 5) & 0x07) != 0) - di->di_printf(", %d", (insn >> 5) & 0x07);*/ - break; - default: - di->di_printf("[%c - unknown]", *f_ptr); - break; - } - if (*(f_ptr+1) >= 'A' && *(f_ptr+1) <= 'Z') - ++f_ptr; - else if (*(++f_ptr)) { - ++fmt; - if (fmt == 1) - di->di_printf("\t"); - else - di->di_printf(", "); - } - }; - - di->di_printf("\n"); - - return(loc + INSN_SIZE); -} - - -static void -disasm_register_shift(const disasm_interface_t *di, u_int insn) -{ - di->di_printf("r%d", (insn & 0x0f)); - if ((insn & 0x00000ff0) == 0) - ; - else if ((insn & 0x00000ff0) == 0x00000060) - di->di_printf(", rrx"); - else { - if (insn & 0x10) - di->di_printf(", %s r%d", op2_shift(insn), - (insn >> 8) & 0x0f); - else - di->di_printf(", %s #%d", op2_shift(insn), - (insn >> 7) & 0x1f); - } -} - - -static void -disasm_print_reglist(const disasm_interface_t *di, u_int insn) -{ - int loop; - int start; - int comma; - - di->di_printf("{"); - start = -1; - comma = 0; - - for (loop = 0; loop < 17; ++loop) { - if (start != -1) { - if (loop == 16 || !(insn & (1 << loop))) { - if (comma) - di->di_printf(", "); - else - comma = 1; - if (start == loop - 1) - di->di_printf("r%d", start); - else - di->di_printf("r%d-r%d", start, loop - 1); - start = -1; - } - } else { - if (insn & (1 << loop)) - start = loop; - } - } - di->di_printf("}"); - - if (insn & (1 << 22)) - di->di_printf("^"); -} - -static void -disasm_insn_ldrstr(const disasm_interface_t *di, u_int insn, u_int loc) -{ - int offset; - - offset = insn & 0xfff; - if ((insn & 0x032f0000) == 0x010f0000) { - /* rA = pc, immediate index */ - if (insn & 0x00800000) - loc += offset; - else - loc -= offset; - di->di_printaddr(loc + 8); - } else { - di->di_printf("[r%d", (insn >> 16) & 0x0f); - if ((insn & 0x03000fff) != 0x01000000) { - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - if (!(insn & 0x00800000)) - di->di_printf("-"); - if (insn & (1 << 25)) - disasm_register_shift(di, insn); - else - di->di_printf("#0x%03x", offset); - } - if (insn & (1 << 24)) - di->di_printf("]"); - } -} - -static void -disasm_insn_ldrhstrh(const disasm_interface_t *di, u_int insn, u_int loc) -{ - int offset; - - offset = ((insn & 0xf00) >> 4) | (insn & 0xf); - if ((insn & 0x004f0000) == 0x004f0000) { - /* rA = pc, immediate index */ - if (insn & 0x00800000) - loc += offset; - else - loc -= offset; - di->di_printaddr(loc + 8); - } else { - di->di_printf("[r%d", (insn >> 16) & 0x0f); - if ((insn & 0x01400f0f) != 0x01400000) { - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - if (!(insn & 0x00800000)) - di->di_printf("-"); - if (insn & (1 << 22)) - di->di_printf("#0x%02x", offset); - else - di->di_printf("r%d", (insn & 0x0f)); - } - if (insn & (1 << 24)) - di->di_printf("]"); - } -} - -static void -disasm_insn_ldcstc(const disasm_interface_t *di, u_int insn, u_int loc) -{ - if (((insn >> 8) & 0xf) == 1) - di->di_printf("f%d, ", (insn >> 12) & 0x07); - else - di->di_printf("c%d, ", (insn >> 12) & 0x0f); - - di->di_printf("[r%d", (insn >> 16) & 0x0f); - - di->di_printf("%s, ", (insn & (1 << 24)) ? "" : "]"); - - if (!(insn & (1 << 23))) - di->di_printf("-"); - - di->di_printf("#0x%03x", (insn & 0xff) << 2); - - if (insn & (1 << 24)) - di->di_printf("]"); - - if (insn & (1 << 21)) - di->di_printf("!"); -} - -static u_int -disassemble_readword(u_int address) -{ - return(*((u_int *)address)); -} - -static void -disassemble_printaddr(u_int address) -{ - printf("0x%08x", address); -} - -static void -disassemble_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vprintf(fmt, ap); - va_end(ap); -} - -static const disasm_interface_t disassemble_di = { - disassemble_readword, disassemble_printaddr, disassemble_printf -}; - -void -disassemble(u_int address) -{ - - (void)disasm(&disassemble_di, address, 0); -} - -/* End of disassem.c */ diff --git a/libacc/tests/disassem.h b/libacc/tests/disassem.h deleted file mode 100644 index 02747cd..0000000 --- a/libacc/tests/disassem.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $NetBSD: disassem.h,v 1.4 2001/03/04 04:15:58 matt Exp $ */ - -/*- - * Copyright (c) 1997 Mark Brinicombe. - * Copyright (c) 1997 Causality Limited. - * - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Mark Brinicombe. - * 4. The name of the company nor the name of the author may be used to - * endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Define the interface structure required by the disassembler. - * - * $FreeBSD: /repoman/r/ncvs/src/sys/arm/include/disassem.h,v 1.2 2005/01/05 21:58:48 imp Exp $ - */ - -#ifndef ANDROID_MACHINE_DISASSEM_H -#define ANDROID_MACHINE_DISASSEM_H - -#include <sys/types.h> - -#if __cplusplus -extern "C" { -#endif - -typedef struct { - u_int (*di_readword)(u_int); - void (*di_printaddr)(u_int); - void (*di_printf)(const char *, ...); -} disasm_interface_t; - -/* Prototypes for callable functions */ - -u_int disasm(const disasm_interface_t *, u_int, int); -void disassemble(u_int); - -#if __cplusplus -} -#endif - -#endif /* !ANDROID_MACHINE_DISASSEM_H */ diff --git a/libacc/tests/main.cpp b/libacc/tests/main.cpp deleted file mode 100644 index e4e386f..0000000 --- a/libacc/tests/main.cpp +++ /dev/null @@ -1,207 +0,0 @@ -/* - * 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 - -#if defined(__arm__) -#define PROVIDE_ARM_DISASSEMBLY -#endif - -#ifdef PROVIDE_ARM_DISASSEMBLY -#include "disassem.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); -} - -ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { - return (ACCvoid*) dlsym(RTLD_DEFAULT, name); -} - -#ifdef PROVIDE_ARM_DISASSEMBLY - -static FILE* disasmOut; - -static u_int -disassemble_readword(u_int address) -{ - return(*((u_int *)address)); -} - -static void -disassemble_printaddr(u_int address) -{ - fprintf(disasmOut, "0x%08x", address); -} - -static void -disassemble_printf(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); - vfprintf(disasmOut, fmt, ap); - va_end(ap); -} - -static int disassemble(ACCscript* script, FILE* out) { - disasmOut = out; - disasm_interface_t di; - di.di_readword = disassemble_readword; - di.di_printaddr = disassemble_printaddr; - di.di_printf = disassemble_printf; - - ACCvoid* base; - ACCsizei length; - - accGetProgramBinary(script, &base, &length); - unsigned long* pBase = (unsigned long*) base; - unsigned long* pEnd = (unsigned long*) (((unsigned char*) base) + length); - - for(unsigned long* pInstruction = pBase; pInstruction < pEnd; pInstruction++) { - fprintf(out, "%08x: %08x ", (int) pInstruction, (int) *pInstruction); - ::disasm(&di, (uint) pInstruction, 0); - } - return 0; -} - -#endif // PROVIDE_ARM_DISASSEMBLY - -int main(int argc, char** argv) { - const char* inFile = NULL; - bool printListing; - bool runResults = false; - 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; - case 'R': - runResults = 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 + 1]; - size_t bytesRead = fread(text, 1, fileSize, in); - if (bytesRead != fileSize) { - fprintf(stderr, "Could not read all of file %s\n", inFile); - } - - text[fileSize] = '\0'; - - ACCscript* script = accCreateScript(); - - const ACCchar* scriptSource[] = {text}; - accScriptSource(script, 1, scriptSource, NULL); - delete[] text; - - accRegisterSymbolCallback(script, symbolLookup, NULL); - - accCompileScript(script); - int result = accGetError(script); - MainPtr mainPointer = 0; - if (result != 0) { - ACCsizei bufferLength; - accGetScriptInfoLog(script, 0, &bufferLength, NULL); - char* buf = (char*) malloc(bufferLength + 1); - if (buf != NULL) { - accGetScriptInfoLog(script, bufferLength + 1, NULL, buf); - fprintf(stderr, "%s", buf); - free(buf); - } else { - fprintf(stderr, "Out of memory.\n"); - } - goto exit; - } - - { - ACCsizei numPragmaStrings; - accGetPragmas(script, &numPragmaStrings, 0, NULL); - if (numPragmaStrings) { - char** strings = new char*[numPragmaStrings]; - accGetPragmas(script, NULL, numPragmaStrings, strings); - for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { - fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); - } - delete[] strings; - } - } - - if (printListing) { -#ifdef PROVIDE_ARM_DISASSEMBLY - disassemble(script, stderr); -#endif - } - - if (runResults) { - accGetScriptLabel(script, "main", (ACCvoid**) & mainPointer); - - result = accGetError(script); - if (result != ACC_NO_ERROR) { - fprintf(stderr, "Could not find main: %d\n", result); - } else { - 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); - } - } - -exit: - - accDeleteScript(script); - - return result; -} diff --git a/libacc/tests/runtimeTest.cpp b/libacc/tests/runtimeTest.cpp deleted file mode 100644 index 55bf877..0000000 --- a/libacc/tests/runtimeTest.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * RuntimeTest for ACC compiler. - * - */ - -#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 void (*ScriptPtr)(); - -// This is a separate function so it can easily be set by breakpoint in gdb. -void run(ScriptPtr scriptFn) { - scriptFn(); -} - -// Private API for development: - -extern "C" -void accDisassemble(ACCscript* script); - -int globalVar; - -void op_int(int a) { - printf("op_int(%d)\n", a); -} - -void op_float12(float a, float b, float c, float d, - float e, float f, float g, float h, - float i, float j, float k, float l) { - printf("op_float12(%g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g, %g)\n", - a, b, c, d, e, f, g, h, i, j, k, l); -} - -const char* text = "void op_int(int a);\n" - "void op_float12(float a, float b, float c, float d,\n" - " float e, float f, float g, float h,\n" - " float i, float j, float k, float l);\n" - "void script() {\n" - " globalVar += 3;\n" - " op_int(123);\n" - " op_float12(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0);\n" - "}\n"; - -ACCvoid* symbolLookup(ACCvoid* pContext, const ACCchar* name) { - if (strcmp("op_int", name) == 0) { - return (ACCvoid*) op_int; - } - if (strcmp("op_float12", name) == 0) { - return (ACCvoid*) op_float12; - } - if (strcmp("globalVar", name) == 0) { - return (ACCvoid*) &globalVar; - } - return (ACCvoid*) dlsym(RTLD_DEFAULT, name); -} - -int main(int argc, char** argv) { - ACCscript* script = accCreateScript(); - - accRegisterSymbolCallback(script, symbolLookup, NULL); - - const ACCchar* scriptSource[] = {text}; - accScriptSource(script, 1, scriptSource, NULL); - - accCompileScript(script); - int result = accGetError(script); - ScriptPtr scriptPointer = 0; - if (result != 0) { - char buf[1024]; - accGetScriptInfoLog(script, sizeof(buf), NULL, buf); - fprintf(stderr, "%s", buf); - goto exit; - } - - { - ACCsizei numPragmaStrings; - accGetPragmas(script, &numPragmaStrings, 0, NULL); - if (numPragmaStrings) { - char** strings = new char*[numPragmaStrings]; - accGetPragmas(script, NULL, numPragmaStrings, strings); - for(ACCsizei i = 0; i < numPragmaStrings; i += 2) { - fprintf(stderr, "#pragma %s(%s)\n", strings[i], strings[i+1]); - } - delete[] strings; - } - } - - accGetScriptLabel(script, "script", (ACCvoid**) & scriptPointer); - - result = accGetError(script); - if (result != ACC_NO_ERROR) { - fprintf(stderr, "Could not find script: %d\n", result); - } else { - fprintf(stderr, "Executing script:\n"); - globalVar = 17; - run(scriptPointer); - fprintf(stderr, "After script globalVar = %d\n", globalVar); - } - - -exit: - - accDeleteScript(script); - - return result; -} diff --git a/libacc/tests/test b/libacc/tests/test deleted file mode 100755 index 8fd6916..0000000 --- a/libacc/tests/test +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/bash - -SCRIPT_DIR=`dirname $BASH_SOURCE` -cd $SCRIPT_DIR -python test.py "$@" - diff --git a/libacc/tests/test.py b/libacc/tests/test.py deleted file mode 100644 index 1b444c7..0000000 --- a/libacc/tests/test.py +++ /dev/null @@ -1,517 +0,0 @@ -# -# Test the acc compiler - -import unittest -import subprocess -import os -import sys - -gArmInitialized = False -gUseArm = True -gUseX86 = True -gRunOTCCOutput = True -gCompileOTCCANSI = True - - -def parseArgv(): - global gUseArm - global gUseX86 - global gRunOTCCOutput - for arg in sys.argv[1:]: - if arg == "--noarm": - print "--noarm: not testing ARM" - gUseArm = False - elif arg == "--nox86": - print "--nox86: not testing x86" - gUseX86 = False - elif arg == "--norunotcc": - print "--norunotcc detected, not running OTCC output" - gRunOTCCOutput = False - else: - print "Unknown parameter: ", arg - raise "Unknown parameter" - sys.argv = sys.argv[0:1] - -def compile(args): - proc = subprocess.Popen(["acc"] + args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) - result = proc.communicate() - return result - -def runCmd(args): - proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - result = proc.communicate() - return result[0].strip() - -def uname(): - return runCmd(["uname"]) - -def unameM(): - return runCmd(["uname", "-m"]) - -def which(item): - return runCmd(["which", item]) - -def fileType(item): - return runCmd(["file", item]) - -def outputCanRun(): - ft = fileType(which("acc")) - return ft.find("ELF 32-bit LSB executable, Intel 80386") >= 0 - -def checkEnvironment(): - global gRunOTCCOutput - global gCompileOTCCANSI - osName = uname() - gRunOTCCOutput = osName == "Linux" and unameM() != "x86_64" and outputCanRun() - # OSX doesn't have stdin/stdout/stderr accessible through dll load symbols, so - # we can't compile the ANSI version of the OTCC compiler on OS X. - gCompileOTCCANSI = osName == "Linux" - -def adb(args): - return runCmd(["adb"] + args) - -def setupArm(): - global gArmInitialized - if gArmInitialized: - return - print "Setting up arm" - adb(["remount"]) - adb(["shell", "rm", "/system/bin/acc"]) - adb(["shell", "mkdir", "/system/bin/accdata"]) - adb(["shell", "mkdir", "/system/bin/accdata/data"]) - # Clear out old data TODO: handle recursion - adb(["shell", "rm", "/system/bin/accdata/data/*"]) - # Copy over data - for root, dirs, files in os.walk("data"): - for d in dirs: - adb(["shell", "mkdir", os.path.join(root, d)]) - for f in files: - adb(["push", os.path.join(root, f), os.path.join("/system/bin/accdata", root, f)]) - # Copy over compiler - adb(["sync"]) - gArmInitialized = True - -def compileArm(args): - setupArm() - proc = subprocess.Popen(["adb", "shell", "/system/bin/acc"] + args, stdout=subprocess.PIPE) - result = proc.communicate() - return result[0].replace("\r","") - -def compare(a, b): - if a != b: - firstDiff = firstDifference(a, b) - print "Strings differ at character %d. Common: %s. Difference '%s' != '%s'" % ( - firstDiff, a[0:firstDiff], safeAccess(a, firstDiff), safeAccess(b, firstDiff)) - -def safeAccess(s, i): - if 0 <= i < len(s): - return s[i] - else: - return '?' - -def firstDifference(a, b): - commonLen = min(len(a), len(b)) - for i in xrange(0, commonLen): - if a[i] != b[i]: - return i - return commonLen - -# a1 and a2 are the expected stdout and stderr. -# b1 and b2 are the actual stdout and stderr. -# Compare the two, sets. Allow any individual line -# to appear in either stdout or stderr. This is because -# the way we obtain output on the ARM combines both -# streams into one sequence. - -def compareOuput(a1,a2,b1,b2): - while True: - totalLen = len(a1) + len(a2) + len(b1) + len(b2) - a1, b1 = matchCommon(a1, b1) - a1, b2 = matchCommon(a1, b2) - a2, b1 = matchCommon(a2, b1) - a2, b2 = matchCommon(a2, b2) - newTotalLen = len(a1) + len(a2) + len(b1) + len(b2) - if newTotalLen == 0: - return True - if newTotalLen == totalLen: - print "Failed at %d %d %d %d" % (len(a1), len(a2), len(b1), len(b2)) - print "a1", a1 - print "a2", a2 - print "b1", b1 - print "b2", b2 - return False - -def matchCommon(a, b): - """Remove common items from the beginning of a and b, - return just the tails that are different.""" - while len(a) > 0 and len(b) > 0 and a[0] == b[0]: - a = a[1:] - b = b[1:] - return a, b - -def rewritePaths(args): - return [rewritePath(x) for x in args] - -def rewritePath(p): - """Take a path that's correct on the x86 and convert to a path - that's correct on ARM.""" - if p.startswith("data/"): - p = "/system/bin/accdata/" + p - return p - -class TestACC(unittest.TestCase): - - def checkResult(self, out, err, stdErrResult, stdOutResult=""): - a1 = out.splitlines() - a2 = err.splitlines() - b2 = stdErrResult.splitlines() - b1 = stdOutResult.splitlines() - self.assertEqual(True, compareOuput(a1,a2,b1,b2)) - - def compileCheck(self, args, stdErrResult, stdOutResult="", - targets=['arm', 'x86']): - global gUseArm - global gUseX86 - targetSet = frozenset(targets) - if gUseX86 and 'x86' in targetSet: - out, err = compile(args) - self.checkResult(out, err, stdErrResult, stdOutResult) - if gUseArm and 'arm' in targetSet: - out = compileArm(rewritePaths(args)) - self.checkResult(out, "", stdErrResult, stdOutResult) - - def compileCheckArm(self, args, result): - self.assertEqual(compileArm(args), result) - - def testCompileReturnVal(self): - self.compileCheck(["data/returnval-ansi.c"], "") - - def testCompileOTCCANSI(self): - global gCompileOTCCANSI - if gCompileOTCCANSI: - self.compileCheck(["data/otcc-ansi.c"], "", "", ['x86']) - - def testRunReturnVal(self): - self.compileCheck(["-R", "data/returnval-ansi.c"], - "Executing compiled code:\nresult: 42\n") - - def testContinue(self): - self.compileCheck(["-R", "data/continue.c"], - "Executing compiled code:\nresult: 400\n") - - def testStringLiteralConcatenation(self): - self.compileCheck(["-R", "data/testStringConcat.c"], - "Executing compiled code:\nresult: 13\n", "Hello, world\n") - - def testRunOTCCANSI(self): - global gRunOTCCOutput - if gRunOTCCOutput: - self.compileCheck(["-R", "data/otcc-ansi.c", "data/returnval.c"], - "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\natcc-ansi.c: result: 42\nresult: 42\n", "", - ['x86']) - - def testRunOTCCANSI2(self): - global gRunOTCCOutput - if gRunOTCCOutput: - self.compileCheck(["-R", "data/otcc-ansi.c", "data/otcc.c", "data/returnval.c"], - "Executing compiled code:\notcc-ansi.c: About to execute compiled code:\notcc.c: about to execute compiled code.\natcc-ansi.c: result: 42\nresult: 42\n", "",['x86']) - - def testRunConstants(self): - self.compileCheck(["-R", "data/constants.c"], - "Executing compiled code:\nresult: 12\n", - "0 = 0\n010 = 8\n0x10 = 16\n'\\a' = 7\n'\\b' = 8\n'\\f' = 12\n'\\n' = 10\n'\\r' = 13\n'\\t' = 9\n'\\v' = 11\n'\\\\' = 92\n'\\'' = 39\n" + - "'\\\"' = 34\n'\\?' = 63\n'\\0' = 0\n'\\1' = 1\n'\\12' = 10\n'\\123' = 83\n'\\x0' = 0\n'\\x1' = 1\n'\\x12' = 18\n'\\x123' = 291\n'\\x1f' = 31\n'\\x1F' = 31\n") - - def testRunFloat(self): - self.compileCheck(["-R", "data/float.c"], - "Executing compiled code:\nresult: 0\n", - """Constants: 0 0 0 0.01 0.01 0.1 10 10 0.1 -int: 1 float: 2.2 double: 3.3 - ftoi(1.4f)=1 - dtoi(2.4)=2 - itof(3)=3 - itod(4)=4 -globals: 1 2 3 4 -args: 1 2 3 4 -locals: 1 2 3 4 -cast rval: 2 4 -cast lval: 1.1 2 3.3 4 -""") - - def testRunFlops(self): - self.compileCheck(["-R", "data/flops.c"], - """Executing compiled code: -result: 0""", -"""-1.1 = -1.1 -!1.2 = 0 -!0 = 1 -double op double: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -float op float: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op float: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op int: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -int op double: -1 + 2 = 3 -1 - 2 = -1 -1 * 2 = 2 -1 / 2 = 0.5 -double op double: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -double op float: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -float op float: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -int op double: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -double op int: -1 op 2: < 1 <= 1 == 0 >= 0 > 0 != 1 -1 op 1: < 0 <= 1 == 1 >= 1 > 0 != 0 -2 op 1: < 0 <= 0 == 0 >= 1 > 1 != 1 -branching: 1 0 1 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassi: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassf: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassd: 1 2 3 4 5 6 7 8 9 10 11 12 -testpassidf: 1 2 3 -""") - def testCasts(self): - self.compileCheck(["-R", "data/casts.c"], - """Executing compiled code: -result: 0""", """Reading from a pointer: 3 3 -Writing to a pointer: 4 -Testing casts: 3 3 4.5 4 -Testing reading (int*): 4 -Testing writing (int*): 8 9 -Testing reading (char*): 0x78 0x56 0x34 0x12 -Testing writing (char*): 0x87654321 -f(10) -Function pointer result: 70 -Testing read/write (float*): 8.8 9.9 -Testing read/write (double*): 8.8 9.9 -""") - - def testChar(self): - self.compileCheck(["-R", "data/char.c"], """Executing compiled code: -result: 0""", """a = 99, b = 41 -ga = 100, gb = 44""") - - def testTypedef(self): - self.compileCheck(["-R", "data/typedef.c"], """Executing compiled code: -result: 0""", """x = 3 -(4, 6) = (1, 2) + (3, 4) -""") - - def testPointerArithmetic(self): - self.compileCheck(["-R", "data/pointers.c"], """Executing compiled code: -result: 0""", """Pointer difference: 1 4 -Pointer addition: 2 -Pointer comparison to zero: 0 0 1 -Pointer comparison: 1 0 0 0 1 -""") - def testRollo3(self): - self.compileCheck(["-R", "data/rollo3.c"], """Executing compiled code: -result: 10""", """""") - - def testFloatDouble(self): - self.compileCheck(["-R", "data/floatdouble.c"], """Executing compiled code: -result: 0""", """0.002 0.1 10""") - - def testIncDec(self): - self.compileCheck(["-R", "data/inc.c"], """Executing compiled code: -0 -1 -2 -1 -1 -2 -1 -0 -result: 0 -""","""""") - - def testIops(self): - self.compileCheck(["-R", "data/iops.c"], """Executing compiled code: -result: 0""", """Literals: 1 -1 -++ -0 -1 -2 -3 -4 -5 -6 -7 -8 -9 --- -10 -9 -8 -7 -6 -5 -4 -3 -2 -1 -0 -""") - - def testFilm(self): - self.compileCheck(["-R", "data/film.c"], """Executing compiled code: -result: 0""", """testing... -Total bad: 0 -""") - - def testMacros(self): - self.compileCheck(["-R", "data/macros.c"], """Executing compiled code: -result: 0""", """A = 6 -A = 10 -""") - - def testpointers2(self): - self.compileCheck(["-R", "data/pointers2.c"], """Executing compiled code: -result: 0""", """a = 0, *pa = 0 -a = 2, *pa = 2 -a = 0, *pa = 0 **ppa = 0 -a = 2, *pa = 2 **ppa = 2 -a = 0, *pa = 0 **ppa = 0 -a = 2, *pa = 2 **ppa = 2 -""") - - def testassignmentop(self): - self.compileCheck(["-R", "data/assignmentop.c"], """Executing compiled code: -result: 0""", """2 *= 5 10 -20 /= 5 4 -17 %= 5 2 -17 += 5 22 -17 -= 5 12 -17<<= 1 34 -17>>= 1 8 -17&= 1 1 -17^= 1 16 -16|= 1 17 -*f() = *f() + 10; -f() -f() -a = 10 -*f() += 10; -f() -a = 10 -""") - - def testcomma(self): - self.compileCheck(["-R", "data/comma.c"], """Executing compiled code: -result: 0""", """statement: 10 -if: a = 0 -while: b = 11 -for: b = 22 -return: 30 -arg: 12 -""") - - def testBrackets(self): - self.compileCheck(["-R", "data/brackets.c"], """Executing compiled code: -Errors: 0 -2D Errors: 0 -result: 0 -""","""""") - - def testShort(self): - self.compileCheck(["-R", "data/short.c"], """Executing compiled code: -result: -2 -""","""""") - - def testAssignment(self): - self.compileCheck(["-R", "data/assignment.c"], """Executing compiled code: -result: 7 -""","""""") - - def testArray(self): - self.compileCheck(["-R", "data/array.c"], """Executing compiled code: -localInt: 3 -localDouble: 3 3 -globalChar: 3 -globalDouble: 3 -testArgs: 0 2 4 -testDecay: Hi! -test2D: -abcdefghijdefghijklm -defghijklmghijklmnop -ghijklmnopjklmnopabc -jklmnopabcmnopabcdef -mnopabcdefpabcdefghi -pabcdefghicdefghijkl -cdefghijklfghijklmno -fghijklmnoijklmnopab -ijklmnopablmnopabcde -lmnopabcdefghijklmno -result: 0 -""","""""") - - def testDefines(self): - self.compileCheck(["-R", "data/defines.c"], """Executing compiled code: -result: 3 -""","""""") - - def testFuncArgs(self): - self.compileCheck(["-R", "data/funcargs.c"], """Executing compiled code: -result: 4 -""","""""") - - def testB2071670(self): - self.compileCheck(["-R", "data/b2071670.c"], """Executing compiled code: -result: 1092616192 -""","""""") - - def testStructs(self): - self.compileCheck(["-R", "data/structs.c"], """Executing compiled code: -testCopying: 37 == 37 -testUnion: 1 == 0x3f800000 -testArgs: (6, 8, 10, 12) -result: 6 -""","""""") - - def testAddressOf(self): - self.compileCheck(["-R", "data/addressOf.c"], """Executing compiled code: -testStruct: 10 10 10 -testArray: 1 1 1 -result: 0 -""","""""") - -def main(): - checkEnvironment() - parseArgv() - unittest.main() - -if __name__ == '__main__': - main() - diff --git a/libcutils/Android.mk b/libcutils/Android.mk index 8b739e9..25d36da 100644 --- a/libcutils/Android.mk +++ b/libcutils/Android.mk @@ -109,7 +109,7 @@ else #!sim # ======================================================== include $(CLEAR_VARS) LOCAL_MODULE := libcutils -LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c uevent.c +LOCAL_SRC_FILES := $(commonSources) ashmem-dev.c mq.c android_reboot.c uevent.c ifeq ($(TARGET_ARCH),arm) LOCAL_SRC_FILES += arch-arm/memset32.S diff --git a/libcutils/android_reboot.c b/libcutils/android_reboot.c new file mode 100644 index 0000000..33a7358 --- /dev/null +++ b/libcutils/android_reboot.c @@ -0,0 +1,134 @@ +/* + * Copyright 2011, 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. + */ + +#include <unistd.h> +#include <sys/reboot.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <stdio.h> +#include <string.h> + +#include <cutils/android_reboot.h> + +/* Check to see if /proc/mounts contains any writeable filesystems + * backed by a block device. + * Return true if none found, else return false. + */ +static int remount_ro_done(void) +{ + FILE *f; + char mount_dev[256]; + char mount_dir[256]; + char mount_type[256]; + char mount_opts[256]; + int mount_freq; + int mount_passno; + int match; + int found_rw_fs = 0; + + f = fopen("/proc/mounts", "r"); + if (! f) { + /* If we can't read /proc/mounts, just give up */ + return 1; + } + + do { + match = fscanf(f, "%255s %255s %255s %255s %d %d\n", + mount_dev, mount_dir, mount_type, + mount_opts, &mount_freq, &mount_passno); + mount_dev[255] = 0; + mount_dir[255] = 0; + mount_type[255] = 0; + mount_opts[255] = 0; + if ((match == 6) && !strncmp(mount_dev, "/dev/block", 10) && strstr(mount_opts, "rw")) { + found_rw_fs = 1; + break; + } + } while (match != EOF); + + fclose(f); + + return !found_rw_fs; +} + +/* Remounting filesystems read-only is difficult when there are files + * opened for writing or pending deletes on the filesystem. There is + * no way to force the remount with the mount(2) syscall. The magic sysrq + * 'u' command does an emergency remount read-only on all writable filesystems + * that have a block device (i.e. not tmpfs filesystems) by calling + * emergency_remount(), which knows how to force the remount to read-only. + * Unfortunately, that is asynchronous, and just schedules the work and + * returns. The best way to determine if it is done is to read /proc/mounts + * repeatedly until there are no more writable filesystems mounted on + * block devices. + */ +static void remount_ro(void) +{ + int fd, cnt = 0; + + /* Trigger the remount of the filesystems as read-only, + * which also marks them clean. + */ + fd = open("/proc/sysrq-trigger", O_WRONLY); + if (fd < 0) { + return; + } + write(fd, "u", 1); + close(fd); + + + /* Now poll /proc/mounts till it's done */ + while (!remount_ro_done() && (cnt < 50)) { + usleep(100000); + cnt++; + } + + return; +} + + +int android_reboot(int cmd, int flags, char *arg) +{ + int ret; + + if (!(flags & ANDROID_RB_FLAG_NO_SYNC)) + sync(); + + if (!(flags & ANDROID_RB_FLAG_NO_REMOUNT_RO)) + remount_ro(); + + switch (cmd) { + case ANDROID_RB_RESTART: + ret = reboot(RB_AUTOBOOT); + break; + + case ANDROID_RB_POWEROFF: + ret = reboot(RB_POWER_OFF); + break; + + case ANDROID_RB_RESTART2: + ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, arg); + break; + + default: + ret = -1; + } + + return ret; +} + diff --git a/libcutils/atomic-android-sh.c b/libcutils/atomic-android-sh.c index f8f1f57..8bac68a 100644 --- a/libcutils/atomic-android-sh.c +++ b/libcutils/atomic-android-sh.c @@ -113,18 +113,6 @@ int32_t android_atomic_or(int32_t value, volatile int32_t* addr) { return oldValue; } -int32_t android_atomic_acquire_swap(int32_t value, volatile int32_t* addr) { - return android_atomic_release_swap(value, addr); -} - -int32_t android_atomic_release_swap(int32_t value, volatile int32_t* addr) { - int32_t oldValue; - do { - oldValue = *addr; - } while (android_atomic_cmpxchg(oldValue, value, addr)); - return oldValue; -} - int android_atomic_acquire_cmpxchg(int32_t oldvalue, int32_t newvalue, volatile int32_t* addr) { return android_atomic_release_cmpxchg(oldValue, newValue, addr); diff --git a/libcutils/properties.c b/libcutils/properties.c index 547cc6d..98f356b 100644 --- a/libcutils/properties.c +++ b/libcutils/properties.c @@ -31,47 +31,9 @@ #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_ #include <sys/_system_properties.h> -static int send_prop_msg(prop_msg *msg) -{ - int s; - int r; - - s = socket_local_client(PROP_SERVICE_NAME, - ANDROID_SOCKET_NAMESPACE_RESERVED, - SOCK_STREAM); - if(s < 0) return -1; - - while((r = send(s, msg, sizeof(prop_msg), 0)) < 0) { - if((errno == EINTR) || (errno == EAGAIN)) continue; - break; - } - - if(r == sizeof(prop_msg)) { - r = 0; - } else { - r = -1; - } - - close(s); - return r; -} - int property_set(const char *key, const char *value) { - prop_msg msg; - unsigned resp; - - if(key == 0) return -1; - if(value == 0) value = ""; - - if(strlen(key) >= PROP_NAME_MAX) return -1; - if(strlen(value) >= PROP_VALUE_MAX) return -1; - - msg.cmd = PROP_MSG_SETPROP; - strcpy((char*) msg.name, key); - strcpy((char*) msg.value, value); - - return send_prop_msg(&msg); + return __system_property_set(key, value); } int property_get(const char *key, char *value, const char *default_value) diff --git a/libnetutils/dhcp_utils.c b/libnetutils/dhcp_utils.c index 064eb0c..030e677 100644 --- a/libnetutils/dhcp_utils.c +++ b/libnetutils/dhcp_utils.c @@ -18,6 +18,7 @@ #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <unistd.h> #include <arpa/inet.h> #include <netinet/in.h> @@ -28,8 +29,7 @@ static const char DAEMON_NAME[] = "dhcpcd"; static const char DAEMON_PROP_NAME[] = "init.svc.dhcpcd"; static const char HOSTNAME_PROP_NAME[] = "net.hostname"; static const char DHCP_PROP_NAME_PREFIX[] = "dhcp"; -static const char DAEMON_NAME_RENEW[] = "iprenew"; -static const int NAP_TIME = 1; /* wait for 1 second at a time */ +static const int NAP_TIME = 200; /* wait for 200ms at a time */ /* when polling for property values */ static char errmsg[100]; @@ -42,14 +42,14 @@ static char errmsg[100]; static int wait_for_property(const char *name, const char *desired_value, int maxwait) { char value[PROPERTY_VALUE_MAX] = {'\0'}; - int maxnaps = maxwait / NAP_TIME; + int maxnaps = (maxwait * 1000) / NAP_TIME; if (maxnaps < 1) { maxnaps = 1; } while (maxnaps-- > 0) { - usleep(1000000); + usleep(NAP_TIME * 1000); if (property_get(name, value, NULL)) { if (desired_value == NULL || strcmp(value, desired_value) == 0) { @@ -60,60 +60,60 @@ static int wait_for_property(const char *name, const char *desired_value, int ma return -1; /* failure */ } -static void fill_ip_info(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, +static int fill_ip_info(const char *interface, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease) { char prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX]; - struct in_addr addr; - in_addr_t iaddr; snprintf(prop_name, sizeof(prop_name), "%s.%s.ipaddress", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *ipaddr = addr.s_addr; - } else { - *ipaddr = 0; - } + property_get(prop_name, ipaddr, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.gateway", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *gateway = addr.s_addr; - } else { - *gateway = 0; - } + property_get(prop_name, gateway, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.mask", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *mask = addr.s_addr; - } else { - *mask = 0; + if (property_get(prop_name, prop_value, NULL)) { + int p; + // this conversion is v4 only, but this dhcp client is v4 only anyway + in_addr_t mask = ntohl(inet_addr(prop_value)); + // Check netmask is a valid IP address. ntohl gives NONE response (all 1's) for + // non 255.255.255.255 inputs. if we get that value check if it is legit.. + if (mask == INADDR_NONE && strcmp(prop_value, "255.255.255.255") != 0) { + snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value); + return -1; + } + for (p = 0; p < 32; p++) { + if (mask == 0) break; + // check for non-contiguous netmask, e.g., 255.254.255.0 + if ((mask & 0x80000000) == 0) { + snprintf(errmsg, sizeof(errmsg), "DHCP gave invalid net mask %s", prop_value); + return -1; + } + mask = mask << 1; + } + *prefixLength = p; } snprintf(prop_name, sizeof(prop_name), "%s.%s.dns1", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns1 = addr.s_addr; - } else { - *dns1 = 0; - } + property_get(prop_name, dns1, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.dns2", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *dns2 = addr.s_addr; - } else { - *dns2 = 0; - } + property_get(prop_name, dns2, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.server", DHCP_PROP_NAME_PREFIX, interface); - if (property_get(prop_name, prop_value, NULL) && inet_aton(prop_value, &addr)) { - *server = addr.s_addr; - } else { - *server = 0; - } + property_get(prop_name, server, NULL); + snprintf(prop_name, sizeof(prop_name), "%s.%s.leasetime", DHCP_PROP_NAME_PREFIX, interface); if (property_get(prop_name, prop_value, NULL)) { *lease = atol(prop_value); } + return 0; } static const char *ipaddr_to_string(in_addr_t addr) @@ -129,16 +129,15 @@ static const char *ipaddr_to_string(in_addr_t addr) * configuring the interface. */ int dhcp_do_request(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, + char *ipaddr, + char *gateway, + uint32_t *prefixLength, + char *dns1, + char *dns2, + char *server, uint32_t *lease) { char result_prop_name[PROPERTY_KEY_MAX]; - char daemon_prop_name[PROPERTY_KEY_MAX]; char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; char daemon_cmd[PROPERTY_VALUE_MAX * 2]; const char *ctrl_prop = "ctl.start"; @@ -147,23 +146,18 @@ int dhcp_do_request(const char *interface, snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", DHCP_PROP_NAME_PREFIX, interface); - - snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s", - DAEMON_PROP_NAME, - interface); - /* Erase any previous setting of the dhcp result property */ property_set(result_prop_name, ""); /* Start the daemon and wait until it's ready */ if (property_get(HOSTNAME_PROP_NAME, prop_value, NULL) && (prop_value[0] != '\0')) - snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:-h %s %s", DAEMON_NAME, interface, + snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:-h %s %s", DAEMON_NAME, prop_value, interface); else - snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME, interface, interface); + snprintf(daemon_cmd, sizeof(daemon_cmd), "%s:%s", DAEMON_NAME, interface); memset(prop_value, '\0', PROPERTY_VALUE_MAX); property_set(ctrl_prop, daemon_cmd); - if (wait_for_property(daemon_prop_name, desired_status, 10) < 0) { + if (wait_for_property(DAEMON_PROP_NAME, desired_status, 10) < 0) { snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for dhcpcd to start"); return -1; } @@ -181,8 +175,13 @@ int dhcp_do_request(const char *interface, } if (strcmp(prop_value, "ok") == 0) { char dns_prop_name[PROPERTY_KEY_MAX]; - fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease); - /* copy the dhcp.XXX.dns properties to net.XXX.dns */ + if (fill_ip_info(interface, ipaddr, gateway, prefixLength, dns1, dns2, server, lease) + == -1) { + return -1; + } + + /* copy dns data to system properties - TODO - remove this after we have async + * notification of renewal's */ snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns1", interface); property_set(dns_prop_name, *dns1 ? ipaddr_to_string(*dns1) : ""); snprintf(dns_prop_name, sizeof(dns_prop_name), "net.%s.dns2", interface); @@ -200,24 +199,15 @@ int dhcp_do_request(const char *interface, int dhcp_stop(const char *interface) { char result_prop_name[PROPERTY_KEY_MAX]; - char daemon_prop_name[PROPERTY_KEY_MAX]; - char daemon_cmd[PROPERTY_VALUE_MAX * 2]; const char *ctrl_prop = "ctl.stop"; const char *desired_status = "stopped"; snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", DHCP_PROP_NAME_PREFIX, interface); - - snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s", - DAEMON_PROP_NAME, - interface); - - snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface); - /* Stop the daemon and wait until it's reported to be stopped */ - property_set(ctrl_prop, daemon_cmd); - if (wait_for_property(daemon_prop_name, desired_status, 5) < 0) { + property_set(ctrl_prop, DAEMON_NAME); + if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) { return -1; } property_set(result_prop_name, "failed"); @@ -229,20 +219,12 @@ int dhcp_stop(const char *interface) */ int dhcp_release_lease(const char *interface) { - char daemon_prop_name[PROPERTY_KEY_MAX]; - char daemon_cmd[PROPERTY_VALUE_MAX * 2]; const char *ctrl_prop = "ctl.stop"; const char *desired_status = "stopped"; - snprintf(daemon_prop_name, sizeof(daemon_prop_name), "%s_%s", - DAEMON_PROP_NAME, - interface); - - snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s", DAEMON_NAME, interface); - /* Stop the daemon and wait until it's reported to be stopped */ - property_set(ctrl_prop, daemon_cmd); - if (wait_for_property(daemon_prop_name, desired_status, 5) < 0) { + property_set(ctrl_prop, DAEMON_NAME); + if (wait_for_property(DAEMON_PROP_NAME, desired_status, 5) < 0) { return -1; } return 0; @@ -251,53 +233,3 @@ int dhcp_release_lease(const char *interface) char *dhcp_get_errmsg() { return errmsg; } - -/** - * Run WiMAX dhcp renew service. - * "wimax_renew" service shoud be included in init.rc. - */ -int dhcp_do_request_renew(const char *interface, - in_addr_t *ipaddr, - in_addr_t *gateway, - in_addr_t *mask, - in_addr_t *dns1, - in_addr_t *dns2, - in_addr_t *server, - uint32_t *lease) -{ - char result_prop_name[PROPERTY_KEY_MAX]; - char prop_value[PROPERTY_VALUE_MAX] = {'\0'}; - char daemon_cmd[PROPERTY_VALUE_MAX * 2]; - const char *ctrl_prop = "ctl.start"; - - snprintf(result_prop_name, sizeof(result_prop_name), "%s.%s.result", - DHCP_PROP_NAME_PREFIX, - interface); - - /* Erase any previous setting of the dhcp result property */ - property_set(result_prop_name, ""); - - /* Start the renew daemon and wait until it's ready */ - snprintf(daemon_cmd, sizeof(daemon_cmd), "%s_%s:%s", DAEMON_NAME_RENEW, interface, interface); - memset(prop_value, '\0', PROPERTY_VALUE_MAX); - property_set(ctrl_prop, daemon_cmd); - - /* Wait for the daemon to return a result */ - if (wait_for_property(result_prop_name, NULL, 30) < 0) { - snprintf(errmsg, sizeof(errmsg), "%s", "Timed out waiting for DHCP Renew to finish"); - return -1; - } - - if (!property_get(result_prop_name, prop_value, NULL)) { - /* shouldn't ever happen, given the success of wait_for_property() */ - snprintf(errmsg, sizeof(errmsg), "%s", "DHCP Renew result property was not set"); - return -1; - } - if (strcmp(prop_value, "ok") == 0) { - fill_ip_info(interface, ipaddr, gateway, mask, dns1, dns2, server, lease); - return 0; - } else { - snprintf(errmsg, sizeof(errmsg), "DHCP Renew result was %s", prop_value); - return -1; - } -} diff --git a/libnetutils/dhcpclient.c b/libnetutils/dhcpclient.c index ff00432..5039e26 100644 --- a/libnetutils/dhcpclient.c +++ b/libnetutils/dhcpclient.c @@ -93,6 +93,8 @@ const char *ipaddr(in_addr_t addr) return inet_ntoa(in_addr); } +extern int ipv4NetmaskToPrefixLength(in_addr_t mask); + typedef struct dhcp_info dhcp_info; struct dhcp_info { @@ -100,7 +102,7 @@ struct dhcp_info { uint32_t ipaddr; uint32_t gateway; - uint32_t netmask; + uint32_t prefixLength; uint32_t dns1; uint32_t dns2; @@ -111,13 +113,13 @@ struct dhcp_info { dhcp_info last_good_info; -void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *mask, +void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *prefixLength, uint32_t *dns1, uint32_t *dns2, uint32_t *server, uint32_t *lease) { *ipaddr = last_good_info.ipaddr; *gateway = last_good_info.gateway; - *mask = last_good_info.netmask; + *prefixLength = last_good_info.prefixLength; *dns1 = last_good_info.dns1; *dns2 = last_good_info.dns2; *server = last_good_info.serveraddr; @@ -127,7 +129,7 @@ void get_dhcp_info(uint32_t *ipaddr, uint32_t *gateway, uint32_t *mask, static int dhcp_configure(const char *ifname, dhcp_info *info) { last_good_info = *info; - return ifc_configure(ifname, info->ipaddr, info->netmask, info->gateway, + return ifc_configure(ifname, info->ipaddr, info->prefixLength, info->gateway, info->dns1, info->dns2); } @@ -153,8 +155,7 @@ void dump_dhcp_info(dhcp_info *info) dhcp_type_to_name(info->type), info->type); strcpy(addr, ipaddr(info->ipaddr)); strcpy(gway, ipaddr(info->gateway)); - strcpy(mask, ipaddr(info->netmask)); - LOGD("ip %s gw %s mask %s", addr, gway, mask); + LOGD("ip %s gw %s prefixLength %d", addr, gway, info->prefixLength); if (info->dns1) LOGD("dns1: %s", ipaddr(info->dns1)); if (info->dns2) LOGD("dns2: %s", ipaddr(info->dns2)); LOGD("server %s, lease %d seconds", @@ -196,7 +197,7 @@ int decode_dhcp_msg(dhcp_msg *msg, int len, dhcp_info *info) } switch(opt) { case OPT_SUBNET_MASK: - if (optlen >= 4) memcpy(&info->netmask, x, 4); + if (optlen >= 4) info->prefixLength = ipv4NetmaskToPrefixLength((int)x); break; case OPT_GATEWAY: if (optlen >= 4) memcpy(&info->gateway, x, 4); diff --git a/libnetutils/ifc_utils.c b/libnetutils/ifc_utils.c index 0ca5fe6..946c39d 100644 --- a/libnetutils/ifc_utils.c +++ b/libnetutils/ifc_utils.c @@ -25,6 +25,7 @@ #include <sys/types.h> #include <netinet/in.h> #include <arpa/inet.h> +#include <net/if.h> #include <linux/if.h> #include <linux/if_ether.h> @@ -50,6 +51,33 @@ static int ifc_ctl_sock = -1; static int ifc_ctl_sock6 = -1; void printerr(char *fmt, ...); +in_addr_t prefixLengthToIpv4Netmask(int prefix_length) +{ + in_addr_t mask = 0; + + // C99 (6.5.7): shifts of 32 bits have undefined results + if (prefix_length <= 0 || prefix_length > 32) { + return 0; + } + + mask = ~mask << (32 - prefix_length); + mask = htonl(mask); + + return mask; +} + +int ipv4NetmaskToPrefixLength(in_addr_t mask) +{ + mask = ntohl(mask); + int prefixLength = 0; + uint32_t m = (uint32_t)mask; + while (m & 0x80000000) { + prefixLength++; + m = m << 1; + } + return prefixLength; +} + static const char *ipaddr_to_string(in_addr_t addr) { struct in_addr in_addr; @@ -126,7 +154,7 @@ int ifc_get_ifindex(const char *name, int *if_indexp) if(r < 0) return -1; *if_indexp = ifr.ifr_ifindex; - return 0; + return 0; } static int ifc_set_flags(const char *name, unsigned set, unsigned clr) @@ -163,7 +191,7 @@ int ifc_set_addr(const char *name, in_addr_t addr) ifc_init_ifr(name, &ifr); init_sockaddr_in(&ifr.ifr_addr, addr); - + return ioctl(ifc_ctl_sock, SIOCSIFADDR, &ifr); } @@ -178,17 +206,37 @@ int ifc_set_hwaddr(const char *name, const void *ptr) return ioctl(ifc_ctl_sock, SIOCSIFHWADDR, &ifr); } -int ifc_set_mask(const char *name, in_addr_t mask) +int ifc_set_prefixLength(const char *name, int prefixLength) { struct ifreq ifr; + // TODO - support ipv6 + if (prefixLength > 32 || prefixLength < 0) return -1; + in_addr_t mask = prefixLengthToIpv4Netmask(prefixLength); ifc_init_ifr(name, &ifr); init_sockaddr_in(&ifr.ifr_addr, mask); - + return ioctl(ifc_ctl_sock, SIOCSIFNETMASK, &ifr); } -int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *flags) +int ifc_get_addr(const char *name, in_addr_t *addr) +{ + struct ifreq ifr; + int ret = 0; + + ifc_init_ifr(name, &ifr); + if (addr != NULL) { + ret = ioctl(ifc_ctl_sock, SIOCGIFADDR, &ifr); + if (ret < 0) { + *addr = 0; + } else { + *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + } + } + return ret; +} + +int ifc_get_info(const char *name, in_addr_t *addr, int *prefixLength, unsigned *flags) { struct ifreq ifr; ifc_init_ifr(name, &ifr); @@ -200,12 +248,13 @@ int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *f *addr = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; } } - - if (mask != NULL) { + + if (prefixLength != NULL) { if(ioctl(ifc_ctl_sock, SIOCGIFNETMASK, &ifr) < 0) { - *mask = 0; + *prefixLength = 0; } else { - *mask = ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr; + *prefixLength = ipv4NetmaskToPrefixLength((int) + ((struct sockaddr_in*) &ifr.ifr_addr)->sin_addr.s_addr); } } @@ -220,16 +269,6 @@ int ifc_get_info(const char *name, in_addr_t *addr, in_addr_t *mask, unsigned *f return 0; } -in_addr_t get_ipv4_netmask(int prefix_length) -{ - in_addr_t mask = 0; - - mask = ~mask << (32 - prefix_length); - mask = htonl(mask); - - return mask; -} - int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length, struct in_addr gw) { @@ -242,7 +281,7 @@ int ifc_add_ipv4_route(const char *ifname, struct in_addr dst, int prefix_length rt.rt_dst.sa_family = AF_INET; rt.rt_dev = (void*) ifname; - netmask = get_ipv4_netmask(prefix_length); + netmask = prefixLengthToIpv4Netmask(prefix_length); init_sockaddr_in(&rt.rt_genmask, netmask); init_sockaddr_in(&rt.rt_dst, dst.s_addr); rt.rt_flags = RTF_UP; @@ -306,11 +345,20 @@ int ifc_enable(const char *ifname) int ifc_disable(const char *ifname) { + unsigned addr, count; int result; ifc_init(); result = ifc_down(ifname); + ifc_set_addr(ifname, 0); + for (count=0, addr=1;((addr != 0) && (count < 255)); count++) { + if (ifc_get_addr(ifname, &addr) < 0) + break; + if (addr) + ifc_set_addr(ifname, 0); + } + ifc_close(); return result; } @@ -318,17 +366,34 @@ int ifc_disable(const char *ifname) int ifc_reset_connections(const char *ifname) { #ifdef HAVE_ANDROID_OS - int result; + int result, success; in_addr_t myaddr; struct ifreq ifr; + struct in6_ifreq ifr6; + /* IPv4. Clear connections on the IP address. */ ifc_init(); ifc_get_info(ifname, &myaddr, NULL, NULL); ifc_init_ifr(ifname, &ifr); init_sockaddr_in(&ifr.ifr_addr, myaddr); result = ioctl(ifc_ctl_sock, SIOCKILLADDR, &ifr); ifc_close(); - + + /* + * IPv6. On Linux, when an interface goes down it loses all its IPv6 + * addresses, so we don't know which connections belonged to that interface + * So we clear all unused IPv6 connections on the device by specifying an + * empty IPv6 address. + */ + ifc_init6(); + // This implicitly specifies an address of ::, i.e., kill all IPv6 sockets. + memset(&ifr6, 0, sizeof(ifr6)); + success = ioctl(ifc_ctl_sock6, SIOCKILLADDR, &ifr6); + if (result == 0) { + result = success; + } + ifc_close6(); + return result; #else return 0; @@ -467,7 +532,7 @@ int ifc_remove_default_route(const char *ifname) int ifc_configure(const char *ifname, in_addr_t address, - in_addr_t netmask, + uint32_t prefixLength, in_addr_t gateway, in_addr_t dns1, in_addr_t dns2) { @@ -486,8 +551,8 @@ ifc_configure(const char *ifname, ifc_close(); return -1; } - if (ifc_set_mask(ifname, netmask)) { - printerr("failed to set netmask %s: %s\n", ipaddr_to_string(netmask), strerror(errno)); + if (ifc_set_prefixLength(ifname, prefixLength)) { + printerr("failed to set prefixLength %d: %s\n", prefixLength, strerror(errno)); ifc_close(); return -1; } diff --git a/libsysutils/Android.mk b/libsysutils/Android.mk index dd2b32d..3b1f618 100644 --- a/libsysutils/Android.mk +++ b/libsysutils/Android.mk @@ -1,3 +1,4 @@ +ifneq ($(BUILD_TINY_ANDROID),true) BUILD_LIBSYSUTILS := false ifneq ($(TARGET_SIMULATOR),true) BUILD_LIBSYSUTILS := true @@ -33,3 +34,4 @@ endif include $(BUILD_SHARED_LIBRARY) endif +endif diff --git a/libsysutils/src/FrameworkClient.cpp b/libsysutils/src/FrameworkClient.cpp index 562dd67..2f37055 100644 --- a/libsysutils/src/FrameworkClient.cpp +++ b/libsysutils/src/FrameworkClient.cpp @@ -14,13 +14,15 @@ FrameworkClient::FrameworkClient(int socket) { } int FrameworkClient::sendMsg(const char *msg) { + int ret; if (mSocket < 0) { errno = EHOSTUNREACH; return -1; } pthread_mutex_lock(&mWriteMutex); - if (write(mSocket, msg, strlen(msg) +1) < 0) { + ret = TEMP_FAILURE_RETRY(write(mSocket, msg, strlen(msg) +1)); + if (ret < 0) { SLOGW("Unable to send msg '%s' (%s)", msg, strerror(errno)); } pthread_mutex_unlock(&mWriteMutex); @@ -28,13 +30,13 @@ int FrameworkClient::sendMsg(const char *msg) { } int FrameworkClient::sendMsg(const char *msg, const char *data) { - char *buffer = (char *) alloca(strlen(msg) + strlen(data) + 1); + size_t bufflen = strlen(msg) + strlen(data) + 1; + char *buffer = (char *) alloca(bufflen); if (!buffer) { errno = -ENOMEM; return -1; } - strcpy(buffer, msg); - strcat(buffer, data); + snprintf(buffer, bufflen, "%s%s", msg, data); return sendMsg(buffer); } diff --git a/libsysutils/src/FrameworkListener.cpp b/libsysutils/src/FrameworkListener.cpp index 640b6df..3416ceb 100644 --- a/libsysutils/src/FrameworkListener.cpp +++ b/libsysutils/src/FrameworkListener.cpp @@ -15,6 +15,7 @@ */ #include <errno.h> #include <string.h> +#include <stdlib.h> #define LOG_TAG "FrameworkListener" @@ -33,7 +34,8 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { char buffer[255]; int len; - if ((len = read(c->getSocket(), buffer, sizeof(buffer) -1)) < 0) { + len = TEMP_FAILURE_RETRY(read(c->getSocket(), buffer, sizeof(buffer))); + if (len < 0) { SLOGE("read() failed (%s)", strerror(errno)); return false; } else if (!len) @@ -44,6 +46,7 @@ bool FrameworkListener::onDataAvailable(SocketClient *c) { for (i = 0; i < len; i++) { if (buffer[i] == '\0') { + /* IMPORTANT: dispatchCommand() expects a zero-terminated string */ dispatchCommand(c, buffer + offset); offset = i + 1; } @@ -62,6 +65,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { char tmp[255]; char *p = data; char *q = tmp; + char *qlimit = tmp + sizeof(tmp) - 1; bool esc = false; bool quote = false; int k; @@ -71,6 +75,8 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { while(*p) { if (*p == '\\') { if (esc) { + if (q >= qlimit) + goto overflow; *q++ = '\\'; esc = false; } else @@ -78,11 +84,15 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { p++; continue; } else if (esc) { - if (*p == '"') + if (*p == '"') { + if (q >= qlimit) + goto overflow; *q++ = '"'; - else if (*p == '\\') + } else if (*p == '\\') { + if (q >= qlimit) + goto overflow; *q++ = '\\'; - else { + } else { cli->sendMsg(500, "Unsupported escape sequence", false); goto out; } @@ -100,9 +110,13 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { continue; } + if (q >= qlimit) + goto overflow; *q = *p++; if (!quote && *q == ' ') { *q = '\0'; + if (argc >= CMD_ARGS_MAX) + goto overflow; argv[argc++] = strdup(tmp); memset(tmp, 0, sizeof(tmp)); q = tmp; @@ -111,6 +125,9 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { q++; } + *q = '\0'; + if (argc >= CMD_ARGS_MAX) + goto overflow; argv[argc++] = strdup(tmp); #if 0 for (k = 0; k < argc; k++) { @@ -122,7 +139,7 @@ void FrameworkListener::dispatchCommand(SocketClient *cli, char *data) { cli->sendMsg(500, "Unclosed quotes error", false); goto out; } - + for (i = mCommands->begin(); i != mCommands->end(); ++i) { FrameworkCommand *c = *i; @@ -140,4 +157,8 @@ out: for (j = 0; j < argc; j++) free(argv[j]); return; + +overflow: + cli->sendMsg(500, "Command too long", false); + goto out; } diff --git a/libsysutils/src/NetlinkEvent.cpp b/libsysutils/src/NetlinkEvent.cpp index 86c1f42..c8d3b1f 100644 --- a/libsysutils/src/NetlinkEvent.cpp +++ b/libsysutils/src/NetlinkEvent.cpp @@ -56,45 +56,76 @@ void NetlinkEvent::dump() { } } +/* If the string between 'str' and 'end' begins with 'prefixlen' characters + * from the 'prefix' array, then return 'str + prefixlen', otherwise return + * NULL. + */ +static const char* +has_prefix(const char* str, const char* end, const char* prefix, size_t prefixlen) +{ + if ((end-str) >= (ptrdiff_t)prefixlen && !memcmp(str, prefix, prefixlen)) + return str + prefixlen; + else + return NULL; +} + +/* Same as strlen(x) for constant string literals ONLY */ +#define CONST_STRLEN(x) (sizeof(x)-1) + +/* Convenience macro to call has_prefix with a constant string literal */ +#define HAS_CONST_PREFIX(str,end,prefix) has_prefix((str),(end),prefix,CONST_STRLEN(prefix)) + + bool NetlinkEvent::decode(char *buffer, int size) { - char *s = buffer; - char *end; + const char *s = buffer; + const char *end; int param_idx = 0; int i; int first = 1; + if (size == 0) + return false; + + /* Ensure the buffer is zero-terminated, the code below depends on this */ + buffer[size-1] = '\0'; + end = s + size; while (s < end) { if (first) { - char *p; - for (p = s; *p != '@'; p++); - p++; - mPath = strdup(p); + const char *p; + /* buffer is 0-terminated, no need to check p < end */ + for (p = s; *p != '@'; p++) { + if (!*p) { /* no '@', should not happen */ + return false; + } + } + mPath = strdup(p+1); first = 0; } else { - if (!strncmp(s, "ACTION=", strlen("ACTION="))) { - char *a = s + strlen("ACTION="); + const char* a; + if ((a = HAS_CONST_PREFIX(s, end, "ACTION=")) != NULL) { if (!strcmp(a, "add")) mAction = NlActionAdd; else if (!strcmp(a, "remove")) mAction = NlActionRemove; else if (!strcmp(a, "change")) mAction = NlActionChange; - } else if (!strncmp(s, "SEQNUM=", strlen("SEQNUM="))) - mSeq = atoi(s + strlen("SEQNUM=")); - else if (!strncmp(s, "SUBSYSTEM=", strlen("SUBSYSTEM="))) - mSubsystem = strdup(s + strlen("SUBSYSTEM=")); - else + } else if ((a = HAS_CONST_PREFIX(s, end, "SEQNUM=")) != NULL) { + mSeq = atoi(a); + } else if ((a = HAS_CONST_PREFIX(s, end, "SUBSYSTEM=")) != NULL) { + mSubsystem = strdup(a); + } else if (param_idx < NL_PARAMS_MAX) { mParams[param_idx++] = strdup(s); + } } - s+= strlen(s) + 1; + s += strlen(s) + 1; } return true; } const char *NetlinkEvent::findParam(const char *paramName) { size_t len = strlen(paramName); - for (int i = 0; mParams[i] && i < NL_PARAMS_MAX; ++i) { + for (int i = 0; i < NL_PARAMS_MAX && mParams[i] != NULL; ++i) { const char *ptr = mParams[i] + len; if (!strncmp(mParams[i], paramName, len) && *ptr == '=') return ++ptr; diff --git a/libsysutils/src/NetlinkListener.cpp b/libsysutils/src/NetlinkListener.cpp index fb088e1..ddf6537 100644 --- a/libsysutils/src/NetlinkListener.cpp +++ b/libsysutils/src/NetlinkListener.cpp @@ -39,7 +39,8 @@ bool NetlinkListener::onDataAvailable(SocketClient *cli) struct iovec iov = {mBuffer, sizeof(mBuffer)}; struct msghdr hdr = {&snl, sizeof(snl), &iov, 1, cred_msg, sizeof(cred_msg), 0}; - if ((count = recvmsg(socket, &hdr, 0)) < 0) { + count = TEMP_FAILURE_RETRY(recvmsg(socket, &hdr, 0)); + if (count < 0) { SLOGE("recvmsg failed (%s)", strerror(errno)); return false; } diff --git a/libsysutils/src/ServiceManager.cpp b/libsysutils/src/ServiceManager.cpp index 60b161a..41ac1dd 100644 --- a/libsysutils/src/ServiceManager.cpp +++ b/libsysutils/src/ServiceManager.cpp @@ -1,4 +1,5 @@ #include <errno.h> +#include <string.h> #include <sysutils/ServiceManager.h> @@ -9,7 +10,39 @@ ServiceManager::ServiceManager() { } +/* The service name should not exceed SERVICE_NAME_MAX to avoid + * some weird things. This is due to the fact that: + * + * - Starting a service is done by writing its name to the "ctl.start" + * system property. This triggers the init daemon to actually start + * the service for us. + * + * - Stopping the service is done by writing its name to "ctl.stop" + * in a similar way. + * + * - Reading the status of a service is done by reading the property + * named "init.svc.<name>" + * + * If strlen(<name>) > (PROPERTY_KEY_MAX-1)-9, then you can start/stop + * the service by writing to ctl.start/stop, but you won't be able to + * read its state due to the truncation of "init.svc.<name>" into a + * zero-terminated buffer of PROPERTY_KEY_MAX characters. + */ +#define SERVICE_NAME_MAX (PROPERTY_KEY_MAX-10) + +/* The maximum amount of time to wait for a service to start or stop, + * in micro-seconds (really an approximation) */ +#define SLEEP_MAX_USEC 2000000 /* 2 seconds */ + +/* The minimal sleeping interval between checking for the service's state + * when looping for SLEEP_MAX_USEC */ +#define SLEEP_MIN_USEC 200000 /* 200 msec */ + int ServiceManager::start(const char *name) { + if (strlen(name) > SERVICE_NAME_MAX) { + SLOGE("Service name '%s' is too long", name); + return 0; + } if (isRunning(name)) { SLOGW("Service '%s' is already running", name); return 0; @@ -18,13 +51,14 @@ int ServiceManager::start(const char *name) { SLOGD("Starting service '%s'", name); property_set("ctl.start", name); - int count = 200; - while(count--) { - sched_yield(); + int count = SLEEP_MAX_USEC; + while(count > 0) { + usleep(SLEEP_MIN_USEC); + count -= SLEEP_MIN_USEC; if (isRunning(name)) break; } - if (!count) { + if (count <= 0) { SLOGW("Timed out waiting for service '%s' to start", name); errno = ETIMEDOUT; return -1; @@ -34,6 +68,10 @@ int ServiceManager::start(const char *name) { } int ServiceManager::stop(const char *name) { + if (strlen(name) > SERVICE_NAME_MAX) { + SLOGE("Service name '%s' is too long", name); + return 0; + } if (!isRunning(name)) { SLOGW("Service '%s' is already stopped", name); return 0; @@ -42,28 +80,33 @@ int ServiceManager::stop(const char *name) { SLOGD("Stopping service '%s'", name); property_set("ctl.stop", name); - int count = 200; - while(count--) { - sched_yield(); + int count = SLEEP_MAX_USEC; + while(count > 0) { + usleep(SLEEP_MIN_USEC); + count -= SLEEP_MIN_USEC; if (!isRunning(name)) break; } - if (!count) { + if (count <= 0) { SLOGW("Timed out waiting for service '%s' to stop", name); errno = ETIMEDOUT; return -1; } - SLOGD("Sucessfully stopped '%s'", name); + SLOGD("Successfully stopped '%s'", name); return 0; } bool ServiceManager::isRunning(const char *name) { char propVal[PROPERTY_VALUE_MAX]; - char propName[255]; - - snprintf(propName, sizeof(propVal), "init.svc.%s", name); + char propName[PROPERTY_KEY_MAX]; + int ret; + ret = snprintf(propName, sizeof(propName), "init.svc.%s", name); + if (ret > (int)sizeof(propName)-1) { + SLOGD("Service name '%s' is too long", name); + return false; + } if (property_get(propName, propVal, NULL)) { if (!strcmp(propVal, "running")) diff --git a/libusbhost/Android.mk b/libusbhost/Android.mk new file mode 100644 index 0000000..52b4ead --- /dev/null +++ b/libusbhost/Android.mk @@ -0,0 +1,46 @@ +# +# Copyright (C) 2010 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. +# + +LOCAL_PATH := $(my-dir) + +# Static library for Linux host +# ======================================================== + +ifeq ($(HOST_OS),linux) + +include $(CLEAR_VARS) + +LOCAL_MODULE := libusbhost +LOCAL_SRC_FILES := usbhost.c + +include $(BUILD_HOST_STATIC_LIBRARY) + +endif + +# Shared library for target +# ======================================================== + +include $(CLEAR_VARS) + +LOCAL_MODULE := libusbhost +LOCAL_SRC_FILES := usbhost.c + +LOCAL_CFLAGS := -g -DUSE_LIBLOG + +# needed for logcat +LOCAL_SHARED_LIBRARIES := libcutils + +include $(BUILD_SHARED_LIBRARY) diff --git a/libusbhost/usbhost.c b/libusbhost/usbhost.c new file mode 100644 index 0000000..b1c967d --- /dev/null +++ b/libusbhost/usbhost.c @@ -0,0 +1,585 @@ +/* + * Copyright (C) 2010 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. + */ + +// #define DEBUG 1 +#if DEBUG + +#ifdef USE_LIBLOG +#define LOG_TAG "usbhost" +#include "utils/Log.h" +#define D LOGD +#else +#define D printf +#endif + +#else +#define D(...) +#endif + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/time.h> +#include <sys/inotify.h> +#include <dirent.h> +#include <fcntl.h> +#include <errno.h> +#include <ctype.h> +#include <pthread.h> + +#include <linux/usbdevice_fs.h> +#include <asm/byteorder.h> + +#include "usbhost/usbhost.h" + +#define USB_FS_DIR "/dev/bus/usb" +#define USB_FS_ID_SCANNER "/dev/bus/usb/%d/%d" +#define USB_FS_ID_FORMAT "/dev/bus/usb/%03d/%03d" + +// From drivers/usb/core/devio.c +// I don't know why this isn't in a kernel header +#define MAX_USBFS_BUFFER_SIZE 16384 + +struct usb_host_context { + int fd; +}; + +struct usb_device { + char dev_name[64]; + unsigned char desc[4096]; + int desc_length; + int fd; + int writeable; +}; + +static inline int badname(const char *name) +{ + while(*name) { + if(!isdigit(*name++)) return 1; + } + return 0; +} + +/* returns true if one of the callbacks indicates we are done */ +static int find_existing_devices(usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + void *client_data) +{ + char busname[32], devname[32]; + DIR *busdir , *devdir ; + struct dirent *de; + int done = 0; + + busdir = opendir(USB_FS_DIR); + if(busdir == 0) return 1; + + while ((de = readdir(busdir)) != 0 && !done) { + if(badname(de->d_name)) continue; + + snprintf(busname, sizeof busname, "%s/%s", USB_FS_DIR, de->d_name); + devdir = opendir(busname); + if(devdir == 0) continue; + + while ((de = readdir(devdir)) && !done) { + if(badname(de->d_name)) continue; + + snprintf(devname, sizeof devname, "%s/%s", busname, de->d_name); + done = added_cb(devname, client_data); + } // end of devdir while + closedir(devdir); + } //end of busdir while + closedir(busdir); + + return done; +} + +struct usb_host_context *usb_host_init() +{ + struct usb_host_context *context = calloc(1, sizeof(struct usb_host_context)); + if (!context) { + fprintf(stderr, "out of memory in usb_host_context\n"); + return NULL; + } + context->fd = inotify_init(); + if (context->fd < 0) { + fprintf(stderr, "inotify_init failed\n"); + free(context); + return NULL; + } + return context; +} + +void usb_host_cleanup(struct usb_host_context *context) +{ + close(context->fd); + free(context); +} + +void usb_host_run(struct usb_host_context *context, + usb_device_added_cb added_cb, + usb_device_removed_cb removed_cb, + usb_discovery_done_cb discovery_done_cb, + void *client_data) +{ + struct inotify_event* event; + char event_buf[512]; + char path[100]; + int i, ret, done = 0; + int wd, wds[10]; + int wd_count = sizeof(wds) / sizeof(wds[0]); + + D("Created device discovery thread\n"); + + /* watch for files added and deleted within USB_FS_DIR */ + memset(wds, 0, sizeof(wds)); + /* watch the root for new subdirectories */ + wds[0] = inotify_add_watch(context->fd, USB_FS_DIR, IN_CREATE | IN_DELETE); + if (wds[0] < 0) { + fprintf(stderr, "inotify_add_watch failed\n"); + if (discovery_done_cb) + discovery_done_cb(client_data); + return; + } + + /* watch existing subdirectories of USB_FS_DIR */ + for (i = 1; i < wd_count; i++) { + snprintf(path, sizeof(path), "%s/%03d", USB_FS_DIR, i); + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); + if (ret > 0) + wds[i] = ret; + } + + /* check for existing devices first, after we have inotify set up */ + done = find_existing_devices(added_cb, removed_cb, client_data); + if (discovery_done_cb) + done |= discovery_done_cb(client_data); + + while (!done) { + ret = read(context->fd, event_buf, sizeof(event_buf)); + if (ret >= (int)sizeof(struct inotify_event)) { + event = (struct inotify_event *)event_buf; + wd = event->wd; + if (wd == wds[0]) { + i = atoi(event->name); + snprintf(path, sizeof(path), "%s/%s", USB_FS_DIR, event->name); + D("new subdirectory %s: index: %d\n", path, i); + if (i > 0 && i < wd_count) { + ret = inotify_add_watch(context->fd, path, IN_CREATE | IN_DELETE); + if (ret > 0) + wds[i] = ret; + } + } else { + for (i = 1; i < wd_count && !done; i++) { + if (wd == wds[i]) { + snprintf(path, sizeof(path), "%s/%03d/%s", USB_FS_DIR, i, event->name); + if (event->mask == IN_CREATE) { + D("new device %s\n", path); + done = added_cb(path, client_data); + } else if (event->mask == IN_DELETE) { + D("gone device %s\n", path); + done = removed_cb(path, client_data); + } + } + } + } + } + } +} + +struct usb_device *usb_device_open(const char *dev_name) +{ + int fd, did_retry = 0, writeable = 1; + + D("usb_device_open %s\n", dev_name); + +retry: + fd = open(dev_name, O_RDWR); + if (fd < 0) { + /* if we fail, see if have read-only access */ + fd = open(dev_name, O_RDONLY); + D("usb_device_open open returned %d errno %d\n", fd, errno); + if (fd < 0 && (errno == EACCES || errno == ENOENT) && !did_retry) { + /* work around race condition between inotify and permissions management */ + sleep(1); + did_retry = 1; + goto retry; + } + + if (fd < 0) + return NULL; + writeable = 0; + D("[ usb open read-only %s fd = %d]\n", dev_name, fd); + } + + struct usb_device* result = usb_device_new(dev_name, fd); + if (result) + result->writeable = writeable; + return result; +} + +void usb_device_close(struct usb_device *device) +{ + close(device->fd); + free(device); +} + +struct usb_device *usb_device_new(const char *dev_name, int fd) +{ + struct usb_device *device = calloc(1, sizeof(struct usb_device)); + int length; + + D("usb_device_new %s fd: %d\n", dev_name, fd); + + if (lseek(fd, 0, SEEK_SET) != 0) + goto failed; + length = read(fd, device->desc, sizeof(device->desc)); + D("usb_device_new read returned %d errno %d\n", length, errno); + if (length < 0) + goto failed; + + strncpy(device->dev_name, dev_name, sizeof(device->dev_name) - 1); + device->fd = fd; + device->desc_length = length; + // assume we are writeable, since usb_device_get_fd will only return writeable fds + device->writeable = 1; + return device; + +failed: + close(fd); + free(device); + return NULL; +} + +static int usb_device_reopen_writeable(struct usb_device *device) +{ + if (device->writeable) + return 1; + + int fd = open(device->dev_name, O_RDWR); + if (fd >= 0) { + close(device->fd); + device->fd = fd; + device->writeable = 1; + return 1; + } + D("usb_device_reopen_writeable failed errno %d\n", errno); + return 0; +} + +int usb_device_get_fd(struct usb_device *device) +{ + if (!usb_device_reopen_writeable(device)) + return -1; + return device->fd; +} + +const char* usb_device_get_name(struct usb_device *device) +{ + return device->dev_name; +} + +int usb_device_get_unique_id(struct usb_device *device) +{ + int bus = 0, dev = 0; + sscanf(device->dev_name, USB_FS_ID_SCANNER, &bus, &dev); + return bus * 1000 + dev; +} + +int usb_device_get_unique_id_from_name(const char* name) +{ + int bus = 0, dev = 0; + sscanf(name, USB_FS_ID_SCANNER, &bus, &dev); + return bus * 1000 + dev; +} + +char* usb_device_get_name_from_unique_id(int id) +{ + int bus = id / 1000; + int dev = id % 1000; + char* result = (char *)calloc(1, strlen(USB_FS_ID_FORMAT)); + snprintf(result, strlen(USB_FS_ID_FORMAT) - 1, USB_FS_ID_FORMAT, bus, dev); + return result; +} + +uint16_t usb_device_get_vendor_id(struct usb_device *device) +{ + struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; + return __le16_to_cpu(desc->idVendor); +} + +uint16_t usb_device_get_product_id(struct usb_device *device) +{ + struct usb_device_descriptor* desc = (struct usb_device_descriptor*)device->desc; + return __le16_to_cpu(desc->idProduct); +} + +const struct usb_device_descriptor* usb_device_get_device_descriptor(struct usb_device *device) +{ + return (struct usb_device_descriptor*)device->desc; +} + +char* usb_device_get_string(struct usb_device *device, int id) +{ + char string[256]; + __u16 buffer[128]; + __u16 languages[128]; + int i, result; + int languageCount = 0; + + string[0] = 0; + memset(languages, 0, sizeof(languages)); + + // read list of supported languages + result = usb_device_control_transfer(device, + USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) | 0, 0, languages, sizeof(languages), 0); + if (result > 0) + languageCount = (result - 2) / 2; + + for (i = 1; i <= languageCount; i++) { + memset(buffer, 0, sizeof(buffer)); + + result = usb_device_control_transfer(device, + USB_DIR_IN|USB_TYPE_STANDARD|USB_RECIP_DEVICE, USB_REQ_GET_DESCRIPTOR, + (USB_DT_STRING << 8) | id, languages[i], buffer, sizeof(buffer), 0); + if (result > 0) { + int i; + // skip first word, and copy the rest to the string, changing shorts to bytes. + result /= 2; + for (i = 1; i < result; i++) + string[i - 1] = buffer[i]; + string[i - 1] = 0; + return strdup(string); + } + } + + return NULL; +} + +char* usb_device_get_manufacturer_name(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iManufacturer) + return usb_device_get_string(device, desc->iManufacturer); + else + return NULL; +} + +char* usb_device_get_product_name(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iProduct) + return usb_device_get_string(device, desc->iProduct); + else + return NULL; +} + +char* usb_device_get_serial(struct usb_device *device) +{ + struct usb_device_descriptor *desc = (struct usb_device_descriptor *)device->desc; + + if (desc->iSerialNumber) + return usb_device_get_string(device, desc->iSerialNumber); + else + return NULL; +} + +int usb_device_is_writeable(struct usb_device *device) +{ + return device->writeable; +} + +void usb_descriptor_iter_init(struct usb_device *device, struct usb_descriptor_iter *iter) +{ + iter->config = device->desc; + iter->config_end = device->desc + device->desc_length; + iter->curr_desc = device->desc; +} + +struct usb_descriptor_header *usb_descriptor_iter_next(struct usb_descriptor_iter *iter) +{ + struct usb_descriptor_header* next; + if (iter->curr_desc >= iter->config_end) + return NULL; + next = (struct usb_descriptor_header*)iter->curr_desc; + iter->curr_desc += next->bLength; + return next; +} + +int usb_device_claim_interface(struct usb_device *device, unsigned int interface) +{ + return ioctl(device->fd, USBDEVFS_CLAIMINTERFACE, &interface); +} + +int usb_device_release_interface(struct usb_device *device, unsigned int interface) +{ + return ioctl(device->fd, USBDEVFS_RELEASEINTERFACE, &interface); +} + +int usb_device_connect_kernel_driver(struct usb_device *device, + unsigned int interface, int connect) +{ + struct usbdevfs_ioctl ctl; + + ctl.ifno = interface; + ctl.ioctl_code = (connect ? USBDEVFS_CONNECT : USBDEVFS_DISCONNECT); + ctl.data = NULL; + return ioctl(device->fd, USBDEVFS_IOCTL, &ctl); +} + +int usb_device_control_transfer(struct usb_device *device, + int requestType, + int request, + int value, + int index, + void* buffer, + int length, + unsigned int timeout) +{ + struct usbdevfs_ctrltransfer ctrl; + + // this usually requires read/write permission + if (!usb_device_reopen_writeable(device)) + return -1; + + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.bRequestType = requestType; + ctrl.bRequest = request; + ctrl.wValue = value; + ctrl.wIndex = index; + ctrl.wLength = length; + ctrl.data = buffer; + ctrl.timeout = timeout; + return ioctl(device->fd, USBDEVFS_CONTROL, &ctrl); +} + +int usb_device_bulk_transfer(struct usb_device *device, + int endpoint, + void* buffer, + int length, + unsigned int timeout) +{ + struct usbdevfs_bulktransfer ctrl; + + // need to limit request size to avoid EINVAL + if (length > MAX_USBFS_BUFFER_SIZE) + length = MAX_USBFS_BUFFER_SIZE; + + memset(&ctrl, 0, sizeof(ctrl)); + ctrl.ep = endpoint; + ctrl.len = length; + ctrl.data = buffer; + ctrl.timeout = timeout; + return ioctl(device->fd, USBDEVFS_BULK, &ctrl); +} + +struct usb_request *usb_request_new(struct usb_device *dev, + const struct usb_endpoint_descriptor *ep_desc) +{ + struct usbdevfs_urb *urb = calloc(1, sizeof(struct usbdevfs_urb)); + if (!urb) + return NULL; + + if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) + urb->type = USBDEVFS_URB_TYPE_BULK; + else if ((ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) + urb->type = USBDEVFS_URB_TYPE_INTERRUPT; + else { + D("Unsupported endpoint type %d", ep_desc->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); + free(urb); + return NULL; + } + urb->endpoint = ep_desc->bEndpointAddress; + + struct usb_request *req = calloc(1, sizeof(struct usb_request)); + if (!req) { + free(urb); + return NULL; + } + + req->dev = dev; + req->max_packet_size = __le16_to_cpu(ep_desc->wMaxPacketSize); + req->private_data = urb; + req->endpoint = urb->endpoint; + urb->usercontext = req; + + return req; +} + +void usb_request_free(struct usb_request *req) +{ + free(req->private_data); + free(req); +} + +int usb_request_queue(struct usb_request *req) +{ + struct usbdevfs_urb *urb = (struct usbdevfs_urb*)req->private_data; + int res; + + urb->status = -1; + urb->buffer = req->buffer; + // need to limit request size to avoid EINVAL + if (req->buffer_length > MAX_USBFS_BUFFER_SIZE) + urb->buffer_length = MAX_USBFS_BUFFER_SIZE; + else + urb->buffer_length = req->buffer_length; + + do { + res = ioctl(req->dev->fd, USBDEVFS_SUBMITURB, urb); + } while((res < 0) && (errno == EINTR)); + + return res; +} + +struct usb_request *usb_request_wait(struct usb_device *dev) +{ + struct usbdevfs_urb *urb = NULL; + struct usb_request *req = NULL; + int res; + + while (1) { + int res = ioctl(dev->fd, USBDEVFS_REAPURB, &urb); + D("USBDEVFS_REAPURB returned %d\n", res); + if (res < 0) { + if(errno == EINTR) { + continue; + } + D("[ reap urb - error ]\n"); + return NULL; + } else { + D("[ urb @%p status = %d, actual = %d ]\n", + urb, urb->status, urb->actual_length); + req = (struct usb_request*)urb->usercontext; + req->actual_length = urb->actual_length; + } + break; + } + return req; +} + +int usb_request_cancel(struct usb_request *req) +{ + struct usbdevfs_urb *urb = ((struct usbdevfs_urb*)req->private_data); + return ioctl(req->dev->fd, USBDEVFS_DISCARDURB, &urb); +} + diff --git a/logcat/event.logtags b/logcat/event.logtags index 0083c57..2e814ff 100644 --- a/logcat/event.logtags +++ b/logcat/event.logtags @@ -63,47 +63,7 @@ # ZygoteInit class preloading ends: 3030 boot_progress_preload_end (time|2|3) -# dvm_gc_info: LIST (LONG, LONG, LONG) -# -# First LONG: -# -# [63] 1 -# [62-24] ASCII process identifier -# [23-12] GC time in ms -# [11- 0] Bytes freed -# -# Second LONG (aggregated heap info): -# -# [63-62] 10 -# [61-60] Reserved; must be zero -# [59-48] Objects freed -# [47-36] Actual size (current footprint) -# [35-24] Allowed size (current hard max) -# [23-12] Objects allocated -# [11- 0] Bytes allocated -# -# Third LONG (zygote heap info): -# -# [63-62] 11 -# [61-60] Reserved; must be zero -# [59-48] Soft limit -# [47-36] Actual size (current footprint) -# [35-24] Allowed size (current hard max) -# [23-12] Objects allocated -# [11- 0] Bytes allocated -# -# Fourth LONG: -# -# [63-48] Reserved; must be zero -# [47-36] dlmallocFootprint -# [35-24] mallinfo: total allocated space -# [23-12] External byte limit -# [11- 0] External bytes allocated -# -# See HeapDebug.c -# -20001 dvm_gc_info (custom|2),(custom|2),(custom|2),(custom|2) -20002 dvm_gc_madvise_info (total|1|2),(zygote|1|2) +# Dalvik VM 20003 dvm_lock_sample (process|3),(main|1|5),(thread|3),(time|1|3),(file|3),(line|1|5),(ownerfile|3),(ownerline|1|5),(sample_percent|1|6) 75000 sqlite_mem_alarm_current (current|1|2) @@ -115,31 +75,20 @@ 50000 menu_item_selected (Menu type where 0 is options and 1 is context|1|5),(Menu item title|3) 50001 menu_opened (Menu type where 0 is options and 1 is context|1|5) -# Wi-Fi network state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Detailed state ordinal (as defined by NetworkInfo.DetailedState) -50021 wifi_network_state_changed (network_state|1|5) - -# Wi-Fi supplicant state changed: -# [31- 6] Reserved for future use -# [ 5- 0] Supplicant state ordinal (as defined by SupplicantState) -50022 wifi_supplicant_state_changed (supplicant_state|1|5) - -# Wi-Fi driver state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Driver start (1) or stopped (0) -50023 wifi_driver_state_changed (driver_state|1|5) - -# Wi-Fi interface configuration state changed: -# [31- 1] Reserved for future use -# [ 0- 0] Interface configuration succeeded (1) or failed (0) -50024 wifi_interface_configuration_state_changed (IP_configuration|1|5) - -# Wi-Fi supplicant connection state changed: -# [31- 2] Reserved for future use -# [ 1- 0] Connected to supplicant (1) or disconnected from supplicant (0), -# or supplicant died (2) -50025 wifi_supplicant_connection_state_changed (connected|1|5) +# HSM wifi state change +# Hierarchical state class name (as defined in WifiStateTracker.java) +# Logged on every state change in the hierarchical state machine +50021 wifi_state_changed (wifi_state|3) +# HSM wifi event +# [31-16] Reserved for future use +# [15 - 0] HSM event (as defined in WifiStateTracker.java) +# Logged when an event is handled in a hierarchical state +50022 wifi_event_handled (wifi_event|1|5) +# Supplicant state change +# [31-13] Reserved for future use +# [8 - 0] Supplicant state (as defined in SupplicantState.java) +# Logged when the supplicant switches to a new state +50023 wifi_supplicant_state_changed (supplicant_state|1|5) # Do not change these names without updating tag in: #//device/dalvik/libcore/luni/src/main/native/org_apache_harmony_luni_platform_OSNetworkSystem.c diff --git a/logcat/logcat.cpp b/logcat/logcat.cpp index 5acdf77..96b68ef 100644 --- a/logcat/logcat.cpp +++ b/logcat/logcat.cpp @@ -402,8 +402,9 @@ static void show_help(const char *cmd) " -d dump the log and then exit (don't block)\n" " -t <count> print only the most recent <count> lines (implies -d)\n" " -g get the size of the log's ring buffer and exit\n" - " -b <buffer> request alternate ring buffer\n" - " ('main' (default), 'radio', 'events')\n" + " -b <buffer> Request alternate ring buffer, 'main', 'system', 'radio'\n" + " or 'events'. Multiple -b parameters are allowed and the\n" + " results are interleaved. The default is -b main -b system.\n" " -B output the log in binary"); diff --git a/mkbootimg/Android.mk b/mkbootimg/Android.mk index 18f0ff3..2a97c26 100644 --- a/mkbootimg/Android.mk +++ b/mkbootimg/Android.mk @@ -9,4 +9,4 @@ LOCAL_MODULE := mkbootimg include $(BUILD_HOST_EXECUTABLE) -$(call dist-for-goals,droid,$(LOCAL_BUILT_MODULE)) +$(call dist-for-goals,dist_files,$(LOCAL_BUILT_MODULE)) diff --git a/netcfg/netcfg.c b/netcfg/netcfg.c index 9cd883a..c520075 100644 --- a/netcfg/netcfg.c +++ b/netcfg/netcfg.c @@ -20,6 +20,7 @@ #include <errno.h> #include <dirent.h> #include <netinet/ether.h> +#include <netinet/if_ether.h> #include <netutils/ifc.h> #include <netutils/dhcp.h> @@ -44,21 +45,30 @@ const char *ipaddr(in_addr_t addr) void usage(void) { fprintf(stderr,"usage: netcfg [<interface> {dhcp|up|down}]\n"); - exit(1); + exit(1); } int dump_interface(const char *name) { - unsigned addr, mask, flags; - - if(ifc_get_info(name, &addr, &mask, &flags)) { + unsigned addr, prefixLength, flags; + unsigned char hwbuf[ETH_ALEN]; + + if(ifc_get_info(name, &addr, &prefixLength, &flags)) { return 0; } printf("%-8s %s ", name, flags & 1 ? "UP " : "DOWN"); - printf("%-16s", ipaddr(addr)); - printf("%-16s", ipaddr(mask)); - printf("0x%08x\n", flags); + printf("%40s", ipaddr(addr)); + printf("/%-4d", prefixLength); + printf("0x%08x ", flags); + if (!ifc_get_hwaddr(name, hwbuf)) { + int i; + for(i=0; i < (ETH_ALEN-1); i++) + printf("%02x:", hwbuf[i]); + printf("%02x\n", hwbuf[i]); + } else { + printf("\n"); + } return 0; } @@ -66,10 +76,10 @@ int dump_interfaces(void) { DIR *d; struct dirent *de; - + d = opendir("/sys/class/net"); if(d == 0) return -1; - + while((de = readdir(d))) { if(de->d_name[0] == '.') continue; dump_interface(de->d_name); diff --git a/patch.txt b/patch.txt deleted file mode 100644 index 258965d..0000000 --- a/patch.txt +++ /dev/null @@ -1,16 +0,0 @@ -diff --git a/init/util.c b/init/util.c -index 4d98cc2..0667593 100755 ---- a/init/util.c -+++ b/init/util.c -@@ -657,8 +657,9 @@ static void get_hardware_name(void) - if (x) { - x += 2; - n = 0; -- while (*x && !isspace(*x)) { -- hardware[n++] = tolower(*x); -+ while (*x && *x != '\n') { -+ if (!isspace(*x)) -+ hardware[n++] = tolower(*x); - x++; - if (n == 31) break; - } diff --git a/rootdir/etc/init.goldfish.rc b/rootdir/etc/init.goldfish.rc index 569555c..1ac09ca 100644 --- a/rootdir/etc/init.goldfish.rc +++ b/rootdir/etc/init.goldfish.rc @@ -1,5 +1,12 @@ +on early-init + export EXTERNAL_STORAGE /mnt/sdcard + mkdir /mnt/sdcard 0000 system system + # for backwards compatibility + symlink /mnt/sdcard /sdcard + on boot setprop ARGH ARGH + setprop net.eth0.gw 10.0.2.2 setprop net.eth0.dns1 10.0.2.3 setprop net.gprs.local-ip 10.0.2.15 setprop ro.radio.use-ppp no @@ -16,6 +23,11 @@ on boot stop dund stop akmd +# start essential services + start qemud + start goldfish-logcat + start goldfish-setup + setprop ro.setupwizard.mode EMULATOR # enable Google-specific location features, @@ -36,6 +48,8 @@ on boot # something else. service goldfish-setup /system/etc/init.goldfish.sh + user root + group root oneshot service qemud /system/bin/qemud @@ -46,7 +60,7 @@ service qemud /system/bin/qemud # program to check wether it runs on the emulator # if it does, it redirects its output to the device # named by the androidboot.console kernel option -# if not, is simply exit immediately +# if not, is simply exits immediately service goldfish-logcat /system/bin/logcat -Q oneshot diff --git a/rootdir/etc/init.goldfish.sh b/rootdir/etc/init.goldfish.sh index cfa2c82..1156dd7 100755 --- a/rootdir/etc/init.goldfish.sh +++ b/rootdir/etc/init.goldfish.sh @@ -1,8 +1,26 @@ #!/system/bin/sh +# Setup networking when boot starts ifconfig eth0 10.0.2.15 netmask 255.255.255.0 up route add default gw 10.0.2.2 dev eth0 +# ro.kernel.android.qemud is normally set when we +# want the RIL (radio interface layer) to talk to +# the emulated modem through qemud. +# +# However, this will be undefined in two cases: +# +# - When we want the RIL to talk directly to a guest +# serial device that is connected to a host serial +# device by the emulator. +# +# - We don't want to use the RIL but the VM-based +# modem emulation that runs inside the guest system +# instead. +# +# The following detects the latter case and sets up the +# system for it. +# qemud=`getprop ro.kernel.android.qemud` case "$qemud" in "") @@ -18,17 +36,18 @@ case "$qemud" in ;; esac -num_dns=`getprop ro.kernel.android.ndns` +# Setup additionnal DNS servers if needed +num_dns=`getprop ro.kernel.ndns` case "$num_dns" in 2) setprop net.eth0.dns2 10.0.2.4 - ;; + ;; 3) setprop net.eth0.dns2 10.0.2.4 - setprop net.eth0.dns3 10.0.2.5 - ;; + setprop net.eth0.dns3 10.0.2.5 + ;; 4) setprop net.eth0.dns2 10.0.2.4 - setprop net.eth0.dns3 10.0.2.5 - setprop net.eth0.dns4 10.0.2.6 - ;; + setprop net.eth0.dns3 10.0.2.5 + setprop net.eth0.dns4 10.0.2.6 + ;; esac # disable boot animation for a faster boot sequence when needed @@ -42,10 +61,6 @@ esac # /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 - # set up the second interface (for inter-emulator connections) # if required my_ip=`getprop net.shared_net_ip` diff --git a/rootdir/etc/ueventd.goldfish.rc b/rootdir/etc/ueventd.goldfish.rc index f4262fb..8de7049 100644 --- a/rootdir/etc/ueventd.goldfish.rc +++ b/rootdir/etc/ueventd.goldfish.rc @@ -1,2 +1,5 @@ +# These settings are specific to running under the Android emulator /dev/qemu_trace 0666 system system /dev/qemu_pipe 0666 system system +/dev/ttyS* 0666 system system +/proc 0666 system system diff --git a/rootdir/init.rc b/rootdir/init.rc index 90c017b..657797e 100644 --- a/rootdir/init.rc +++ b/rootdir/init.rc @@ -1,6 +1,9 @@ on early-init start ueventd +# create mountpoints + mkdir /mnt 0775 root system + on init sysclktz 0 @@ -14,10 +17,9 @@ loglevel 3 export ANDROID_ROOT /system export ANDROID_ASSETS /system/app export ANDROID_DATA /data - export EXTERNAL_STORAGE /mnt/sdcard export ASEC_MOUNTPOINT /mnt/asec export LOOP_MOUNTPOINT /mnt/obb - export BOOTCLASSPATH /system/framework/core.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar + export BOOTCLASSPATH /system/framework/core.jar:/system/framework/apache-xml.jar:/system/framework/bouncycastle.jar:/system/framework/ext.jar:/system/framework/framework.jar:/system/framework/android.policy.jar:/system/framework/services.jar:/system/framework/core-junit.jar # Backward compatibility symlink /system/etc /etc @@ -27,18 +29,11 @@ loglevel 3 # but someday that may change. symlink /system/vendor /vendor -# create mountpoints - mkdir /mnt 0775 root system - mkdir /mnt/sdcard 0000 system system - # Create cgroup mount point for cpu accounting mkdir /acct mount cgroup none /acct cpuacct mkdir /acct/uid -# Backwards Compat - XXX: Going away in G* - symlink /mnt/sdcard /sdcard - mkdir /system mkdir /data 0771 system system mkdir /cache 0770 system cache @@ -101,6 +96,32 @@ on post-fs # once everything is setup, no need to modify / mount rootfs rootfs / ro remount + # We chown/chmod /cache again so because mount is run as root + defaults + chown system cache /cache + chmod 0770 /cache + + # This may have been created by the recovery system with odd permissions + chown system cache /cache/recovery + chmod 0770 /cache/recovery + + #change permissions on vmallocinfo so we can grab it from bugreports + chown root log /proc/vmallocinfo + chmod 0440 /proc/vmallocinfo + + #change permissions on kmsg & sysrq-trigger so bugreports can grab kthread stacks + chown root system /proc/kmsg + chmod 0440 /proc/kmsg + chown root system /proc/sysrq-trigger + chmod 0220 /proc/sysrq-trigger + + # create the lost+found directories, so as to enforce our permissions + mkdir /cache/lost+found 0770 + + # double check the perms, in case lost+found already exists, and set owner + chown root root /cache/lost+found + chmod 0770 /cache/lost+found + +on post-fs-data # We chown/chmod /data again so because mount is run as root + defaults chown system system /data chmod 0771 /data @@ -124,25 +145,7 @@ on post-fs write /proc/apanic_console 1 - # Same reason as /data above - chown system cache /cache - chmod 0770 /cache - - # This may have been created by the recovery system with odd permissions - chown system cache /cache/recovery - chmod 0770 /cache/recovery - - #change permissions on vmallocinfo so we can grab it from bugreports - chown root log /proc/vmallocinfo - chmod 0440 /proc/vmallocinfo - - #change permissions on kmsg & sysrq-trigger so bugreports can grab kthread stacks - chown root system /proc/kmsg - chmod 0440 /proc/kmsg - chown root system /proc/sysrq-trigger - chmod 0220 /proc/sysrq-trigger - -# create basic filesystem structure + # create basic filesystem structure mkdir /data/misc 01771 system misc mkdir /data/misc/bluetoothd 0770 bluetooth bluetooth mkdir /data/misc/bluetooth 0770 system system @@ -168,18 +171,19 @@ on post-fs # create the lost+found directories, so as to enforce our permissions mkdir /data/lost+found 0770 - mkdir /cache/lost+found 0770 # double check the perms, in case lost+found already exists, and set owner chown root root /data/lost+found chmod 0770 /data/lost+found - chown root root /cache/lost+found - chmod 0770 /cache/lost+found - # create data/drm directory + # create directory for DRM plug-ins mkdir /data/drm 0774 drm drm - chown drm drm /data/drm - chmod 0774 /data/drm + + # If there is no fs-post-data action in the init.<device>.rc file, you + # must uncomment this line, otherwise encrypted filesystems + # won't work. + # Set indication (checked by vold) that we have finished this action + #setprop vold.post_fs_data_done 1 on boot # basic network init @@ -204,15 +208,28 @@ on boot # Define the memory thresholds at which the above process classes will # be killed. These numbers are in pages (4k). - setprop ro.FOREGROUND_APP_MEM 2048 - setprop ro.VISIBLE_APP_MEM 3072 - setprop ro.PERCEPTIBLE_APP_MEM 4096 - setprop ro.HEAVY_WEIGHT_APP_MEM 4096 - setprop ro.SECONDARY_SERVER_MEM 6144 - setprop ro.BACKUP_APP_MEM 6144 - setprop ro.HOME_APP_MEM 6144 - setprop ro.HIDDEN_APP_MEM 7168 - setprop ro.EMPTY_APP_MEM 8192 + # These are currently tuned for tablets with approx 1GB RAM. + setprop ro.FOREGROUND_APP_MEM 8192 + setprop ro.VISIBLE_APP_MEM 10240 + setprop ro.PERCEPTIBLE_APP_MEM 12288 + setprop ro.HEAVY_WEIGHT_APP_MEM 12288 + setprop ro.SECONDARY_SERVER_MEM 14336 + setprop ro.BACKUP_APP_MEM 14336 + setprop ro.HOME_APP_MEM 14336 + setprop ro.HIDDEN_APP_MEM 16384 + setprop ro.EMPTY_APP_MEM 20480 + + # Old values for phones. Should probably be adjusted up for the next + # phone version. + #setprop ro.FOREGROUND_APP_MEM 2048 + #setprop ro.VISIBLE_APP_MEM 3072 + #setprop ro.PERCEPTIBLE_APP_MEM 4096 + #setprop ro.HEAVY_WEIGHT_APP_MEM 4096 + #setprop ro.SECONDARY_SERVER_MEM 6144 + #setprop ro.BACKUP_APP_MEM 6144 + #setprop ro.HOME_APP_MEM 6144 + #setprop ro.HIDDEN_APP_MEM 7168 + #setprop ro.EMPTY_APP_MEM 8192 # Write value must be consistent with the above properties. # Note that the driver only supports 6 slots, so we have combined some of @@ -222,7 +239,7 @@ on boot write /proc/sys/vm/overcommit_memory 1 write /proc/sys/vm/min_free_order_shift 4 - write /sys/module/lowmemorykiller/parameters/minfree 2048,3072,4096,6144,7168,8192 + write /sys/module/lowmemorykiller/parameters/minfree 8192,10240,12288,14336,16384,20480 # Set init its forked children's oom_adj. write /proc/1/oom_adj -16 @@ -278,24 +295,54 @@ on boot setprop net.tcp.buffersize.edge 4093,26280,35040,4096,16384,35040 setprop net.tcp.buffersize.gprs 4092,8760,11680,4096,8760,11680 - class_start default +# Set this property so surfaceflinger is not started by system_init + setprop system_init.startsurfaceflinger 0 + + class_start core + class_start main + +on nonencrypted + class_start late_start + +on property:vold.decrypt=trigger_reset_main + class_reset main + +on property:vold.decrypt=trigger_load_persist_props + load_persist_props + +on property:vold.decrypt=trigger_post_fs_data + trigger post-fs-data + +on property:vold.decrypt=trigger_restart_min_framework + class_start main + +on property:vold.decrypt=trigger_restart_framework + class_start main + class_start late_start + +on property:vold.decrypt=trigger_shutdown_framework + class_reset late_start + class_reset main ## Daemon processes to be run by init. ## service ueventd /sbin/ueventd + class core critical service console /system/bin/sh + class core console disabled user shell group log -on property:ro.secure=0 +on property:ro.debuggable=1 start console # adbd is controlled by the persist.service.adb.enable system property service adbd /sbin/adbd + class core disabled # adbd on at boot in emulator @@ -309,58 +356,74 @@ on property:persist.service.adb.enable=0 stop adbd service servicemanager /system/bin/servicemanager + class core user system + group system critical onrestart restart zygote onrestart restart media service vold /system/bin/vold + class core socket vold stream 0660 root mount ioprio be 2 service netd /system/bin/netd + class main socket netd stream 0660 root system socket dnsproxyd stream 0660 root inet service debuggerd /system/bin/debuggerd + class main service ril-daemon /system/bin/rild + class late_start socket rild stream 660 root radio socket rild-debug stream 660 radio system user root group radio cache inet misc audio sdcard_rw +service surfaceflinger /system/bin/surfaceflinger + class main + user system + group graphics + onrestart restart zygote + service zygote /system/bin/app_process -Xzygote /system/bin --zygote --start-system-server + class main socket zygote stream 666 onrestart write /sys/android_power/request_state wake onrestart write /sys/power/state on + onrestart restart surfaceflinger onrestart restart media onrestart restart netd service drm /system/bin/drmserver + class main user drm - group system root inet - -service drmio /system/bin/drmioserver - user drmio + group system inet service media /system/bin/mediaserver + class main user media - group system audio camera graphics inet net_bt net_bt_admin net_raw + group audio camera inet net_bt net_bt_admin ioprio rt 4 service bootanim /system/bin/bootanimation + class main user graphics group graphics disabled oneshot service dbus /system/bin/dbus-daemon --system --nofork + class main socket dbus stream 660 bluetooth bluetooth user bluetooth group bluetooth net_bt_admin service bluetoothd /system/bin/bluetoothd -n + class main socket bluetooth stream 660 bluetooth bluetooth socket dbus_bluetooth stream 660 bluetooth bluetooth # init.rc does not yet support applying capabilities, so run as root and @@ -368,37 +431,16 @@ service bluetoothd /system/bin/bluetoothd -n group bluetooth net_bt_admin misc disabled -service hfag /system/bin/sdptool add --channel=10 HFAG - user bluetooth - group bluetooth net_bt_admin - disabled - oneshot - -service hsag /system/bin/sdptool add --channel=11 HSAG - user bluetooth - group bluetooth net_bt_admin - disabled - oneshot - -service opush /system/bin/sdptool add --channel=12 OPUSH - user bluetooth - group bluetooth net_bt_admin - disabled - oneshot - -service pbap /system/bin/sdptool add --channel=19 PBAP - user bluetooth - group bluetooth net_bt_admin - disabled - oneshot - service installd /system/bin/installd + class main socket installd stream 600 system system service flash_recovery /system/etc/install-recovery.sh + class main oneshot service racoon /system/bin/racoon + class main socket racoon stream 600 system system # racoon will setuid to vpn after getting necessary resources. group net_admin @@ -406,6 +448,7 @@ service racoon /system/bin/racoon oneshot service mtpd /system/bin/mtpd + class main socket mtpd stream 600 system system user vpn group vpn net_admin net_raw @@ -413,11 +456,13 @@ service mtpd /system/bin/mtpd oneshot service keystore /system/bin/keystore /data/misc/keystore + class main user keystore group keystore socket keystore stream 666 service dumpstate /system/bin/dumpstate -s + class main socket dumpstate stream 0660 shell log disabled oneshot diff --git a/rootdir/ueventd.rc b/rootdir/ueventd.rc index d475c44..51a4337 100644 --- a/rootdir/ueventd.rc +++ b/rootdir/ueventd.rc @@ -23,7 +23,6 @@ /dev/android_adb 0660 adb adb /dev/android_adb_enable 0660 adb adb /dev/ttyMSM0 0600 bluetooth bluetooth -/dev/ttyHS0 0600 bluetooth bluetooth /dev/uinput 0660 system bluetooth /dev/alarm 0664 system radio /dev/tty0 0660 root system @@ -69,6 +68,7 @@ /dev/qmi1 0640 radio radio /dev/qmi2 0640 radio radio /dev/bus/usb/* 0660 root usb +/dev/mtp_usb 0660 root mtp /dev/usb_accessory 0660 root usb # CDMA radio interface MUX diff --git a/sdcard/sdcard.c b/sdcard/sdcard.c index 82e6354..7112ebf 100644 --- a/sdcard/sdcard.c +++ b/sdcard/sdcard.c @@ -25,6 +25,7 @@ #include <sys/statfs.h> #include <sys/uio.h> #include <dirent.h> +#include <ctype.h> #include <private/android_filesystem_config.h> @@ -55,10 +56,6 @@ * kernel, you must rollback the refcount to reflect the reference the * kernel did not actually acquire * - * - * Bugs: - * - * - need to move/rename node on RENAME */ #define FUSE_TRACE 0 @@ -89,15 +86,21 @@ struct node { __u64 nid; __u64 gen; - struct node *next; - struct node *child; - struct node *all; - struct node *parent; + struct node *next; /* per-dir sibling list */ + struct node *child; /* first contained file by this dir */ + struct node *all; /* global node list */ + struct node *parent; /* containing directory */ __u32 refcount; __u32 namelen; - char name[1]; + char *name; + /* If non-null, this is the real name of the file in the underlying storage. + * This may differ from the field "name" only by case. + * strlen(actual_name) will always equal strlen(name), so it is safe to use + * namelen for both fields. + */ + char *actual_name; }; struct fuse { @@ -112,10 +115,24 @@ struct fuse { char rootpath[1024]; }; +static unsigned uid = -1; +static unsigned gid = -1; + #define PATH_BUFFER_SIZE 1024 -char *node_get_path(struct node *node, char *buf, const char *name) +#define NO_CASE_SENSITIVE_MATCH 0 +#define CASE_SENSITIVE_MATCH 1 + +/* + * Get the real-life absolute path to a node. + * node: start at this node + * buf: storage for returned string + * name: append this string to path if set + */ +char *do_node_get_path(struct node *node, char *buf, const char *name, int match_case_insensitive) { + struct node *in_node = node; + const char *in_name = name; char *out = buf + PATH_BUFFER_SIZE - 1; int len; out[0] = 0; @@ -126,7 +143,7 @@ char *node_get_path(struct node *node, char *buf, const char *name) } while (node) { - name = node->name; + name = (node->actual_name ? node->actual_name : node->name); len = node->namelen; node = node->parent; start: @@ -134,11 +151,45 @@ char *node_get_path(struct node *node, char *buf, const char *name) return 0; out -= len; memcpy(out, name, len); - out --; - out[0] = '/'; + /* avoid double slash at beginning of path */ + if (out[0] != '/') { + out --; + out[0] = '/'; + } } - return out; + /* If we are searching for a file within node (rather than computing node's path) + * and fail, then we need to look for a case insensitive match. + */ + if (in_name && match_case_insensitive && access(out, F_OK) != 0) { + char *path, buffer[PATH_BUFFER_SIZE]; + DIR* dir; + struct dirent* entry; + path = do_node_get_path(in_node, buffer, NULL, NO_CASE_SENSITIVE_MATCH); + dir = opendir(path); + if (!dir) { + ERROR("opendir %s failed: %s", path, strerror(errno)); + return out; + } + + while ((entry = readdir(dir))) { + if (!strcasecmp(entry->d_name, in_name)) { + /* we have a match - replace the name */ + len = strlen(in_name); + memcpy(buf + PATH_BUFFER_SIZE - len - 1, entry->d_name, len); + break; + } + } + closedir(dir); + } + + return out; +} + +char *node_get_path(struct node *node, char *buf, const char *name) +{ + /* We look for case insensitive matches by default */ + return do_node_get_path(node, buf, name, CASE_SENSITIVE_MATCH); } void attr_from_stat(struct fuse_attr *attr, struct stat *s) @@ -189,28 +240,84 @@ int node_get_attr(struct node *node, struct fuse_attr *attr) return 0; } +static void add_node_to_parent(struct node *node, struct node *parent) { + node->parent = parent; + node->next = parent->child; + parent->child = node; + parent->refcount++; +} + +/* Check to see if our parent directory already has a file with a name + * that differs only by case. If we find one, store it in the actual_name + * field so node_get_path will map it to this file in the underlying storage. + */ +static void node_find_actual_name(struct node *node) +{ + char *path, buffer[PATH_BUFFER_SIZE]; + const char *node_name = node->name; + DIR* dir; + struct dirent* entry; + + if (!node->parent) return; + + path = node_get_path(node->parent, buffer, 0); + dir = opendir(path); + if (!dir) { + ERROR("opendir %s failed: %s", path, strerror(errno)); + return; + } + + while ((entry = readdir(dir))) { + const char *test_name = entry->d_name; + if (strcmp(test_name, node_name) && !strcasecmp(test_name, node_name)) { + /* we have a match - differs but only by case */ + node->actual_name = strdup(test_name); + if (!node->actual_name) { + ERROR("strdup failed - out of memory\n"); + exit(1); + } + break; + } + } + closedir(dir); +} + struct node *node_create(struct node *parent, const char *name, __u64 nid, __u64 gen) { struct node *node; int namelen = strlen(name); - node = calloc(1, sizeof(struct node) + namelen); + node = calloc(1, sizeof(struct node)); if (node == 0) { return 0; } + node->name = malloc(namelen + 1); + if (node->name == 0) { + free(node); + return 0; + } node->nid = nid; node->gen = gen; - node->parent = parent; - node->next = parent->child; - parent->child = node; + add_node_to_parent(node, parent); memcpy(node->name, name, namelen + 1); node->namelen = namelen; - parent->refcount++; - + node_find_actual_name(node); return node; } +static char *rename_node(struct node *node, const char *name) +{ + node->namelen = strlen(name); + char *newname = realloc(node->name, node->namelen + 1); + if (newname == 0) + return 0; + node->name = newname; + memcpy(node->name, name, node->namelen + 1); + node_find_actual_name(node); + return node->name; +} + void fuse_init(struct fuse *fuse, int fd, const char *path) { fuse->fd = fd; @@ -227,8 +334,8 @@ void fuse_init(struct fuse *fuse, int fd, const char *path) fuse->root.all = 0; fuse->root.refcount = 2; - strcpy(fuse->root.name, path); - fuse->root.namelen = strlen(fuse->root.name); + fuse->root.name = 0; + rename_node(&fuse->root, path); } static inline void *id_to_ptr(__u64 nid) @@ -271,6 +378,37 @@ struct node *lookup_child_by_inode(struct node *node, __u64 nid) return 0; } +static void dec_refcount(struct node *node) { + if (node->refcount > 0) { + node->refcount--; + TRACE("dec_refcount %p(%s) -> %d\n", node, node->name, node->refcount); + } else { + ERROR("Zero refcnt %p\n", node); + } + } + +static struct node *remove_child(struct node *parent, __u64 nid) +{ + struct node *prev = 0; + struct node *node; + + for (node = parent->child; node; node = node->next) { + if (node->nid == nid) { + if (prev) { + prev->next = node->next; + } else { + parent->child = node->next; + } + node->next = 0; + node->parent = 0; + dec_refcount(parent); + return node; + } + prev = node; + } + return 0; +} + struct node *node_lookup(struct fuse *fuse, struct node *parent, const char *name, struct fuse_attr *attr) { @@ -305,7 +443,7 @@ struct node *node_lookup(struct fuse *fuse, struct node *parent, const char *nam void node_release(struct node *node) { TRACE("RELEASE %p (%s) rc=%d\n", node, node->name, node->refcount); - node->refcount--; + dec_refcount(node); if (node->refcount == 0) { if (node->parent->child == node) { node->parent->child = node->parent->child->next; @@ -326,8 +464,10 @@ void node_release(struct node *node) node->next = 0; /* TODO: remove debugging - poison memory */ - memset(node, 0xef, sizeof(*node) + strlen(node->name)); - + memset(node->name, 0xef, node->namelen); + free(node->name); + free(node->actual_name); + memset(node, 0xfc, sizeof(*node)); free(node); } } @@ -427,7 +567,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da struct fuse_getattr_in *req = data; struct fuse_attr_out out; - TRACE("GETATTR flags=%x fh=%llx\n",req->getattr_flags, req->fh); + TRACE("GETATTR flags=%x fh=%llx\n", req->getattr_flags, req->fh); memset(&out, 0, sizeof(out)); node_get_attr(node, &out.attr); @@ -439,15 +579,60 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da case FUSE_SETATTR: { /* setattr_in -> attr_out */ struct fuse_setattr_in *req = data; struct fuse_attr_out out; + char *path, buffer[PATH_BUFFER_SIZE]; + int res = 0; + struct timespec times[2]; + TRACE("SETATTR fh=%llx id=%llx valid=%x\n", req->fh, hdr->nodeid, req->valid); - /* XXX */ + /* XXX: incomplete implementation on purpose. chmod/chown + * should NEVER be implemented.*/ + + path = node_get_path(node, buffer, 0); + if (req->valid & FATTR_SIZE) + res = truncate(path, req->size); + if (res) + goto getout; + + /* Handle changing atime and mtime. If FATTR_ATIME_and FATTR_ATIME_NOW + * are both set, then set it to the current time. Else, set it to the + * time specified in the request. Same goes for mtime. Use utimensat(2) + * as it allows ATIME and MTIME to be changed independently, and has + * nanosecond resolution which fuse also has. + */ + if (req->valid & (FATTR_ATIME | FATTR_MTIME)) { + times[0].tv_nsec = UTIME_OMIT; + times[1].tv_nsec = UTIME_OMIT; + if (req->valid & FATTR_ATIME) { + if (req->valid & FATTR_ATIME_NOW) { + times[0].tv_nsec = UTIME_NOW; + } else { + times[0].tv_sec = req->atime; + times[0].tv_nsec = req->atimensec; + } + } + if (req->valid & FATTR_MTIME) { + if (req->valid & FATTR_MTIME_NOW) { + times[1].tv_nsec = UTIME_NOW; + } else { + times[1].tv_sec = req->mtime; + times[1].tv_nsec = req->mtimensec; + } + } + TRACE("Calling utimensat on %s with atime %ld, mtime=%ld\n", path, times[0].tv_sec, times[1].tv_sec); + res = utimensat(-1, path, times, 0); + } + getout: memset(&out, 0, sizeof(out)); node_get_attr(node, &out.attr); out.attr_valid = 10; - fuse_reply(fuse, hdr->unique, &out, sizeof(out)); + + if (res) + fuse_status(fuse, hdr->unique, -errno); + else + fuse_reply(fuse, hdr->unique, &out, sizeof(out)); return; } // case FUSE_READLINK: @@ -457,6 +642,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da char *path, buffer[PATH_BUFFER_SIZE]; char *name = ((char*) data) + sizeof(*req); int res; + TRACE("MKNOD %s @ %llx\n", name, hdr->nodeid); path = node_get_path(node, buffer, name); @@ -475,6 +661,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da char *path, buffer[PATH_BUFFER_SIZE]; char *name = ((char*) data) + sizeof(*req); int res; + TRACE("MKDIR %s @ %llx 0%o\n", name, hdr->nodeid, req->mode); path = node_get_path(node, buffer, name); @@ -511,19 +698,49 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da char *newname = oldname + strlen(oldname) + 1; char *oldpath, oldbuffer[PATH_BUFFER_SIZE]; char *newpath, newbuffer[PATH_BUFFER_SIZE]; - struct node *newnode; + struct node *target; + struct node *newparent; int res; - newnode = lookup_by_inode(fuse, req->newdir); - if (!newnode) { + TRACE("RENAME %s->%s @ %llx\n", oldname, newname, hdr->nodeid); + + target = lookup_child_by_name(node, oldname); + if (!target) { fuse_status(fuse, hdr->unique, -ENOENT); return; } - oldpath = node_get_path(node, oldbuffer, oldname); - newpath = node_get_path(newnode, newbuffer, newname); + + newparent = lookup_by_inode(fuse, req->newdir); + if (!newparent) { + fuse_status(fuse, hdr->unique, -ENOENT); + return; + } + if (newparent == node) { + /* Special case for renaming a file where destination + * is same path differing only by case. + * In this case we don't want to look for a case insensitive match. + * This allows commands like "mv foo FOO" to work as expected. + */ + newpath = do_node_get_path(newparent, newbuffer, newname, NO_CASE_SENSITIVE_MATCH); + } else { + newpath = node_get_path(newparent, newbuffer, newname); + } + + if (!remove_child(node, target->nid)) { + ERROR("RENAME remove_child not found"); + fuse_status(fuse, hdr->unique, -ENOENT); + return; + } + if (!rename_node(target, newname)) { + fuse_status(fuse, hdr->unique, -ENOMEM); + return; + } + add_node_to_parent(target, newparent); res = rename(oldpath, newpath); + TRACE("RENAME result %d\n", res); + fuse_status(fuse, hdr->unique, res ? -errno : 0); return; } @@ -565,7 +782,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da fuse_status(fuse, hdr->unique, -EINVAL); return; } - res = pread(h->fd, buffer, req->size, req->offset); + res = pread64(h->fd, buffer, req->size, req->offset); if (res < 0) { fuse_status(fuse, hdr->unique, errno); return; @@ -579,7 +796,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da struct handle *h = id_to_ptr(req->fh); int res; TRACE("WRITE %p(%d) %u@%llu\n", h, h->fd, req->size, req->offset); - res = pwrite(h->fd, ((char*) data) + sizeof(*req), req->size, req->offset); + res = pwrite64(h->fd, ((char*) data) + sizeof(*req), req->size, req->offset); if (res < 0) { fuse_status(fuse, hdr->unique, errno); return; @@ -661,13 +878,19 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da struct dirent *de; struct dirhandle *h = id_to_ptr(req->fh); TRACE("READDIR %p\n", h); + if (req->offset == 0) { + /* rewinddir() might have been called above us, so rewind here too */ + TRACE("calling rewinddir()\n"); + rewinddir(h->d); + } de = readdir(h->d); if (!de) { fuse_status(fuse, hdr->unique, 0); return; } fde->ino = FUSE_UNKNOWN_INO; - fde->off = 0; + /* increment the offset so we can detect when rewinddir() seeks back to the beginning */ + fde->off = req->offset + 1; fde->type = de->d_type; fde->namelen = strlen(de->d_name); memcpy(fde->name, de->d_name, fde->namelen + 1); @@ -695,7 +918,7 @@ void handle_fuse_request(struct fuse *fuse, struct fuse_in_header *hdr, void *da out.major = FUSE_KERNEL_VERSION; out.minor = FUSE_KERNEL_MINOR_VERSION; out.max_readahead = req->max_readahead; - out.flags = 0; + out.flags = FUSE_ATOMIC_O_TRUNC; out.max_background = 32; out.congestion_threshold = 32; out.max_write = 256 * 1024; @@ -735,30 +958,44 @@ void handle_fuse_requests(struct fuse *fuse) } } +static int usage() +{ + ERROR("usage: sdcard [-l -f] <path> <uid> <gid>\n\n\t-l force file names to lower case when creating new files\n\t-f fix up file system before starting (repairs bad file name case and group ownership)\n"); + return -1; +} + int main(int argc, char **argv) { struct fuse fuse; char opts[256]; int fd; int res; - unsigned uid; - unsigned gid; - const char *path; - - if (argc != 4) { - ERROR("usage: sdcard <path> <uid> <gid>\n"); - return -1; + const char *path = NULL; + int i; + + for (i = 1; i < argc; i++) { + char* arg = argv[i]; + if (!path) + path = arg; + else if (uid == -1) + uid = strtoul(arg, 0, 10); + else if (gid == -1) + gid = strtoul(arg, 0, 10); + else { + ERROR("too many arguments\n"); + return usage(); + } } - uid = strtoul(argv[2], 0, 10); - gid = strtoul(argv[3], 0, 10); - if (!uid || !gid) { + if (!path) { + ERROR("no path specified\n"); + return usage(); + } + if (uid <= 0 || gid <= 0) { ERROR("uid and gid must be nonzero\n"); - return -1; + return usage(); } - path = argv[1]; - /* cleanup from previous instance, if necessary */ umount2(MOUNT_POINT, 2); @@ -100,7 +100,7 @@ signame_to_signum(const char *p) p += 3; for (i = 0; i < NSIG; ++i) - if (strcasecmp (p, sys_signame[i]) == 0) + if (sys_signame[i] && (strcasecmp (p, sys_signame[i]) == 0)) return i; return -1; } diff --git a/toolbox/Android.mk b/toolbox/Android.mk index ef3980a..ff01172 100644 --- a/toolbox/Android.mk +++ b/toolbox/Android.mk @@ -57,10 +57,11 @@ TOOLS := \ lsof LOCAL_SRC_FILES:= \ + dynarray.c \ toolbox.c \ $(patsubst %,%.c,$(TOOLS)) -LOCAL_SHARED_LIBRARIES := libcutils libc +LOCAL_SHARED_LIBRARIES := libcutils libc libusbhost LOCAL_MODULE:= toolbox diff --git a/toolbox/cmp.c b/toolbox/cmp.c index 9bd2e19..80635ad 100644 --- a/toolbox/cmp.c +++ b/toolbox/cmp.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include <stdint.h> +#include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <errno.h> diff --git a/toolbox/date.c b/toolbox/date.c index 13b5210..35ef846 100644 --- a/toolbox/date.c +++ b/toolbox/date.c @@ -1,10 +1,12 @@ #include <stdio.h> #include <stdlib.h> +#include <unistd.h> #include <fcntl.h> #include <string.h> #include <errno.h> #include <time.h> #include <linux/android_alarm.h> +#include <sys/ioctl.h> static void settime(char *s) { struct tm tm; diff --git a/toolbox/dd.h b/toolbox/dd.h index 794a464..cca1024 100644 --- a/toolbox/dd.h +++ b/toolbox/dd.h @@ -35,6 +35,8 @@ * @(#)dd.h 8.3 (Berkeley) 4/2/94 */ +#include <stdint.h> + /* Input/output stream state. */ typedef struct { u_char *db; /* buffer address */ diff --git a/toolbox/dynarray.c b/toolbox/dynarray.c new file mode 100644 index 0000000..e9b7b03 --- /dev/null +++ b/toolbox/dynarray.c @@ -0,0 +1,103 @@ +#include "dynarray.h" +#include <stdlib.h> +#include <limits.h> + +void +dynarray_init( dynarray_t *a ) +{ + a->count = a->capacity = 0; + a->items = NULL; +} + + +static void +dynarray_reserve_more( dynarray_t *a, int count ) +{ + int old_cap = a->capacity; + int new_cap = old_cap; + const int max_cap = INT_MAX/sizeof(void*); + void** new_items; + int new_count = a->count + count; + + if (count <= 0) + return; + + if (count > max_cap - a->count) + abort(); + + new_count = a->count + count; + + while (new_cap < new_count) { + old_cap = new_cap; + new_cap += (new_cap >> 2) + 4; + if (new_cap < old_cap || new_cap > max_cap) { + new_cap = max_cap; + } + } + new_items = realloc(a->items, new_cap*sizeof(void*)); + if (new_items == NULL) + abort(); + + a->items = new_items; + a->capacity = new_cap; +} + +void +dynarray_append( dynarray_t *a, void* item ) +{ + if (a->count >= a->capacity) + dynarray_reserve_more(a, 1); + + a->items[a->count++] = item; +} + +void +dynarray_done( dynarray_t *a ) +{ + free(a->items); + a->items = NULL; + a->count = a->capacity = 0; +} + +// string arrays + +void strlist_init( strlist_t *list ) +{ + dynarray_init(list); +} + +void strlist_append_b( strlist_t *list, const void* str, size_t slen ) +{ + char *copy = malloc(slen+1); + memcpy(copy, str, slen); + copy[slen] = '\0'; + dynarray_append(list, copy); +} + +void strlist_append_dup( strlist_t *list, const char *str) +{ + strlist_append_b(list, str, strlen(str)); +} + +void strlist_done( strlist_t *list ) +{ + STRLIST_FOREACH(list, string, free(string)); + dynarray_done(list); +} + +static int strlist_compare_strings(const void* a, const void* b) +{ + const char *sa = *(const char **)a; + const char *sb = *(const char **)b; + return strcmp(sa, sb); +} + +void strlist_sort( strlist_t *list ) +{ + if (list->count > 0) { + qsort(list->items, + (size_t)list->count, + sizeof(void*), + strlist_compare_strings); + } +} diff --git a/toolbox/dynarray.h b/toolbox/dynarray.h new file mode 100644 index 0000000..f73fb3b --- /dev/null +++ b/toolbox/dynarray.h @@ -0,0 +1,80 @@ +#ifndef DYNARRAY_H +#define DYNARRAY_H + +#include <stddef.h> + +/* simple dynamic array of pointers */ +typedef struct { + int count; + int capacity; + void** items; +} dynarray_t; + +#define DYNARRAY_INITIALIZER { 0, 0, NULL } + +void dynarray_init( dynarray_t *a ); +void dynarray_done( dynarray_t *a ); + +void dynarray_append( dynarray_t *a, void* item ); + +/* Used to iterate over a dynarray_t + * _array :: pointer to the array + * _item_type :: type of objects pointed to by the array + * _item :: name of a local variable defined within the loop + * with type '_item_type' + * _stmnt :: C statement that will be executed in each iteration. + * + * You case use 'break' and 'continue' within _stmnt + * + * This macro is only intended for simple uses. I.e. do not add or + * remove items from the array during iteration. + */ +#define DYNARRAY_FOREACH_TYPE(_array,_item_type,_item,_stmnt) \ + do { \ + int _nn_##__LINE__ = 0; \ + for (;_nn_##__LINE__ < (_array)->count; ++ _nn_##__LINE__) { \ + _item_type _item = (_item_type)(_array)->items[_nn_##__LINE__]; \ + _stmnt; \ + } \ + } while (0) + +#define DYNARRAY_FOREACH(_array,_item,_stmnt) \ + DYNARRAY_FOREACH_TYPE(_array,void *,_item,_stmnt) + +/* Simple dynamic string arrays + * + * NOTE: A strlist_t owns the strings it references. + */ +typedef dynarray_t strlist_t; + +#define STRLIST_INITIALIZER DYNARRAY_INITIALIZER + +/* Used to iterate over a strlist_t + * _list :: pointer to strlist_t object + * _string :: name of local variable name defined within the loop with + * type 'char*' + * _stmnt :: C statement executed in each iteration + * + * This macro is only intended for simple uses. Do not add or remove items + * to/from the list during iteration. + */ +#define STRLIST_FOREACH(_list,_string,_stmnt) \ + DYNARRAY_FOREACH_TYPE(_list,char *,_string,_stmnt) + +void strlist_init( strlist_t *list ); + +/* note: strlist_done will free all the strings owned by the list */ +void strlist_done( strlist_t *list ); + +/* append a new string made of the first 'slen' characters from 'str' + * followed by a trailing zero. + */ +void strlist_append_b( strlist_t *list, const void* str, size_t slen ); + +/* append the copy of a given input string to a strlist_t */ +void strlist_append_dup( strlist_t *list, const char *str); + +/* sort the strings in a given list (using strcmp) */ +void strlist_sort( strlist_t *list ); + +#endif /* DYNARRAY_H */
\ No newline at end of file diff --git a/toolbox/getprop.c b/toolbox/getprop.c index fc80a4d..c001fda 100644 --- a/toolbox/getprop.c +++ b/toolbox/getprop.c @@ -1,13 +1,34 @@ #include <stdio.h> +#include <stdlib.h> #include <cutils/properties.h> #include <sys/system_properties.h> +#include "dynarray.h" -static void proplist(const char *key, const char *name, - void *user __attribute__((unused))) +static void record_prop(const char* key, const char* name, void* opaque) { - printf("[%s]: [%s]\n", key, name); + strlist_t* list = opaque; + char temp[PROP_VALUE_MAX + PROP_NAME_MAX + 16]; + snprintf(temp, sizeof temp, "[%s]: [%s]", key, name); + strlist_append_dup(list, temp); +} + +static void list_properties(void) +{ + strlist_t list[1] = { STRLIST_INITIALIZER }; + + /* Record properties in the string list */ + (void)property_list(record_prop, list); + + /* Sort everything */ + strlist_sort(list); + + /* print everything */ + STRLIST_FOREACH(list, str, printf("%s\n", str)); + + /* voila */ + strlist_done(list); } int __system_property_wait(prop_info *pi); @@ -17,7 +38,7 @@ int getprop_main(int argc, char *argv[]) int n = 0; if (argc == 1) { - (void)property_list(proplist, NULL); + list_properties(); } else { char value[PROPERTY_VALUE_MAX]; char *default_value; diff --git a/toolbox/hd.c b/toolbox/hd.c index 1f7d179..da31245 100644 --- a/toolbox/hd.c +++ b/toolbox/hd.c @@ -2,6 +2,7 @@ #include <stdlib.h> #include <string.h> #include <stdint.h> +#include <unistd.h> #include <fcntl.h> #include <sys/ioctl.h> #include <errno.h> diff --git a/toolbox/ioctl.c b/toolbox/ioctl.c index e28f2a4..fb555d2 100644 --- a/toolbox/ioctl.c +++ b/toolbox/ioctl.c @@ -1,11 +1,14 @@ #include <stdio.h> #include <stdlib.h> +#include <stdint.h> #include <fcntl.h> +#include <getopt.h> #include <string.h> #include <linux/kd.h> #include <linux/vt.h> #include <errno.h> #include <pthread.h> +#include <sys/ioctl.h> int ioctl_main(int argc, char *argv[]) { diff --git a/toolbox/ls.c b/toolbox/ls.c index 962bf47..b08e378 100644 --- a/toolbox/ls.c +++ b/toolbox/ls.c @@ -15,128 +15,7 @@ #include <linux/kdev_t.h> #include <limits.h> -// dynamic arrays -typedef struct { - int count; - int capacity; - void** items; -} dynarray_t; - -#define DYNARRAY_INITIALIZER { 0, 0, NULL } - -static void dynarray_init( dynarray_t *a ) -{ - a->count = a->capacity = 0; - a->items = NULL; -} - -static void dynarray_reserve_more( dynarray_t *a, int count ) -{ - int old_cap = a->capacity; - int new_cap = old_cap; - const int max_cap = INT_MAX/sizeof(void*); - void** new_items; - int new_count = a->count + count; - - if (count <= 0) - return; - - if (count > max_cap - a->count) - abort(); - - new_count = a->count + count; - - while (new_cap < new_count) { - old_cap = new_cap; - new_cap += (new_cap >> 2) + 4; - if (new_cap < old_cap || new_cap > max_cap) { - new_cap = max_cap; - } - } - new_items = realloc(a->items, new_cap*sizeof(void*)); - if (new_items == NULL) - abort(); - - a->items = new_items; - a->capacity = new_cap; -} - -static void dynarray_append( dynarray_t *a, void* item ) -{ - if (a->count >= a->capacity) - dynarray_reserve_more(a, 1); - - a->items[a->count++] = item; -} - -static void dynarray_done( dynarray_t *a ) -{ - free(a->items); - a->items = NULL; - a->count = a->capacity = 0; -} - -#define DYNARRAY_FOREACH_TYPE(_array,_item_type,_item,_stmnt) \ - do { \ - int _nn_##__LINE__ = 0; \ - for (;_nn_##__LINE__ < (_array)->count; ++ _nn_##__LINE__) { \ - _item_type _item = (_item_type)(_array)->items[_nn_##__LINE__]; \ - _stmnt; \ - } \ - } while (0) - -#define DYNARRAY_FOREACH(_array,_item,_stmnt) \ - DYNARRAY_FOREACH_TYPE(_array,void *,_item,_stmnt) - -// string arrays - -typedef dynarray_t strlist_t; - -#define STRLIST_INITIALIZER DYNARRAY_INITIALIZER - -#define STRLIST_FOREACH(_list,_string,_stmnt) \ - DYNARRAY_FOREACH_TYPE(_list,char *,_string,_stmnt) - -static void strlist_init( strlist_t *list ) -{ - dynarray_init(list); -} - -static void strlist_append_b( strlist_t *list, const void* str, size_t slen ) -{ - char *copy = malloc(slen+1); - memcpy(copy, str, slen); - copy[slen] = '\0'; - dynarray_append(list, copy); -} - -static void strlist_append_dup( strlist_t *list, const char *str) -{ - strlist_append_b(list, str, strlen(str)); -} - -static void strlist_done( strlist_t *list ) -{ - STRLIST_FOREACH(list, string, free(string)); - dynarray_done(list); -} - -static int strlist_compare_strings(const void* a, const void* b) -{ - const char *sa = *(const char **)a; - const char *sb = *(const char **)b; - return strcmp(sa, sb); -} - -static void strlist_sort( strlist_t *list ) -{ - if (list->count > 0) { - qsort(list->items, - (size_t)list->count, - sizeof(void*), - strlist_compare_strings); - } -} +#include "dynarray.h" // bits for flags argument #define LIST_LONG (1 << 0) @@ -144,6 +23,7 @@ static void strlist_sort( strlist_t *list ) #define LIST_RECURSIVE (1 << 2) #define LIST_DIRECTORIES (1 << 3) #define LIST_SIZE (1 << 4) +#define LIST_LONG_NUMERIC (1 << 5) // fwd static int listpath(const char *name, int flags); @@ -165,7 +45,7 @@ static char mode2kind(unsigned mode) static void mode2str(unsigned mode, char *out) { *out++ = mode2kind(mode); - + *out++ = (mode & 0400) ? 'r' : '-'; *out++ = (mode & 0200) ? 'w' : '-'; if(mode & 04000) { @@ -279,12 +159,17 @@ static int listfile_long(const char *path, int flags) } mode2str(s.st_mode, mode); - user2str(s.st_uid, user); - group2str(s.st_gid, group); + if (flags & LIST_LONG_NUMERIC) { + sprintf(user, "%ld", s.st_uid); + sprintf(group, "%ld", s.st_gid); + } else { + user2str(s.st_uid, user); + group2str(s.st_gid, group); + } strftime(date, 32, "%Y-%m-%d %H:%M", localtime((const time_t*)&s.st_mtime)); date[31] = 0; - + // 12345678901234567890123456789012345678901234567890123456789012345678901234567890 // MMMMMMMM UUUUUUUU GGGGGGGGG XXXXXXXX YYYY-MM-DD HH:MM NAME (->LINK) @@ -292,7 +177,7 @@ static int listfile_long(const char *path, int flags) case S_IFBLK: case S_IFCHR: printf("%s %-8s %-8s %3d, %3d %s %s\n", - mode, user, group, + mode, user, group, (int) MAJOR(s.st_rdev), (int) MINOR(s.st_rdev), date, name); break; @@ -306,7 +191,7 @@ static int listfile_long(const char *path, int flags) len = readlink(path, linkto, 256); if(len < 0) return -1; - + if(len > 255) { linkto[252] = '.'; linkto[253] = '.'; @@ -315,7 +200,7 @@ static int listfile_long(const char *path, int flags) } else { linkto[len] = 0; } - + printf("%s %-8s %-8s %s %s -> %s\n", mode, user, group, date, name, linkto); break; @@ -358,7 +243,7 @@ static int listdir(const char *name, int flags) DIR *d; struct dirent *de; strlist_t files = STRLIST_INITIALIZER; - + d = opendir(name); if(d == 0) { fprintf(stderr, "opendir failed, %s\n", strerror(errno)); @@ -463,7 +348,7 @@ int ls_main(int argc, char **argv) { int flags = 0; int listed = 0; - + if(argc > 1) { int i; int err = 0; @@ -476,6 +361,7 @@ int ls_main(int argc, char **argv) while (arg[0]) { switch (arg[0]) { case 'l': flags |= LIST_LONG; break; + case 'n': flags |= LIST_LONG | LIST_LONG_NUMERIC; break; case 's': flags |= LIST_SIZE; break; case 'R': flags |= LIST_RECURSIVE; break; case 'd': flags |= LIST_DIRECTORIES; break; @@ -502,7 +388,7 @@ int ls_main(int argc, char **argv) return err; } } - - // list working directory if no files or directories were specified + + // list working directory if no files or directories were specified return listpath(".", flags); } diff --git a/toolbox/lsof.c b/toolbox/lsof.c index 99891db..c55384b 100644 --- a/toolbox/lsof.c +++ b/toolbox/lsof.c @@ -196,28 +196,37 @@ void lsof_dumpinfo(pid_t pid) int lsof_main(int argc, char *argv[]) { - DIR *dir = opendir("/proc"); - if (dir == NULL) { - fprintf(stderr, "Couldn't open /proc\n"); - return -1; + long int pid = 0; + char* endptr; + if (argc == 2) { + pid = strtol(argv[1], &endptr, 10); } print_header(); - struct dirent* de; - while ((de = readdir(dir))) { - if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) - continue; - - // Only inspect directories that are PID numbers - char* endptr; - long int pid = strtol(de->d_name, &endptr, 10); - if (*endptr != '\0') - continue; - + if (pid) { lsof_dumpinfo(pid); + } else { + DIR *dir = opendir("/proc"); + if (dir == NULL) { + fprintf(stderr, "Couldn't open /proc\n"); + return -1; + } + + struct dirent* de; + while ((de = readdir(dir))) { + if (!strcmp(de->d_name, ".") || !strcmp(de->d_name, "..")) + continue; + + // Only inspect directories that are PID numbers + pid = strtol(de->d_name, &endptr, 10); + if (*endptr != '\0') + continue; + + lsof_dumpinfo(pid); + } + closedir(dir); } - closedir(dir); return 0; } diff --git a/toolbox/lsusb.c b/toolbox/lsusb.c new file mode 100644 index 0000000..236e74b --- /dev/null +++ b/toolbox/lsusb.c @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2010 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. + */ + +#include <endian.h> +#include <errno.h> +#include <stdio.h> +#include <stdint.h> +#include <string.h> + +#include <usbhost/usbhost.h> + +static int verbose = 0; +static char str_buff[4096]; + +static const char *get_str(struct usb_device *dev, int id) +{ + char *str = usb_device_get_string(dev, id); + + if (id && str) { + strlcpy(str_buff, str, sizeof(str_buff)); + free(str); + } else { + snprintf(str_buff, sizeof(str_buff), "%02x", id); + } + + return str_buff; +} + + +static void lsusb_parse_device_descriptor(struct usb_device *dev, + struct usb_device_descriptor *desc) +{ + printf(" Device Descriptor\n"); + printf("\tbcdUSB: %04x\n", letoh16(desc->bcdUSB)); + printf("\tbDeviceClass: %02x\n", desc->bDeviceClass); + printf("\tbDeviceSubClass: %02x\n", desc->bDeviceSubClass); + printf("\tbDeviceProtocol: %02x\n", desc->bDeviceProtocol); + printf("\tbMaxPacketSize0: %02x\n", desc->bMaxPacketSize0); + printf("\tidVendor: %04x\n", letoh16(desc->idVendor)); + printf("\tidProduct: %04x\n", letoh16(desc->idProduct)); + printf("\tbcdDevice: %04x\n", letoh16(desc->bcdDevice)); + printf("\tiManufacturer: %s\n", get_str(dev, desc->iManufacturer)); + printf("\tiProduct: %s\n", get_str(dev, desc->iProduct)); + printf("\tiSerialNumber: %s\n", get_str(dev,desc->iSerialNumber)); + printf("\tbNumConfiguration: %02x\n", desc->bNumConfigurations); + printf("\n"); +} + +static void lsusb_parse_config_descriptor(struct usb_device *dev, + struct usb_config_descriptor *desc) +{ + printf(" Config Descriptor\n"); + printf("\twTotalLength: %04x\n", letoh16(desc->wTotalLength)); + printf("\tbNumInterfaces: %02x\n", desc->bNumInterfaces); + printf("\tbConfigurationValue: %02x\n", desc->bConfigurationValue); + printf("\tiConfiguration: %s\n", get_str(dev, desc->iConfiguration)); + printf("\tbmAttributes: %02x\n", desc->bmAttributes); + printf("\tbMaxPower: %d mA\n", desc->bMaxPower * 2); + printf("\n"); +} + +static void lsusb_parse_interface_descriptor(struct usb_device *dev, + struct usb_interface_descriptor *desc) +{ + printf(" Interface Descriptor\n"); + printf("\tbInterfaceNumber: %02x\n", desc->bInterfaceNumber); + printf("\tbAlternateSetting: %02x\n", desc->bAlternateSetting); + printf("\tbNumEndpoints: %02x\n", desc->bNumEndpoints); + printf("\tbInterfaceClass: %02x\n", desc->bInterfaceClass); + printf("\tbInterfaceSubClass: %02x\n", desc->bInterfaceSubClass); + printf("\tbInterfaceProtocol: %02x\n", desc->bInterfaceProtocol); + printf("\tiInterface: %s\n", get_str(dev, desc->iInterface)); + printf("\n"); +} + +static void lsusb_parse_endpoint_descriptor(struct usb_device *dev, + struct usb_endpoint_descriptor *desc) +{ + printf(" Endpoint Descriptor\n"); + printf("\tbEndpointAddress: %02x\n", desc->bEndpointAddress); + printf("\tbmAttributes: %02x\n", desc->bmAttributes); + printf("\twMaxPacketSize: %02x\n", letoh16(desc->wMaxPacketSize)); + printf("\tbInterval: %02x\n", desc->bInterval); + printf("\tbRefresh: %02x\n", desc->bRefresh); + printf("\tbSynchAddress: %02x\n", desc->bSynchAddress); + printf("\n"); +} + +static void lsusb_dump_descriptor(struct usb_device *dev, + struct usb_descriptor_header *desc) +{ + int i; + printf(" Descriptor type %02x\n", desc->bDescriptorType); + + for (i = 0; i < desc->bLength; i++ ) { + if ((i % 16) == 0) + printf("\t%02x:", i); + printf(" %02x", ((uint8_t *)desc)[i]); + if ((i % 16) == 15) + printf("\n"); + } + + if ((i % 16) != 0) + printf("\n"); + printf("\n"); +} + +static void lsusb_parse_descriptor(struct usb_device *dev, + struct usb_descriptor_header *desc) +{ + switch (desc->bDescriptorType) { + case USB_DT_DEVICE: + lsusb_parse_device_descriptor(dev, (struct usb_device_descriptor *) desc); + break; + + case USB_DT_CONFIG: + lsusb_parse_config_descriptor(dev, (struct usb_config_descriptor *) desc); + break; + + case USB_DT_INTERFACE: + lsusb_parse_interface_descriptor(dev, (struct usb_interface_descriptor *) desc); + break; + + case USB_DT_ENDPOINT: + lsusb_parse_endpoint_descriptor(dev, (struct usb_endpoint_descriptor *) desc); + break; + + default: + lsusb_dump_descriptor(dev, desc); + + break; + } +} + +static int lsusb_device_added(const char *dev_name, void *client_data) +{ + struct usb_device *dev = usb_device_open(dev_name); + + if (!dev) { + fprintf(stderr, "can't open device %s: %s\n", dev_name, strerror(errno)); + return 0; + } + + if (verbose) { + struct usb_descriptor_iter iter; + struct usb_descriptor_header *desc; + + printf("%s:\n", dev_name); + + usb_descriptor_iter_init(dev, &iter); + + while ((desc = usb_descriptor_iter_next(&iter)) != NULL) + lsusb_parse_descriptor(dev, desc); + + } else { + uint16_t vid, pid; + char *mfg_name, *product_name, *serial; + + vid = usb_device_get_vendor_id(dev); + pid = usb_device_get_product_id(dev); + mfg_name = usb_device_get_manufacturer_name(dev); + product_name = usb_device_get_product_name(dev); + serial = usb_device_get_serial(dev); + + printf("%s: %04x:%04x %s %s %s\n", dev_name, vid, pid, + mfg_name, product_name, serial); + + free(mfg_name); + free(product_name); + free(serial); + } + + usb_device_close(dev); + + return 0; +} + +static int lsusb_device_removed(const char *dev_name, void *client_data) +{ + return 0; +} + + +static int lsusb_discovery_done(void *client_data) +{ + return 1; +} + + + +int lsusb_main(int argc, char **argv) +{ + struct usb_host_context *ctx; + + if (argc == 2 && !strcmp(argv[1], "-v")) + verbose = 1; + + ctx = usb_host_init(); + if (!ctx) { + perror("usb_host_init:"); + return 1; + } + + usb_host_run(ctx, + lsusb_device_added, + lsusb_device_removed, + lsusb_discovery_done, + NULL); + + usb_host_cleanup(ctx); + + return 0; +} + diff --git a/toolbox/mount.c b/toolbox/mount.c index 472c952..82ecc56 100644 --- a/toolbox/mount.c +++ b/toolbox/mount.c @@ -222,9 +222,50 @@ static int print_mounts() return 0; } +static int get_mounts_dev_dir(const char *arg, char **dev, char **dir) +{ + FILE *f; + char mount_dev[256]; + char mount_dir[256]; + char mount_type[256]; + char mount_opts[256]; + int mount_freq; + int mount_passno; + int match; + + f = fopen("/proc/mounts", "r"); + if (!f) { + fprintf(stdout, "could not open /proc/mounts\n"); + return -1; + } + + do { + match = fscanf(f, "%255s %255s %255s %255s %d %d\n", + mount_dev, mount_dir, mount_type, + mount_opts, &mount_freq, &mount_passno); + mount_dev[255] = 0; + mount_dir[255] = 0; + mount_type[255] = 0; + mount_opts[255] = 0; + if (match == 6 && + (strcmp(arg, mount_dev) == 0 || + strcmp(arg, mount_dir) == 0)) { + *dev = strdup(mount_dev); + *dir = strdup(mount_dir); + fclose(f); + return 0; + } + } while (match != EOF); + + fclose(f); + return -1; +} + int mount_main(int argc, char *argv[]) { char *type = NULL; + char *dev = NULL; + char *dir = NULL; int c; int loop = 0; @@ -265,12 +306,19 @@ int mount_main(int argc, char *argv[]) if (rwflag & MS_TYPE) type = "none"; - if (optind + 2 != argc || type == NULL) { + if (optind + 2 == argc) { + dev = argv[optind]; + dir = argv[optind + 1]; + } else if (optind + 1 == argc && rwflag & MS_REMOUNT) { + get_mounts_dev_dir(argv[optind], &dev, &dir); + } + + if (dev == NULL || dir == NULL || type == NULL) { fprintf(stderr, "Usage: %s [-r] [-w] [-o options] [-t type] " "device directory\n", progname); exit(1); } - return do_mount(argv[optind], argv[optind + 1], type, rwflag, - extra.str, loop); + return do_mount(dev, dir, type, rwflag, extra.str, loop); + /* We leak dev and dir in some cases, but we're about to exit */ } diff --git a/toolbox/nandread.c b/toolbox/nandread.c index 9644973..b124731 100644 --- a/toolbox/nandread.c +++ b/toolbox/nandread.c @@ -4,6 +4,7 @@ #include <ctype.h> #include <errno.h> #include <fcntl.h> +#include <unistd.h> #include <mtd/mtd-user.h> #include <sys/ioctl.h> @@ -283,4 +284,3 @@ int nandread_main(int argc, char **argv) return 0; } - diff --git a/toolbox/notify.c b/toolbox/notify.c index b1761d2..c983ed5 100644 --- a/toolbox/notify.c +++ b/toolbox/notify.c @@ -3,6 +3,7 @@ #include <string.h> #include <stdint.h> #include <fcntl.h> +#include <unistd.h> #include <sys/ioctl.h> #include <sys/inotify.h> #include <errno.h> diff --git a/toolbox/ps.c b/toolbox/ps.c index bc50cfa..2aa3efb 100644 --- a/toolbox/ps.c +++ b/toolbox/ps.c @@ -27,6 +27,7 @@ static char *nexttok(char **strp) #define SHOW_PRIO 1 #define SHOW_TIME 2 #define SHOW_POLICY 4 +#define SHOW_CPU 8 static int display_flags = 0; @@ -41,7 +42,7 @@ static int ps_line(int pid, int tid, char *namefilter) int ppid, tty; unsigned wchan, rss, vss, eip; unsigned utime, stime; - int prio, nice, rtprio, sched; + int prio, nice, rtprio, sched, psr; struct passwd *pw; sprintf(statline, "/proc/%d", pid); @@ -122,7 +123,7 @@ static int ps_line(int pid, int tid, char *namefilter) nexttok(&ptr); // nswap nexttok(&ptr); // cnswap nexttok(&ptr); // exit signal - nexttok(&ptr); // processor + psr = atoi(nexttok(&ptr)); // processor rtprio = atoi(nexttok(&ptr)); // rt_priority sched = atoi(nexttok(&ptr)); // scheduling policy @@ -142,7 +143,9 @@ static int ps_line(int pid, int tid, char *namefilter) if(!namefilter || !strncmp(name, namefilter, strlen(namefilter))) { printf("%-9s %-5d %-5d %-6d %-5d", user, pid, ppid, vss / 1024, rss * 4); - if(display_flags&SHOW_PRIO) + if (display_flags & SHOW_CPU) + printf(" %-2d", psr); + if (display_flags & SHOW_PRIO) printf(" %-5d %-5d %-5d %-5d", prio, nice, rtprio, sched); if (display_flags & SHOW_POLICY) { SchedPolicy p; @@ -207,6 +210,8 @@ int ps_main(int argc, char **argv) display_flags |= SHOW_POLICY; } else if(!strcmp(argv[1],"-p")) { display_flags |= SHOW_PRIO; + } else if(!strcmp(argv[1],"-c")) { + display_flags |= SHOW_CPU; } else if(isdigit(argv[1][0])){ pidfilter = atoi(argv[1]); } else { @@ -216,7 +221,8 @@ int ps_main(int argc, char **argv) argv++; } - printf("USER PID PPID VSIZE RSS %s %s WCHAN PC NAME\n", + printf("USER PID PPID VSIZE RSS %s%s %s WCHAN PC NAME\n", + (display_flags&SHOW_CPU)?"CPU ":"", (display_flags&SHOW_PRIO)?"PRIO NICE RTPRI SCHED ":"", (display_flags&SHOW_POLICY)?"PCY " : ""); while((de = readdir(d)) != 0){ diff --git a/toolbox/r.c b/toolbox/r.c index 5a82e20..eb8ea0b 100644 --- a/toolbox/r.c +++ b/toolbox/r.c @@ -13,8 +13,10 @@ static int usage() int r_main(int argc, char *argv[]) { int width = 4, set = 0, fd; - unsigned addr, value; + unsigned addr, value, endaddr = 0; + unsigned long mmap_start, mmap_size; void *page; + char *end; if(argc < 2) return usage(); @@ -31,6 +33,18 @@ int r_main(int argc, char *argv[]) if(argc < 2) return usage(); addr = strtoul(argv[1], 0, 16); + end = strchr(argv[1], '-'); + if (end) + endaddr = strtoul(end + 1, 0, 16); + + if (!endaddr) + endaddr = addr + width - 1; + + if (endaddr <= addr) { + fprintf(stderr, "invalid end address\n"); + return -1; + } + if(argc > 2) { set = 1; value = strtoul(argv[2], 0, 16); @@ -42,33 +56,40 @@ int r_main(int argc, char *argv[]) return -1; } - page = mmap(0, 8192, PROT_READ | PROT_WRITE, - MAP_SHARED, fd, addr & (~4095)); + mmap_start = addr & ~(PAGE_SIZE - 1); + mmap_size = endaddr - mmap_start + 1; + mmap_size = (mmap_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1); + + page = mmap(0, mmap_size, PROT_READ | PROT_WRITE, + MAP_SHARED, fd, mmap_start); if(page == MAP_FAILED){ fprintf(stderr,"cannot mmap region\n"); return -1; } - switch(width){ - case 4: { - unsigned *x = (unsigned*) (((unsigned) page) + (addr & 4095)); - if(set) *x = value; - fprintf(stderr,"%08x: %08x\n", addr, *x); - break; - } - case 2: { - unsigned short *x = (unsigned short*) (((unsigned) page) + (addr & 4095)); - if(set) *x = value; - fprintf(stderr,"%08x: %04x\n", addr, *x); - break; - } - case 1: { - unsigned char *x = (unsigned char*) (((unsigned) page) + (addr & 4095)); - if(set) *x = value; - fprintf(stderr,"%08x: %02x\n", addr, *x); - break; + while (addr <= endaddr) { + switch(width){ + case 4: { + unsigned *x = (unsigned*) (((unsigned) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08x: %08x\n", addr, *x); + break; + } + case 2: { + unsigned short *x = (unsigned short*) (((unsigned) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08x: %04x\n", addr, *x); + break; + } + case 1: { + unsigned char *x = (unsigned char*) (((unsigned) page) + (addr & 4095)); + if(set) *x = value; + fprintf(stderr,"%08x: %02x\n", addr, *x); + break; + } + } + addr += width; } - } return 0; } diff --git a/toolbox/reboot.c b/toolbox/reboot.c index aebe185..f8546de 100644 --- a/toolbox/reboot.c +++ b/toolbox/reboot.c @@ -1,7 +1,7 @@ #include <errno.h> #include <stdio.h> #include <stdlib.h> -#include <sys/reboot.h> +#include <cutils/android_reboot.h> #include <unistd.h> int reboot_main(int argc, char *argv[]) @@ -9,6 +9,7 @@ int reboot_main(int argc, char *argv[]) int ret; int nosync = 0; int poweroff = 0; + int flags = 0; opterr = 0; do { @@ -38,15 +39,16 @@ int reboot_main(int argc, char *argv[]) exit(EXIT_FAILURE); } - if(!nosync) - sync(); + if(nosync) + /* also set NO_REMOUNT_RO as remount ro includes an implicit sync */ + flags = ANDROID_RB_FLAG_NO_SYNC | ANDROID_RB_FLAG_NO_REMOUNT_RO; if(poweroff) - ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_POWER_OFF, NULL); + ret = android_reboot(ANDROID_RB_POWEROFF, flags, 0); else if(argc > optind) - ret = __reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART2, argv[optind]); + ret = android_reboot(ANDROID_RB_RESTART2, flags, argv[optind]); else - ret = reboot(RB_AUTOBOOT); + ret = android_reboot(ANDROID_RB_RESTART, flags, 0); if(ret < 0) { perror("reboot"); exit(EXIT_FAILURE); diff --git a/toolbox/schedtop.c b/toolbox/schedtop.c index c0e0141..6859b50 100644 --- a/toolbox/schedtop.c +++ b/toolbox/schedtop.c @@ -2,7 +2,9 @@ #include <stdlib.h> #include <ctype.h> #include <fcntl.h> +#include <unistd.h> +#include <stdint.h> #include <string.h> #include <sys/stat.h> @@ -332,4 +334,3 @@ int schedtop_main(int argc, char **argv) closedir(d); return 0; } - diff --git a/toolbox/setconsole.c b/toolbox/setconsole.c index b0ce13f..0159c07 100644 --- a/toolbox/setconsole.c +++ b/toolbox/setconsole.c @@ -6,6 +6,8 @@ #include <linux/vt.h> #include <errno.h> #include <pthread.h> +#include <unistd.h> +#include <sys/ioctl.h> static int activate_thread_switch_vc; static void *activate_thread(void *arg) diff --git a/toolbox/top.c b/toolbox/top.c index daade6d..999c8e1 100644 --- a/toolbox/top.c +++ b/toolbox/top.c @@ -65,6 +65,7 @@ struct proc_info { long unsigned delta_time; long vss; long rss; + int prs; int num_threads; char policy[32]; }; @@ -340,8 +341,9 @@ static int read_stat(char *filename, struct proc_info *proc) { /* Scan rest of string. */ sscanf(close_paren + 1, " %c %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d " - "%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld", - &proc->state, &proc->utime, &proc->stime, &proc->vss, &proc->rss); + "%lu %lu %*d %*d %*d %*d %*d %*d %*d %lu %ld " + "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %d", + &proc->state, &proc->utime, &proc->stime, &proc->vss, &proc->rss, &proc->prs); return 0; } @@ -454,9 +456,9 @@ static void print_procs(void) { total_delta_time); printf("\n"); if (!threads) - printf("%5s %4s %1s %5s %7s %7s %3s %-8s %s\n", "PID", "CPU%", "S", "#THR", "VSS", "RSS", "PCY", "UID", "Name"); + printf("%5s %2s %4s %1s %5s %7s %7s %3s %-8s %s\n", "PID", "PR", "CPU%", "S", "#THR", "VSS", "RSS", "PCY", "UID", "Name"); else - printf("%5s %5s %4s %1s %7s %7s %3s %-8s %-15s %s\n", "PID", "TID", "CPU%", "S", "VSS", "RSS", "PCY", "UID", "Thread", "Proc"); + printf("%5s %5s %2s %4s %1s %7s %7s %3s %-8s %-15s %s\n", "PID", "TID", "PR", "CPU%", "S", "VSS", "RSS", "PCY", "UID", "Thread", "Proc"); for (i = 0; i < num_new_procs; i++) { proc = new_procs[i]; @@ -478,10 +480,10 @@ static void print_procs(void) { group_str = group_buf; } if (!threads) - printf("%5d %3ld%% %c %5d %6ldK %6ldK %3s %-8.8s %s\n", proc->pid, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads, + printf("%5d %2d %3ld%% %c %5d %6ldK %6ldK %3s %-8.8s %s\n", proc->pid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->num_threads, proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->name[0] != 0 ? proc->name : proc->tname); else - printf("%5d %5d %3ld%% %c %6ldK %6ldK %3s %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->delta_time * 100 / total_delta_time, proc->state, + printf("%5d %5d %2d %3ld%% %c %6ldK %6ldK %3s %-8.8s %-15s %s\n", proc->pid, proc->tid, proc->prs, proc->delta_time * 100 / total_delta_time, proc->state, proc->vss / 1024, proc->rss * getpagesize() / 1024, proc->policy, user_str, proc->tname, proc->name); } } diff --git a/toolbox/uptime.c b/toolbox/uptime.c index 3d8061c..1c312b0 100644 --- a/toolbox/uptime.c +++ b/toolbox/uptime.c @@ -35,6 +35,7 @@ #include <linux/android_alarm.h> #include <fcntl.h> #include <stdio.h> +#include <time.h> static void format_time(int time, char* buffer) { @@ -75,19 +76,26 @@ int uptime_main(int argc, char *argv[]) float up_time, idle_time; char up_string[100], idle_string[100], sleep_string[100]; int elapsed; + struct timespec up_timespec; FILE* file = fopen("/proc/uptime", "r"); if (!file) { fprintf(stderr, "Could not open /proc/uptime\n"); return -1; } - if (fscanf(file, "%f %f", &up_time, &idle_time) != 2) { + if (fscanf(file, "%*f %f", &idle_time) != 1) { fprintf(stderr, "Could not parse /proc/uptime\n"); fclose(file); return -1; } fclose(file); + if (clock_gettime(CLOCK_MONOTONIC, &up_timespec) < 0) { + fprintf(stderr, "Could not get monotonic time\n"); + return -1; + } + up_time = up_timespec.tv_sec + up_timespec.tv_nsec / 1e9; + elapsed = elapsedRealtime(); if (elapsed < 0) { fprintf(stderr, "elapsedRealtime failed\n"); diff --git a/toolbox/wipe.c b/toolbox/wipe.c index 7e263fd..650a0d6 100644 --- a/toolbox/wipe.c +++ b/toolbox/wipe.c @@ -5,7 +5,7 @@ #include <string.h> #include <errno.h> #include <sys/types.h> -#include <sys/reboot.h> +#include <cutils/android_reboot.h> #include <sys/stat.h> #ifndef PATH_MAX @@ -63,7 +63,7 @@ int wipe_main (int argc, char *argv[]) wipe ("/system"); wipe ("/data"); fprintf(stdout, "Device nuked! Rebooting...\n"); - ret = reboot(RB_AUTOBOOT); + ret = android_reboot(ANDROID_RB_RESTART, 0, 0); if (ret < 0) { fprintf(stderr, "Reboot failed, %s\n", strerror(errno)); return 1; |