Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 16e63329 authored by Steve Kondik's avatar Steve Kondik
Browse files

Merge branch 'ics-mr1' of https://android.googlesource.com/platform/system/core into aosp

parents 330b3dee 7cd3e0a3
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -909,9 +909,11 @@ int adb_main(int is_daemon, int server_port)
        ** AID_NET_BT and AID_NET_BT_ADMIN to diagnose bluetooth (hcidump)
        ** AID_SDCARD_RW to allow writing to the SD card
        ** AID_MOUNT to allow unmounting the SD card before rebooting
        ** AID_NET_BW_STATS to read out qtaguid statistics
        */
        gid_t groups[] = { AID_ADB, AID_LOG, AID_INPUT, AID_INET, AID_GRAPHICS,
                           AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, AID_MOUNT };
                           AID_NET_BT, AID_NET_BT_ADMIN, AID_SDCARD_RW, AID_MOUNT,
                           AID_NET_BW_STATS };
        if (setgroups(sizeof(groups)/sizeof(groups[0]), groups) != 0) {
            exit(1);
        }
+24 −2
Original line number Diff line number Diff line
@@ -577,9 +577,29 @@ static int logcat(transport_type transport, char* serial, int argc, char **argv)
    return 0;
}

static int mkdirs(char *path)
{
    int ret;
    char *x = path + 1;

    for(;;) {
        x = adb_dirstart(x);
        if(x == 0) return 0;
        *x = 0;
        ret = adb_mkdir(path, 0775);
        *x = OS_PATH_SEPARATOR;
        if((ret < 0) && (errno != EEXIST)) {
            return ret;
        }
        x++;
    }
    return 0;
}

