aboutsummaryrefslogtreecommitdiffstats
path: root/testhal/STM32F1xx/I2C/halconf.h
diff options
context:
space:
mode:
Diffstat (limited to 'testhal/STM32F1xx/I2C/halconf.h')
0 files changed, 0 insertions, 0 deletions
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
/*
 * symbols.c: in-kernel printing of symbolic oopses and stack traces.
 *
 * Copyright 2002 Rusty Russell <rusty@rustcorp.com.au> IBM Corporation
 *
 * ChangeLog:
 *
 * (25/Aug/2004) Paulo Marques <pmarques@grupopie.com>
 *      Changed the compression method from stem compression to "table lookup"
 *      compression (see tools/symbols.c for a more complete description)
 */

#include <xen/config.h>
#include <xen/symbols.h>
#include <xen/kernel.h>
#include <xen/init.h>
#include <xen/lib.h>
#include <xen/string.h>
#include <xen/spinlock.h>

extern unsigned long symbols_addresses[];
extern unsigned long symbols_num_syms;
extern u8 symbols_names[];

extern u8 symbols_token_table[];
extern u16 symbols_token_index[];

extern unsigned long symbols_markers[];

/* expand a compressed symbol data into the resulting uncompressed string,
   given the offset to where the symbol is in the compressed stream */
static unsigned int symbols_expand_symbol(unsigned int off, char *result)
{
    int len, skipped_first = 0;
    u8 *tptr, *data;

    /* get the compressed symbol length from the first symbol byte */
    data = &symbols_names[off];
    len = *data;
    data++;

    /* update the offset to return the offset for the next symbol on
     * the compressed stream */
    off += len + 1;

    /* for every byte on the compressed symbol data, copy the table
       entry for that byte */
    while(len) {
        tptr = &symbols_token_table[ symbols_token_index[*data] ];
        data++;
        len--;

        while (*tptr) {
            if(skipped_first) {
                *result = *tptr;
                result++;
            } else
                skipped_first = 1;
            tptr++;
        }
    }

    *result = '\0';

    /* return to offset to the next symbol */
    return off;
}

/* find the offset on the compressed stream given and index in the
 * symbols array */
static unsigned int get_symbol_offset(unsigned long pos)
{
    u8 *name;
    int i;

    /* use the closest marker we have. We have markers every 256 positions,
     * so that should be close enough */
    name = &symbols_names[ symbols_markers[pos>>8] ];

    /* sequentially scan all the symbols up to the point we're searching for.
     * Every symbol is stored in a [<len>][<len> bytes of data] format, so we
     * just need to add the len to the current pointer for every symbol we
     * wish to skip */
    for(i = 0; i < (pos&0xFF); i++)
        name = name + (*name) + 1;

    return name - symbols_names;
}

const char *symbols_lookup(unsigned long addr,
                           unsigned long *symbolsize,
                           unsigned long *offset,
                           char *namebuf)
{
    unsigned long i, low, high, mid;
    unsigned long symbol_end = 0;

    namebuf[KSYM_NAME_LEN] = 0;
    namebuf[0] = 0;

    if (!is_kernel_text(addr) && !is_kernel_inittext(addr))
        return NULL;

        /* do a binary search on the sorted symbols_addresses array */
    low = 0;
    high = symbols_num_syms;

    while (high-low > 1) {
        mid = (low + high) / 2;
        if (symbols_addresses[mid] <= addr) low = mid;
        else high = mid;
    }

    /* search for the first aliased symbol. Aliased symbols are
           symbols with the same address */
    while (low && symbols_addresses[low - 1] == symbols_addresses[low])
        --low;

        /* Grab name */
    symbols_expand_symbol(get_symbol_offset(low), namebuf);

    /* Search for next non-aliased symbol */
    for (i = low + 1; i < symbols_num_syms; i++) {
        if (symbols_addresses[i] > symbols_addresses[low]) {
            symbol_end = symbols_addresses[i];
            break;
        }
    }

    /* if we found no next symbol, we use the end of the section */
    if (!symbol_end)
        symbol_end = is_kernel_inittext(addr) ?
            (unsigned long)_einittext : (unsigned long)_etext;

    *symbolsize = symbol_end - symbols_addresses[low];
    *offset = addr - symbols_addresses[low];
    return namebuf;
}

/* Replace "%s" in format with address, or returns -errno. */
void __print_symbol(const char *fmt, unsigned long address)
{
    const char *name;
    unsigned long offset, size, flags;

    static DEFINE_SPINLOCK(lock);
    static char namebuf[KSYM_NAME_LEN+1];
#define BUFFER_SIZE sizeof("%s+%#lx/%#lx [%s]") + KSYM_NAME_LEN + \
			2*(BITS_PER_LONG*3/10) + 1
    static char buffer[BUFFER_SIZE];

    spin_lock_irqsave(&lock, flags);

    name = symbols_lookup(address, &size, &offset, namebuf);

    if (!name)
        snprintf(buffer, BUFFER_SIZE, "???");
    else
        snprintf(buffer, BUFFER_SIZE, "%s+%#lx/%#lx", name, offset, size);

    printk(fmt, buffer);

    spin_unlock_irqrestore(&lock, flags);
}