static int backup(int argc, char** argv) {
    char buf[4096];
    const char* filename = "./backup.ab";
    char default_name[32];
    const char* filename = strcpy(default_name, "./backup.ab");
    int fd, outFd;
    int i, j;

@@ -602,7 +622,9 @@ static int backup(int argc, char** argv) {
    /* bare "adb backup" or "adb backup -f filename" are not valid invocations */
    if (argc < 2) return usage();

    outFd = adb_open_mode(filename, O_WRONLY | O_CREAT | O_TRUNC, 0640);
    adb_unlink(filename);
    mkdirs((char *)filename);
    outFd = adb_creat(filename, 0640);
    if (outFd < 0) {
        fprintf(stderr, "adb: unable to open file %s\n", filename);
        return -1;
+190 −15
Original line number Diff line number Diff line
@@ -1426,6 +1426,180 @@ event_looper_unhook( EventLooper looper, int fd, int events )
    }
}

/*
 * A fixer for WaitForMultipleObjects on condition that there are more than 64
 * handles to wait on.
 *
 * In cetain cases DDMS may establish more than 64 connections with ADB. For
 * instance, this may happen if there are more than 64 processes running on a
 * device, or there are multiple devices connected (including the emulator) with
 * the combined number of running processes greater than 64. In this case using
 * WaitForMultipleObjects to wait on connection events simply wouldn't cut,
 * because of the API limitations (64 handles max). So, we need to provide a way
 * to scale WaitForMultipleObjects to accept an arbitrary number of handles. The
 * easiest (and "Microsoft recommended") way to do that would be dividing the
 * handle array into chunks with the chunk size less than 64, and fire up as many
 * waiting threads as there are chunks. Then each thread would wait on a chunk of
 * handles, and will report back to the caller which handle has been set.
 * Here is the implementation of that algorithm.
 */

/* Number of handles to wait on in each wating thread. */
#define WAIT_ALL_CHUNK_SIZE 63

/* Descriptor for a wating thread */
typedef struct WaitForAllParam {
    /* A handle to an event to signal when waiting is over. This handle is shared
     * accross all the waiting threads, so each waiting thread knows when any
     * other thread has exited, so it can exit too. */
    HANDLE          main_event;
    /* Upon exit from a waiting thread contains the index of the handle that has
     * been signaled. The index is an absolute index of the signaled handle in
     * the original array. This pointer is shared accross all the waiting threads
     * and it's not guaranteed (due to a race condition) that when all the
     * waiting threads exit, the value contained here would indicate the first
     * handle that was signaled. This is fine, because the caller cares only
     * about any handle being signaled. It doesn't care about the order, nor
     * about the whole list of handles that were signaled. */
    LONG volatile   *signaled_index;
    /* Array of handles to wait on in a waiting thread. */
    HANDLE*         handles;
    /* Number of handles in 'handles' array to wait on. */
    int             handles_count;
    /* Index inside the main array of the first handle in the 'handles' array. */
    int             first_handle_index;
    /* Waiting thread handle. */
    HANDLE          thread;
} WaitForAllParam;

/* Waiting thread routine. */
static unsigned __stdcall
_in_waiter_thread(void*  arg)
{
    HANDLE wait_on[WAIT_ALL_CHUNK_SIZE + 1];
    int res;
    WaitForAllParam* const param = (WaitForAllParam*)arg;

    /* We have to wait on the main_event in order to be notified when any of the
     * sibling threads is exiting. */
    wait_on[0] = param->main_event;
    /* The rest of the handles go behind the main event handle. */
    memcpy(wait_on + 1, param->handles, param->handles_count * sizeof(HANDLE));

    res = WaitForMultipleObjects(param->handles_count + 1, wait_on, FALSE, INFINITE);
    if (res > 0 && res < (param->handles_count + 1)) {
        /* One of the original handles got signaled. Save its absolute index into
         * the output variable. */
        InterlockedCompareExchange(param->signaled_index,
                                   res - 1L + param->first_handle_index, -1L);
    }

    /* Notify the caller (and the siblings) that the wait is over. */
    SetEvent(param->main_event);

    _endthreadex(0);
    return 0;
}

/* WaitForMultipeObjects fixer routine.
 * Param:
 *  handles Array of handles to wait on.
 *  handles_count Number of handles in the array.
 * Return:
 *  (>= 0 && < handles_count) - Index of the signaled handle in the array, or
 *  WAIT_FAILED on an error.
 */
static int
_wait_for_all(HANDLE* handles, int handles_count)
{
    WaitForAllParam* threads;
    HANDLE main_event;
    int chunks, chunk, remains;

    /* This variable is going to be accessed by several threads at the same time,
     * this is bound to fail randomly when the core is run on multi-core machines.
     * To solve this, we need to do the following (1 _and_ 2):
     * 1. Use the "volatile" qualifier to ensure the compiler doesn't optimize
     *    out the reads/writes in this function unexpectedly.
     * 2. Ensure correct memory ordering. The "simple" way to do that is to wrap
     *    all accesses inside a critical section. But we can also use
     *    InterlockedCompareExchange() which always provide a full memory barrier
     *    on Win32.
     */
    volatile LONG sig_index = -1;

    /* Calculate number of chunks, and allocate thread param array. */
    chunks = handles_count / WAIT_ALL_CHUNK_SIZE;
    remains = handles_count % WAIT_ALL_CHUNK_SIZE;
    threads = (WaitForAllParam*)malloc((chunks + (remains ? 1 : 0)) *
                                        sizeof(WaitForAllParam));
    if (threads == NULL) {
        D("Unable to allocate thread array for %d handles.", handles_count);
        return (int)WAIT_FAILED;
    }

    /* Create main event to wait on for all waiting threads. This is a "manualy
     * reset" event that will remain set once it was set. */
    main_event = CreateEvent(NULL, TRUE, FALSE, NULL);
    if (main_event == NULL) {
        D("Unable to create main event. Error: %d", GetLastError());
        free(threads);
        return (int)WAIT_FAILED;
    }

    /*
     * Initialize waiting thread parameters.
     */

    for (chunk = 0; chunk < chunks; chunk++) {
        threads[chunk].main_event = main_event;
        threads[chunk].signaled_index = &sig_index;
        threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
        threads[chunk].handles = handles + threads[chunk].first_handle_index;
        threads[chunk].handles_count = WAIT_ALL_CHUNK_SIZE;
    }
    if (remains) {
        threads[chunk].main_event = main_event;
        threads[chunk].signaled_index = &sig_index;
        threads[chunk].first_handle_index = WAIT_ALL_CHUNK_SIZE * chunk;
        threads[chunk].handles = handles + threads[chunk].first_handle_index;
        threads[chunk].handles_count = remains;
        chunks++;
    }

    /* Start the waiting threads. */
    for (chunk = 0; chunk < chunks; chunk++) {
        /* Note that using adb_thread_create is not appropriate here, since we
         * need a handle to wait on for thread termination. */
        threads[chunk].thread = (HANDLE)_beginthreadex(NULL, 0, _in_waiter_thread,
                                                       &threads[chunk], 0, NULL);
        if (threads[chunk].thread == NULL) {
            /* Unable to create a waiter thread. Collapse. */
            D("Unable to create a waiting thread %d of %d. errno=%d",
              chunk, chunks, errno);
            chunks = chunk;
            SetEvent(main_event);
            break;
        }
    }

    /* Wait on any of the threads to get signaled. */
    WaitForSingleObject(main_event, INFINITE);

    /* Wait on all the waiting threads to exit. */
    for (chunk = 0; chunk < chunks; chunk++) {
        WaitForSingleObject(threads[chunk].thread, INFINITE);
        CloseHandle(threads[chunk].thread);
    }

    CloseHandle(main_event);
    free(threads);


    const int ret = (int)InterlockedCompareExchange(&sig_index, -1, -1);
    return (ret >= 0) ? ret : (int)WAIT_FAILED;
}

static EventLooperRec  win32_looper;

static void fdevent_init(void)
@@ -1525,10 +1699,11 @@ static void fdevent_process()

            D( "adb_win32: waiting for %d events\n", looper->htab_count );
            if (looper->htab_count > MAXIMUM_WAIT_OBJECTS) {
                D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS, aborting!\n", looper->htab_count);
                abort();
            }
                D("handle count %d exceeds MAXIMUM_WAIT_OBJECTS.\n", looper->htab_count);
                wait_ret = _wait_for_all(looper->htab, looper->htab_count);
            } else {
                wait_ret = WaitForMultipleObjects( looper->htab_count, looper->htab, FALSE, INFINITE );
            }
            if (wait_ret == (int)WAIT_FAILED) {
                D( "adb_win32: wait failed, error %ld\n", GetLastError() );
            } else {
+173 −49
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@

#include "utility.h"

/* enable to dump memory pointed to by every register */
#define DUMP_MEM_FOR_ALL_REGS 0

#ifdef WITH_VFP
#ifdef WITH_VFP_D32
#define NUM_VFP_REGS 32
@@ -50,79 +53,200 @@ extern int unwind_backtrace_with_ptrace(int tfd, pid_t pid, mapinfo *map,
                                        int *frame0_pc_sane,
                                        bool at_fault);

void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                         int unwind_depth, unsigned int sp_list[],
                         bool at_fault)
/*
 * If this isn't clearly a null pointer dereference, dump the
 * /proc/maps entries near the fault address.
 *
 * This only makes sense to do on the thread that crashed.
 */
static void show_nearby_maps(int tfd, int pid, mapinfo *map)
{
    unsigned int sp, pc, lr, p, end, data;
    struct pt_regs r;
    int sp_depth;
    bool only_in_tombstone = !at_fault;
    char code_buffer[80];
    siginfo_t si;

    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;
    sp = r.ARM_sp;
    pc = r.ARM_pc;
    lr = r.ARM_lr;
    memset(&si, 0, sizeof(si));
    if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si)) {
        _LOG(tfd, false, "cannot get siginfo for %d: %s\n",
            pid, strerror(errno));
        return;
    }
    if (!signal_has_address(si.si_signo))
        return;

    _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
    uintptr_t addr = (uintptr_t) si.si_addr;
    addr &= ~0xfff;     /* round to 4K page boundary */
    if (addr == 0)      /* null-pointer deref */
        return;

    _LOG(tfd, false, "\nmemory map around addr %08x:\n", si.si_addr);

    /*
     * Search for a match, or for a hole where the match would be.  The list
     * is backward from the file content, so it starts at high addresses.
     */
    bool found = false;
    mapinfo *next = NULL;
    mapinfo *prev = NULL;
    while (map != NULL) {
        if (addr >= map->start && addr < map->end) {
            found = true;
            next = map->next;
            break;
        } else if (addr >= map->end) {
            /* map would be between "prev" and this entry */
            next = map;
            map = NULL;
            break;
        }

        prev = map;
        map = map->next;
    }

    /*
     * Show "next" then "match" then "prev" so that the addresses appear in
     * ascending order (like /proc/pid/maps).
     */
    if (next != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", next->start, next->end, next->name);
    } else {
        _LOG(tfd, false, "(no map below)\n");
    }
    if (map != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", map->start, map->end, map->name);
    } else {
        _LOG(tfd, false, "(no map for address)\n");
    }
    if (prev != NULL) {
        _LOG(tfd, false, "%08x-%08x %s\n", prev->start, prev->end, prev->name);
    } else {
        _LOG(tfd, false, "(no map above)\n");
    }
}

    p = pc & ~3;
/*
 * Dumps a few bytes of memory, starting a bit before and ending a bit
 * after the specified address.
 */
static void dump_memory(int tfd, int pid, uintptr_t addr,
    bool only_in_tombstone)
{
    char code_buffer[64];       /* actual 8+1+((8+1)*4) + 1 == 45 */
    char ascii_buffer[32];      /* actual 16 + 1 == 17 */
    uintptr_t p, end;

    p = addr & ~3;
    p -= 32;
    if (p > pc)
    if (p > addr) {
        /* catch underflow */
        p = 0;
    }
    end = p + 80;
    /* 'end - p' has to be multiples of 16 */
    /* catch overflow; '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
     *  addr     contents                             ascii
     *  00008d34 ef000000 e8bd0090 e1b00000 512fff1e  ............../Q
     *  00008d44 ea00b1f9 e92d0090 e3a070fc ef000000  ......-..p......
     */
    while (p < end) {
        int i;
        char* asc_out = ascii_buffer;

        sprintf(code_buffer, "%08x ", p);

        int i;
        for (i = 0; i < 4; i++) {
            data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
            sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
            /*
             * If we see (data == -1 && errno != 0), we know that the ptrace
             * call failed, probably because we're dumping memory in an
             * unmapped or inaccessible page.  I don't know if there's
             * value in making that explicit in the output -- it likely
             * just complicates parsing and clarifies nothing for the
             * enlightened reader.
             */
            long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
            sprintf(code_buffer + strlen(code_buffer), "%08lx ", data);

            int j;
            for (j = 0; j < 4; j++) {
                /*
                 * Our isprint() allows high-ASCII characters that display
                 * differently (often badly) in different viewers, so we
                 * just use a simpler test.
                 */
                char val = (data >> (j*8)) & 0xff;
                if (val >= 0x20 && val < 0x7f) {
                    *asc_out++ = val;
                } else {
                    *asc_out++ = '.';
                }
            }
            p += 4;
        }
        _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
        *asc_out = '\0';
        _LOG(tfd, only_in_tombstone, "%s %s\n", code_buffer, ascii_buffer);
    }

    if (lr != pc) {
        _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
}

        p = lr & ~3;
        p -= 32;
        if (p > lr)
            p = 0;
        end = p + 80;
        /* 'end - p' has to be multiples of 16 */
        while (end < p)
            end -= 16;
void dump_stack_and_code(int tfd, int pid, mapinfo *map,
                         int unwind_depth, unsigned int sp_list[],
                         bool at_fault)
{
    struct pt_regs r;
    int sp_depth;
    bool only_in_tombstone = !at_fault;

    if(ptrace(PTRACE_GETREGS, pid, 0, &r)) return;

        /* Dump the code around LR as:
         *  addr       contents
         *  00008d34   fffffcd0 4c0eb530 b0934a0e 1c05447c
         *  00008d44   f7ff18a0 490ced94 68035860 d0012b00
    if (DUMP_MEM_FOR_ALL_REGS && at_fault) {
        /*
         * If configured to do so, dump memory around *all* registers
         * for the crashing thread.
         *
         * TODO: remove duplicates.
         */
        while (p < end) {
            int i;
        static const char REG_NAMES[] = "R0R1R2R3R4R5R6R7R8R9SLFPIPSPLRPC";

            sprintf(code_buffer, "%08x ", p);
            for (i = 0; i < 4; i++) {
                data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
                sprintf(code_buffer + strlen(code_buffer), "%08x ", data);
                p += 4;
        int reg;
        for (reg = 0; reg < 16; reg++) {
            /* this may not be a valid way to access, but it'll do for now */
            uintptr_t addr = r.uregs[reg];

            /*
             * Don't bother if it looks like a small int or ~= null, or if
             * it's in the kernel area.
             */
            if (addr < 4096 || addr >= 0xc0000000) {
                continue;
            }

            _LOG(tfd, only_in_tombstone, "\nmem near %.2s:\n",
                &REG_NAMES[reg*2]);
            dump_memory(tfd, pid, addr, false);
        }
    } else {
        unsigned int pc, lr;
        pc = r.ARM_pc;
        lr = r.ARM_lr;

        _LOG(tfd, only_in_tombstone, "\ncode around pc:\n");
        dump_memory(tfd, pid, (uintptr_t) pc, only_in_tombstone);

        if (lr != pc) {
            _LOG(tfd, only_in_tombstone, "\ncode around lr:\n");
            dump_memory(tfd, pid, (uintptr_t) lr, only_in_tombstone);
        }
            _LOG(tfd, only_in_tombstone, "%s\n", code_buffer);
    }

    if (at_fault) {
        show_nearby_maps(tfd, pid, map);
    }

    unsigned int p, end;
    unsigned int sp = r.ARM_sp;

    p = sp - 64;
    if (p > sp)
        p = 0;
@@ -157,7 +281,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map,
    while (p <= end) {
         char *prompt;
         char level[16];
         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
         long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
         if (p == sp_list[sp_depth]) {
             sprintf(level, "#%02d", sp_depth++);
             prompt = level;
@@ -182,7 +306,7 @@ void dump_stack_and_code(int tfd, int pid, mapinfo *map,
        end = ~7;

    while (p <= end) {
         data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
         long data = ptrace(PTRACE_PEEKTEXT, pid, (void*)p, NULL);
         _LOG(tfd, (sp_depth > 2) || only_in_tombstone,
              "    %08x  %08x  %s\n", p, data,
              map_to_name(map, data, ""));
+201 −13

File changed.

Preview size limit exceeded, changes collapsed.

Loading