mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 588607 - 0. Add bionic linker files, r=lvilla a=blocking-fennec
--HG-- extra : rebase_source : 8ea4efe4309b8fac52ba62cd22a2c69039061755
This commit is contained in:
parent
a3298dd3ca
commit
f71e519090
156
other-licenses/android/ba.c
Normal file
156
other-licenses/android/ba.c
Normal file
@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "linker.h"
|
||||
#include "linker_debug.h"
|
||||
#include "ba.h"
|
||||
|
||||
#undef min
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
#define BA_IS_FREE(index) (!(ba->bitmap[index].allocated))
|
||||
#define BA_ORDER(index) ba->bitmap[index].order
|
||||
#define BA_BUDDY_INDEX(index) ((index) ^ (1 << BA_ORDER(index)))
|
||||
#define BA_NEXT_INDEX(index) ((index) + (1 << BA_ORDER(index)))
|
||||
#define BA_OFFSET(index) ((index) * ba->min_alloc)
|
||||
#define BA_START_ADDR(index) (BA_OFFSET(index) + ba->base)
|
||||
#define BA_LEN(index) ((1 << BA_ORDER(index)) * ba->min_alloc)
|
||||
|
||||
static unsigned long ba_order(struct ba *ba, unsigned long len);
|
||||
|
||||
void ba_init(struct ba *ba)
|
||||
{
|
||||
int i, index = 0;
|
||||
|
||||
unsigned long max_order = ba_order(ba, ba->size);
|
||||
if (ba->max_order == 0 || ba->max_order > max_order)
|
||||
ba->max_order = max_order;
|
||||
|
||||
for (i = sizeof(ba->num_entries) * 8 - 1; i >= 0; i--) {
|
||||
if (ba->num_entries & 1<<i) {
|
||||
BA_ORDER(index) = i;
|
||||
index = BA_NEXT_INDEX(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int ba_free(struct ba *ba, int index)
|
||||
{
|
||||
int buddy, curr = index;
|
||||
|
||||
/* clean up the bitmap, merging any buddies */
|
||||
ba->bitmap[curr].allocated = 0;
|
||||
/* find a slots buddy Buddy# = Slot# ^ (1 << order)
|
||||
* if the buddy is also free merge them
|
||||
* repeat until the buddy is not free or end of the bitmap is reached
|
||||
*/
|
||||
do {
|
||||
buddy = BA_BUDDY_INDEX(curr);
|
||||
if (BA_IS_FREE(buddy) &&
|
||||
BA_ORDER(buddy) == BA_ORDER(curr)) {
|
||||
BA_ORDER(buddy)++;
|
||||
BA_ORDER(curr)++;
|
||||
curr = min(buddy, curr);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
} while (curr < ba->num_entries);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long ba_order(struct ba *ba, unsigned long len)
|
||||
{
|
||||
unsigned long i;
|
||||
|
||||
len = (len + ba->min_alloc - 1) / ba->min_alloc;
|
||||
len--;
|
||||
for (i = 0; i < sizeof(len)*8; i++)
|
||||
if (len >> i == 0)
|
||||
break;
|
||||
return i;
|
||||
}
|
||||
|
||||
int ba_allocate(struct ba *ba, unsigned long len)
|
||||
{
|
||||
int curr = 0;
|
||||
int end = ba->num_entries;
|
||||
int best_fit = -1;
|
||||
unsigned long order = ba_order(ba, len);
|
||||
|
||||
if (order > ba->max_order)
|
||||
return -1;
|
||||
|
||||
/* look through the bitmap:
|
||||
* if you find a free slot of the correct order use it
|
||||
* otherwise, use the best fit (smallest with size > order) slot
|
||||
*/
|
||||
while (curr < end) {
|
||||
if (BA_IS_FREE(curr)) {
|
||||
if (BA_ORDER(curr) == (unsigned char)order) {
|
||||
/* set the not free bit and clear others */
|
||||
best_fit = curr;
|
||||
break;
|
||||
}
|
||||
if (BA_ORDER(curr) > (unsigned char)order &&
|
||||
(best_fit < 0 ||
|
||||
BA_ORDER(curr) < BA_ORDER(best_fit)))
|
||||
best_fit = curr;
|
||||
}
|
||||
curr = BA_NEXT_INDEX(curr);
|
||||
}
|
||||
|
||||
/* if best_fit < 0, there are no suitable slots,
|
||||
* return an error
|
||||
*/
|
||||
if (best_fit < 0)
|
||||
return -1;
|
||||
|
||||
/* now partition the best fit:
|
||||
* split the slot into 2 buddies of order - 1
|
||||
* repeat until the slot is of the correct order
|
||||
*/
|
||||
while (BA_ORDER(best_fit) > (unsigned char)order) {
|
||||
int buddy;
|
||||
BA_ORDER(best_fit) -= 1;
|
||||
buddy = BA_BUDDY_INDEX(best_fit);
|
||||
BA_ORDER(buddy) = BA_ORDER(best_fit);
|
||||
}
|
||||
ba->bitmap[best_fit].allocated = 1;
|
||||
return best_fit;
|
||||
}
|
||||
|
||||
unsigned long ba_start_addr(struct ba *ba, int index)
|
||||
{
|
||||
return BA_START_ADDR(index);
|
||||
}
|
||||
|
||||
unsigned long ba_len(struct ba *ba, int index)
|
||||
{
|
||||
return BA_LEN(index);
|
||||
}
|
59
other-licenses/android/ba.h
Normal file
59
other-licenses/android/ba.h
Normal file
@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef __LINKER_BA_H
|
||||
#define __LINKER_BA_H
|
||||
|
||||
struct ba_bits {
|
||||
unsigned allocated:1; /* 1 if allocated, 0 if free */
|
||||
unsigned order:7; /* size of the region in ba space */
|
||||
};
|
||||
|
||||
struct ba {
|
||||
/* start address of the ba space */
|
||||
unsigned long base;
|
||||
/* total size of the ba space */
|
||||
unsigned long size;
|
||||
/* the smaller allocation that can be made */
|
||||
unsigned long min_alloc;
|
||||
/* the order of the largest allocation that can be made */
|
||||
unsigned long max_order;
|
||||
/* number of entries in the ba space */
|
||||
int num_entries;
|
||||
/* the bitmap for the region indicating which entries are allocated
|
||||
* and which are free */
|
||||
struct ba_bits *bitmap;
|
||||
};
|
||||
|
||||
extern void ba_init(struct ba *ba);
|
||||
extern int ba_allocate(struct ba *ba, unsigned long len);
|
||||
extern int ba_free(struct ba *ba, int index);
|
||||
extern unsigned long ba_start_addr(struct ba *ba, int index);
|
||||
extern unsigned long ba_len(struct ba *ba, int index);
|
||||
|
||||
#endif
|
113
other-licenses/android/bionic_tls.h
Normal file
113
other-licenses/android/bionic_tls.h
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _SYS_TLS_H
|
||||
#define _SYS_TLS_H
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
/** WARNING WARNING WARNING
|
||||
**
|
||||
** This header file is *NOT* part of the public Bionic ABI/API
|
||||
** and should not be used/included by user-serviceable parts of
|
||||
** the system (e.g. applications).
|
||||
**
|
||||
** It is only provided here for the benefit of the system dynamic
|
||||
** linker and the OpenGL sub-system (which needs to access the
|
||||
** pre-allocated slot directly for performance reason).
|
||||
**/
|
||||
|
||||
/* maximum number of elements in the TLS array */
|
||||
#define BIONIC_TLS_SLOTS 64
|
||||
|
||||
/* note that slot 0, called TLS_SLOT_SELF must point to itself.
|
||||
* this is required to implement thread-local storage with the x86
|
||||
* Linux kernel, that reads the TLS from fs:[0], where 'fs' is a
|
||||
* thread-specific segment descriptor...
|
||||
*/
|
||||
|
||||
/* Well known TLS slots */
|
||||
#define TLS_SLOT_SELF 0
|
||||
#define TLS_SLOT_THREAD_ID 1
|
||||
#define TLS_SLOT_ERRNO 2
|
||||
|
||||
#define TLS_SLOT_OPENGL_API 3
|
||||
#define TLS_SLOT_OPENGL 4
|
||||
|
||||
/* this slot is only used to pass information from the dynamic linker to
|
||||
* libc.so when the C library is loaded in to memory. The C runtime init
|
||||
* function will then clear it. Since its use is extremely temporary,
|
||||
* we reuse an existing location.
|
||||
*/
|
||||
#define TLS_SLOT_BIONIC_PREINIT (TLS_SLOT_ERRNO+1)
|
||||
|
||||
/* small technical note: it is not possible to call pthread_setspecific
|
||||
* on keys that are <= TLS_SLOT_MAX_WELL_KNOWN, which is why it is set to
|
||||
* TLS_SLOT_ERRNO.
|
||||
*
|
||||
* later slots like TLS_SLOT_OPENGL are pre-allocated through the use of
|
||||
* TLS_DEFAULT_ALLOC_MAP. this means that there is no need to use
|
||||
* pthread_key_create() to initialize them. on the other hand, there is
|
||||
* no destructor associated to them (we might need to implement this later)
|
||||
*/
|
||||
#define TLS_SLOT_MAX_WELL_KNOWN TLS_SLOT_ERRNO
|
||||
|
||||
#define TLS_DEFAULT_ALLOC_MAP 0x0000001F
|
||||
|
||||
/* set the Thread Local Storage, must contain at least BIONIC_TLS_SLOTS pointers */
|
||||
extern void __init_tls(void** tls, void* thread_info);
|
||||
|
||||
/* syscall only, do not call directly */
|
||||
extern int __set_tls(void *ptr);
|
||||
|
||||
/* get the TLS */
|
||||
#ifdef __arm__
|
||||
/* Linux kernel helpers for its TLS implementation */
|
||||
/* For performance reasons, avoid calling the kernel helper
|
||||
* Note that HAVE_ARM_TLS_REGISTER is build-specific
|
||||
* (it must match your kernel configuration)
|
||||
*/
|
||||
# ifdef HAVE_ARM_TLS_REGISTER
|
||||
# define __get_tls() \
|
||||
({ register unsigned int __val asm("r0"); \
|
||||
asm ("mrc p15, 0, r0, c13, c0, 3" : "=r"(__val) ); \
|
||||
(volatile void*)__val; })
|
||||
# else /* !HAVE_ARM_TLS_REGISTER */
|
||||
# define __get_tls() ( *((volatile void **) 0xffff0ff0) )
|
||||
# endif
|
||||
#else
|
||||
extern void* __get_tls( void );
|
||||
#endif
|
||||
|
||||
/* return the stack base and size, used by our malloc debugger */
|
||||
extern void* __get_stack_base(int *p_stack_size);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* _SYS_TLS_H */
|
92
other-licenses/android/debugger.c
Normal file
92
other-licenses/android/debugger.c
Normal file
@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "linker.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
void notify_gdb_of_libraries();
|
||||
|
||||
#define RETRY_ON_EINTR(ret,cond) \
|
||||
do { \
|
||||
ret = (cond); \
|
||||
} while (ret < 0 && errno == EINTR)
|
||||
|
||||
void debugger_signal_handler(int n)
|
||||
{
|
||||
unsigned tid;
|
||||
int s;
|
||||
|
||||
/* avoid picking up GC interrupts */
|
||||
signal(SIGUSR1, SIG_IGN);
|
||||
|
||||
tid = gettid();
|
||||
s = socket_local_client("android:debuggerd",
|
||||
ANDROID_SOCKET_NAMESPACE_ABSTRACT, SOCK_STREAM);
|
||||
|
||||
if(s >= 0) {
|
||||
/* debugger knows our pid from the credentials on the
|
||||
* local socket but we need to tell it our tid. It
|
||||
* is paranoid and will verify that we are giving a tid
|
||||
* that's actually in our process
|
||||
*/
|
||||
int ret;
|
||||
|
||||
RETRY_ON_EINTR(ret, write(s, &tid, sizeof(unsigned)));
|
||||
if (ret == sizeof(unsigned)) {
|
||||
/* if the write failed, there is no point to read on
|
||||
* the file descriptor. */
|
||||
RETRY_ON_EINTR(ret, read(s, &tid, 1));
|
||||
notify_gdb_of_libraries();
|
||||
}
|
||||
close(s);
|
||||
}
|
||||
|
||||
/* remove our net so we fault for real when we return */
|
||||
signal(n, SIG_IGN);
|
||||
}
|
||||
|
||||
void debugger_init()
|
||||
{
|
||||
signal(SIGILL, debugger_signal_handler);
|
||||
signal(SIGABRT, debugger_signal_handler);
|
||||
signal(SIGBUS, debugger_signal_handler);
|
||||
signal(SIGFPE, debugger_signal_handler);
|
||||
signal(SIGSEGV, debugger_signal_handler);
|
||||
signal(SIGSTKFLT, debugger_signal_handler);
|
||||
signal(SIGPIPE, debugger_signal_handler);
|
||||
}
|
276
other-licenses/android/dlfcn.c
Normal file
276
other-licenses/android/dlfcn.c
Normal file
@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (C) 2007 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 <dlfcn.h>
|
||||
#include <pthread.h>
|
||||
#include <stdio.h>
|
||||
#include "linker.h"
|
||||
#include "linker_format.h"
|
||||
|
||||
/* This file hijacks the symbols stubbed out in libdl.so. */
|
||||
|
||||
#define DL_SUCCESS 0
|
||||
#define DL_ERR_CANNOT_LOAD_LIBRARY 1
|
||||
#define DL_ERR_INVALID_LIBRARY_HANDLE 2
|
||||
#define DL_ERR_BAD_SYMBOL_NAME 3
|
||||
#define DL_ERR_SYMBOL_NOT_FOUND 4
|
||||
#define DL_ERR_SYMBOL_NOT_GLOBAL 5
|
||||
|
||||
static char dl_err_buf[1024];
|
||||
static const char *dl_err_str;
|
||||
|
||||
static const char *dl_errors[] = {
|
||||
[DL_ERR_CANNOT_LOAD_LIBRARY] = "Cannot load library",
|
||||
[DL_ERR_INVALID_LIBRARY_HANDLE] = "Invalid library handle",
|
||||
[DL_ERR_BAD_SYMBOL_NAME] = "Invalid symbol name",
|
||||
[DL_ERR_SYMBOL_NOT_FOUND] = "Symbol not found",
|
||||
[DL_ERR_SYMBOL_NOT_GLOBAL] = "Symbol is not global",
|
||||
};
|
||||
|
||||
#define likely(expr) __builtin_expect (expr, 1)
|
||||
#define unlikely(expr) __builtin_expect (expr, 0)
|
||||
|
||||
static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void set_dlerror(int err)
|
||||
{
|
||||
format_buffer(dl_err_buf, sizeof(dl_err_buf), "%s: %s", dl_errors[err],
|
||||
linker_get_error());
|
||||
dl_err_str = (const char *)&dl_err_buf[0];
|
||||
};
|
||||
|
||||
void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
soinfo *ret;
|
||||
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
ret = find_library(filename);
|
||||
if (unlikely(ret == NULL)) {
|
||||
set_dlerror(DL_ERR_CANNOT_LOAD_LIBRARY);
|
||||
} else {
|
||||
ret->refcount++;
|
||||
}
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *dlerror(void)
|
||||
{
|
||||
const char *tmp = dl_err_str;
|
||||
dl_err_str = NULL;
|
||||
return (const char *)tmp;
|
||||
}
|
||||
|
||||
void *dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
soinfo *found;
|
||||
Elf32_Sym *sym;
|
||||
unsigned bind;
|
||||
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
|
||||
if(unlikely(handle == 0)) {
|
||||
set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE);
|
||||
goto err;
|
||||
}
|
||||
if(unlikely(symbol == 0)) {
|
||||
set_dlerror(DL_ERR_BAD_SYMBOL_NAME);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(handle == RTLD_DEFAULT) {
|
||||
sym = lookup(symbol, &found, NULL);
|
||||
} else if(handle == RTLD_NEXT) {
|
||||
void *ret_addr = __builtin_return_address(0);
|
||||
soinfo *si = find_containing_library(ret_addr);
|
||||
|
||||
sym = NULL;
|
||||
if(si && si->next) {
|
||||
sym = lookup(symbol, &found, si->next);
|
||||
}
|
||||
} else {
|
||||
found = (soinfo*)handle;
|
||||
sym = lookup_in_library(found, symbol);
|
||||
}
|
||||
|
||||
if(likely(sym != 0)) {
|
||||
bind = ELF32_ST_BIND(sym->st_info);
|
||||
|
||||
if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) {
|
||||
unsigned ret = sym->st_value + found->base;
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL);
|
||||
}
|
||||
else
|
||||
set_dlerror(DL_ERR_SYMBOL_NOT_FOUND);
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dladdr(void *addr, Dl_info *info)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
|
||||
/* Determine if this address can be found in any library currently mapped */
|
||||
soinfo *si = find_containing_library(addr);
|
||||
|
||||
if(si) {
|
||||
memset(info, 0, sizeof(Dl_info));
|
||||
|
||||
info->dli_fname = si->name;
|
||||
info->dli_fbase = (void*)si->base;
|
||||
|
||||
/* Determine if any symbol in the library contains the specified address */
|
||||
Elf32_Sym *sym = find_containing_symbol(addr, si);
|
||||
|
||||
if(sym != NULL) {
|
||||
info->dli_sname = si->strtab + sym->st_name;
|
||||
info->dli_saddr = (void*)(si->base + sym->st_value);
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int dlclose(void *handle)
|
||||
{
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
(void)unload_library((soinfo*)handle);
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(ANDROID_ARM_LINKER)
|
||||
// 0000000 00011111 111112 22222222 2333333 333344444444445555555
|
||||
// 0123456 78901234 567890 12345678 9012345 678901234567890123456
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0"
|
||||
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455
|
||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
|
||||
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
// 0000000 00011111 111112 22222222 2333333 3333444444444455
|
||||
// 0123456 78901234 567890 12345678 9012345 6789012345678901
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0"
|
||||
|
||||
#else /* !defined(ANDROID_ARM_LINKER) && !defined(ANDROID_X86_LINKER) */
|
||||
#error Unsupported architecture. Only ARM and x86 are presently supported.
|
||||
#endif
|
||||
|
||||
|
||||
static Elf32_Sym libdl_symtab[] = {
|
||||
// total length of libdl_info.strtab, including trailing 0
|
||||
// This is actually the the STH_UNDEF entry. Technically, it's
|
||||
// supposed to have st_name == 0, but instead, it points to an index
|
||||
// in the strtab with a \0 to make iterating through the symtab easier.
|
||||
{ st_name: sizeof(ANDROID_LIBDL_STRTAB) - 1,
|
||||
},
|
||||
{ st_name: 0, // starting index of the name in libdl_info.strtab
|
||||
st_value: (Elf32_Addr) &dlopen,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
{ st_name: 7,
|
||||
st_value: (Elf32_Addr) &dlclose,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
{ st_name: 15,
|
||||
st_value: (Elf32_Addr) &dlsym,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
{ st_name: 21,
|
||||
st_value: (Elf32_Addr) &dlerror,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
{ st_name: 29,
|
||||
st_value: (Elf32_Addr) &dladdr,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
{ st_name: 36,
|
||||
st_value: (Elf32_Addr) &dl_unwind_find_exidx,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
{ st_name: 36,
|
||||
st_value: (Elf32_Addr) &dl_iterate_phdr,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
{ st_name: 36,
|
||||
st_value: (Elf32_Addr) &dl_iterate_phdr,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Fake out a hash table with a single bucket.
|
||||
* A search of the hash table will look through
|
||||
* libdl_symtab starting with index [1], then
|
||||
* use libdl_chains to find the next index to
|
||||
* look at. libdl_chains should be set up to
|
||||
* walk through every element in libdl_symtab,
|
||||
* and then end with 0 (sentinel value).
|
||||
*
|
||||
* I.e., libdl_chains should look like
|
||||
* { 0, 2, 3, ... N, 0 } where N is the number
|
||||
* of actual symbols, or nelems(libdl_symtab)-1
|
||||
* (since the first element of libdl_symtab is not
|
||||
* a real symbol).
|
||||
*
|
||||
* (see _elf_lookup())
|
||||
*
|
||||
* Note that adding any new symbols here requires
|
||||
* stubbing them out in libdl.
|
||||
*/
|
||||
static unsigned libdl_buckets[1] = { 1 };
|
||||
static unsigned libdl_chains[7] = { 0, 2, 3, 4, 5, 6, 0 };
|
||||
|
||||
soinfo libdl_info = {
|
||||
name: "libdl.so",
|
||||
flags: FLAG_LINKED,
|
||||
|
||||
strtab: ANDROID_LIBDL_STRTAB,
|
||||
symtab: libdl_symtab,
|
||||
|
||||
nbucket: 1,
|
||||
nchain: 7,
|
||||
bucket: libdl_buckets,
|
||||
chain: libdl_chains,
|
||||
};
|
||||
|
67
other-licenses/android/dlfcn.h
Normal file
67
other-licenses/android/dlfcn.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#ifndef __DLFCN_H__
|
||||
#define __DLFCN_H__
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef struct {
|
||||
const char *dli_fname; /* Pathname of shared object that
|
||||
contains address */
|
||||
void *dli_fbase; /* Address at which shared object
|
||||
is loaded */
|
||||
const char *dli_sname; /* Name of nearest symbol with address
|
||||
lower than addr */
|
||||
void *dli_saddr; /* Exact address of symbol named
|
||||
in dli_sname */
|
||||
} Dl_info;
|
||||
|
||||
extern void* dlopen(const char* filename, int flag);
|
||||
extern int dlclose(void* handle);
|
||||
extern const char* dlerror(void);
|
||||
extern void* dlsym(void* handle, const char* symbol);
|
||||
extern int dladdr(void* addr, Dl_info *info);
|
||||
|
||||
enum {
|
||||
RTLD_NOW = 0,
|
||||
RTLD_LAZY = 1,
|
||||
|
||||
RTLD_LOCAL = 0,
|
||||
RTLD_GLOBAL = 2,
|
||||
};
|
||||
|
||||
#define RTLD_DEFAULT ((void*) 0xffffffff)
|
||||
#define RTLD_NEXT ((void*) 0xfffffffe)
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif /* __DLFCN_H */
|
||||
|
||||
|
2259
other-licenses/android/linker.c
Normal file
2259
other-licenses/android/linker.c
Normal file
File diff suppressed because it is too large
Load Diff
239
other-licenses/android/linker.h
Normal file
239
other-licenses/android/linker.h
Normal file
@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINKER_H_
|
||||
#define _LINKER_H_
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <linux/elf.h>
|
||||
|
||||
#undef PAGE_MASK
|
||||
#undef PAGE_SIZE
|
||||
#define PAGE_SIZE 4096
|
||||
#define PAGE_MASK 4095
|
||||
|
||||
void debugger_init();
|
||||
const char *addr_to_name(unsigned addr);
|
||||
|
||||
/* magic shared structures that GDB knows about */
|
||||
|
||||
struct link_map
|
||||
{
|
||||
uintptr_t l_addr;
|
||||
char * l_name;
|
||||
uintptr_t l_ld;
|
||||
struct link_map * l_next;
|
||||
struct link_map * l_prev;
|
||||
};
|
||||
|
||||
/* needed for dl_iterate_phdr to be passed to the callbacks provided */
|
||||
struct dl_phdr_info
|
||||
{
|
||||
Elf32_Addr dlpi_addr;
|
||||
const char *dlpi_name;
|
||||
const Elf32_Phdr *dlpi_phdr;
|
||||
Elf32_Half dlpi_phnum;
|
||||
};
|
||||
|
||||
|
||||
// Values for r_debug->state
|
||||
enum {
|
||||
RT_CONSISTENT,
|
||||
RT_ADD,
|
||||
RT_DELETE
|
||||
};
|
||||
|
||||
struct r_debug
|
||||
{
|
||||
int32_t r_version;
|
||||
struct link_map * r_map;
|
||||
void (*r_brk)(void);
|
||||
int32_t r_state;
|
||||
uintptr_t r_ldbase;
|
||||
};
|
||||
|
||||
typedef struct soinfo soinfo;
|
||||
|
||||
#define FLAG_LINKED 0x00000001
|
||||
#define FLAG_ERROR 0x00000002
|
||||
#define FLAG_EXE 0x00000004 // The main executable
|
||||
#define FLAG_PRELINKED 0x00000008 // This is a pre-linked lib
|
||||
|
||||
#define SOINFO_NAME_LEN 128
|
||||
|
||||
struct soinfo
|
||||
{
|
||||
const char name[SOINFO_NAME_LEN];
|
||||
Elf32_Phdr *phdr;
|
||||
int phnum;
|
||||
unsigned entry;
|
||||
unsigned base;
|
||||
unsigned size;
|
||||
// buddy-allocator index, negative for prelinked libraries
|
||||
int ba_index;
|
||||
|
||||
unsigned *dynamic;
|
||||
|
||||
unsigned wrprotect_start;
|
||||
unsigned wrprotect_end;
|
||||
|
||||
soinfo *next;
|
||||
unsigned flags;
|
||||
|
||||
const char *strtab;
|
||||
Elf32_Sym *symtab;
|
||||
|
||||
unsigned nbucket;
|
||||
unsigned nchain;
|
||||
unsigned *bucket;
|
||||
unsigned *chain;
|
||||
|
||||
unsigned *plt_got;
|
||||
|
||||
Elf32_Rel *plt_rel;
|
||||
unsigned plt_rel_count;
|
||||
|
||||
Elf32_Rel *rel;
|
||||
unsigned rel_count;
|
||||
|
||||
#ifdef ANDROID_SH_LINKER
|
||||
Elf32_Rela *plt_rela;
|
||||
unsigned plt_rela_count;
|
||||
|
||||
Elf32_Rela *rela;
|
||||
unsigned rela_count;
|
||||
#endif /* ANDROID_SH_LINKER */
|
||||
|
||||
unsigned *preinit_array;
|
||||
unsigned preinit_array_count;
|
||||
|
||||
unsigned *init_array;
|
||||
unsigned init_array_count;
|
||||
unsigned *fini_array;
|
||||
unsigned fini_array_count;
|
||||
|
||||
void (*init_func)(void);
|
||||
void (*fini_func)(void);
|
||||
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
/* ARM EABI section used for stack unwinding. */
|
||||
unsigned *ARM_exidx;
|
||||
unsigned ARM_exidx_count;
|
||||
#endif
|
||||
|
||||
unsigned refcount;
|
||||
struct link_map linkmap;
|
||||
};
|
||||
|
||||
|
||||
extern soinfo libdl_info;
|
||||
|
||||
/* these must all be powers of two */
|
||||
#ifdef ARCH_SH
|
||||
#define LIBBASE 0x60000000
|
||||
#define LIBLAST 0x70000000
|
||||
#define LIBINC 0x00100000
|
||||
#else
|
||||
#define LIBBASE 0x80000000
|
||||
#define LIBLAST 0x90000000
|
||||
#define LIBINC 0x00100000
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
|
||||
#define R_ARM_COPY 20
|
||||
#define R_ARM_GLOB_DAT 21
|
||||
#define R_ARM_JUMP_SLOT 22
|
||||
#define R_ARM_RELATIVE 23
|
||||
|
||||
/* According to the AAPCS specification, we only
|
||||
* need the above relocations. However, in practice,
|
||||
* the following ones turn up from time to time.
|
||||
*/
|
||||
#define R_ARM_ABS32 2
|
||||
#define R_ARM_REL32 3
|
||||
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GLOB_DAT 6
|
||||
#define R_386_JUMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
|
||||
#elif defined(ANDROID_SH_LINKER)
|
||||
|
||||
#define R_SH_DIR32 1
|
||||
#define R_SH_GLOB_DAT 163
|
||||
#define R_SH_JUMP_SLOT 164
|
||||
#define R_SH_RELATIVE 165
|
||||
|
||||
#endif /* ANDROID_*_LINKER */
|
||||
|
||||
|
||||
#ifndef DT_INIT_ARRAY
|
||||
#define DT_INIT_ARRAY 25
|
||||
#endif
|
||||
|
||||
#ifndef DT_FINI_ARRAY
|
||||
#define DT_FINI_ARRAY 26
|
||||
#endif
|
||||
|
||||
#ifndef DT_INIT_ARRAYSZ
|
||||
#define DT_INIT_ARRAYSZ 27
|
||||
#endif
|
||||
|
||||
#ifndef DT_FINI_ARRAYSZ
|
||||
#define DT_FINI_ARRAYSZ 28
|
||||
#endif
|
||||
|
||||
#ifndef DT_PREINIT_ARRAY
|
||||
#define DT_PREINIT_ARRAY 32
|
||||
#endif
|
||||
|
||||
#ifndef DT_PREINIT_ARRAYSZ
|
||||
#define DT_PREINIT_ARRAYSZ 33
|
||||
#endif
|
||||
|
||||
soinfo *find_library(const char *name);
|
||||
unsigned unload_library(soinfo *si);
|
||||
Elf32_Sym *lookup_in_library(soinfo *si, const char *name);
|
||||
Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start);
|
||||
soinfo *find_containing_library(void *addr);
|
||||
Elf32_Sym *find_containing_symbol(void *addr, soinfo *si);
|
||||
const char *linker_get_error(void);
|
||||
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
typedef long unsigned int *_Unwind_Ptr;
|
||||
_Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount);
|
||||
#elif defined(ANDROID_X86_LINKER) || defined(ANDROID_SH_LINKER)
|
||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *);
|
||||
#endif
|
||||
|
||||
#endif
|
155
other-licenses/android/linker_debug.h
Normal file
155
other-licenses/android/linker_debug.h
Normal file
@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (C) 2008-2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef _LINKER_DEBUG_H_
|
||||
#define _LINKER_DEBUG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifndef LINKER_DEBUG
|
||||
#error LINKER_DEBUG should be defined to either 1 or 0 in Android.mk
|
||||
#endif
|
||||
|
||||
/* set LINKER_DEBUG_TO_LOG to 1 to send the logs to logcat,
|
||||
* or 0 to use stdout instead.
|
||||
*/
|
||||
#define LINKER_DEBUG_TO_LOG 1
|
||||
#define TRACE_DEBUG 1
|
||||
#define DO_TRACE_LOOKUP 1
|
||||
#define DO_TRACE_RELO 1
|
||||
#define TIMING 0
|
||||
#define STATS 0
|
||||
#define COUNT_PAGES 0
|
||||
|
||||
/*********************************************************************
|
||||
* You shouldn't need to modify anything below unless you are adding
|
||||
* more debugging information.
|
||||
*
|
||||
* To enable/disable specific debug options, change the defines above
|
||||
*********************************************************************/
|
||||
|
||||
|
||||
/*********************************************************************/
|
||||
#undef TRUE
|
||||
#undef FALSE
|
||||
#define TRUE 1
|
||||
#define FALSE 0
|
||||
|
||||
/* Only use printf() during debugging. We have seen occasional memory
|
||||
* corruption when the linker uses printf().
|
||||
*/
|
||||
#if LINKER_DEBUG
|
||||
#include "linker_format.h"
|
||||
extern int debug_verbosity;
|
||||
#if LINKER_DEBUG_TO_LOG
|
||||
extern int format_log(int, const char *, const char *, ...);
|
||||
#define _PRINTVF(v,f,x...) \
|
||||
do { \
|
||||
if (debug_verbosity > (v)) format_log(5-(v),"linker",x); \
|
||||
} while (0)
|
||||
#else /* !LINKER_DEBUG_TO_LOG */
|
||||
extern int format_fd(int, const char *, ...);
|
||||
#define _PRINTVF(v,f,x...) \
|
||||
do { \
|
||||
if (debug_verbosity > (v)) format_fd(1, x); \
|
||||
} while (0)
|
||||
#endif /* !LINKER_DEBUG_TO_LOG */
|
||||
#else /* !LINKER_DEBUG */
|
||||
#define _PRINTVF(v,f,x...) do {} while(0)
|
||||
#endif /* LINKER_DEBUG */
|
||||
|
||||
#define PRINT(x...) _PRINTVF(-1, FALSE, x)
|
||||
#define INFO(x...) _PRINTVF(0, TRUE, x)
|
||||
#define TRACE(x...) _PRINTVF(1, TRUE, x)
|
||||
#define WARN(fmt,args...) \
|
||||
_PRINTVF(-1, TRUE, "%s:%d| WARNING: " fmt, __FILE__, __LINE__, ## args)
|
||||
#define ERROR(fmt,args...) \
|
||||
_PRINTVF(-1, TRUE, "%s:%d| ERROR: " fmt, __FILE__, __LINE__, ## args)
|
||||
|
||||
|
||||
#if TRACE_DEBUG
|
||||
#define DEBUG(x...) _PRINTVF(2, TRUE, "DEBUG: " x)
|
||||
#else /* !TRACE_DEBUG */
|
||||
#define DEBUG(x...) do {} while (0)
|
||||
#endif /* TRACE_DEBUG */
|
||||
|
||||
#if LINKER_DEBUG
|
||||
#define TRACE_TYPE(t,x...) do { if (DO_TRACE_##t) { TRACE(x); } } while (0)
|
||||
#else /* !LINKER_DEBUG */
|
||||
#define TRACE_TYPE(t,x...) do {} while (0)
|
||||
#endif /* LINKER_DEBUG */
|
||||
|
||||
#if STATS
|
||||
#define RELOC_ABSOLUTE 0
|
||||
#define RELOC_RELATIVE 1
|
||||
#define RELOC_COPY 2
|
||||
#define RELOC_SYMBOL 3
|
||||
#define NUM_RELOC_STATS 4
|
||||
|
||||
struct _link_stats {
|
||||
int reloc[NUM_RELOC_STATS];
|
||||
};
|
||||
extern struct _link_stats linker_stats;
|
||||
|
||||
#define COUNT_RELOC(type) \
|
||||
do { if (type >= 0 && type < NUM_RELOC_STATS) { \
|
||||
linker_stats.reloc[type] += 1; \
|
||||
} else { \
|
||||
PRINT("Unknown reloc stat requested\n"); \
|
||||
} \
|
||||
} while(0)
|
||||
#else /* !STATS */
|
||||
#define COUNT_RELOC(type) do {} while(0)
|
||||
#endif /* STATS */
|
||||
|
||||
#if TIMING
|
||||
#undef WARN
|
||||
#define WARN(x...) do {} while (0)
|
||||
#endif /* TIMING */
|
||||
|
||||
#if COUNT_PAGES
|
||||
extern unsigned bitmask[];
|
||||
#define MARK(offset) do { \
|
||||
bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \
|
||||
} while(0)
|
||||
#else
|
||||
#define MARK(x) do {} while (0)
|
||||
#endif
|
||||
|
||||
#define DEBUG_DUMP_PHDR(phdr, name, pid) do { \
|
||||
DEBUG("%5d %s (phdr = 0x%08x)\n", (pid), (name), (unsigned)(phdr)); \
|
||||
DEBUG("\t\tphdr->offset = 0x%08x\n", (unsigned)((phdr)->p_offset)); \
|
||||
DEBUG("\t\tphdr->p_vaddr = 0x%08x\n", (unsigned)((phdr)->p_vaddr)); \
|
||||
DEBUG("\t\tphdr->p_paddr = 0x%08x\n", (unsigned)((phdr)->p_paddr)); \
|
||||
DEBUG("\t\tphdr->p_filesz = 0x%08x\n", (unsigned)((phdr)->p_filesz)); \
|
||||
DEBUG("\t\tphdr->p_memsz = 0x%08x\n", (unsigned)((phdr)->p_memsz)); \
|
||||
DEBUG("\t\tphdr->p_flags = 0x%08x\n", (unsigned)((phdr)->p_flags)); \
|
||||
DEBUG("\t\tphdr->p_align = 0x%08x\n", (unsigned)((phdr)->p_align)); \
|
||||
} while (0)
|
||||
|
||||
#endif /* _LINKER_DEBUG_H_ */
|
703
other-licenses/android/linker_format.c
Normal file
703
other-licenses/android/linker_format.c
Normal file
@ -0,0 +1,703 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include "linker_format.h"
|
||||
#include "linker_debug.h"
|
||||
|
||||
/* define UNIT_TESTS to build this file as a single executable that runs
|
||||
* the formatter's unit tests
|
||||
*/
|
||||
#define xxUNIT_TESTS
|
||||
|
||||
/*** Generic output sink
|
||||
***/
|
||||
|
||||
typedef struct {
|
||||
void *opaque;
|
||||
void (*send)(void *opaque, const char *data, int len);
|
||||
} Out;
|
||||
|
||||
static void
|
||||
out_send(Out *o, const void *data, size_t len)
|
||||
{
|
||||
o->send(o->opaque, data, (int)len);
|
||||
}
|
||||
|
||||
static void
|
||||
out_send_repeat(Out *o, char ch, int count)
|
||||
{
|
||||
char pad[8];
|
||||
const int padSize = (int)sizeof(pad);
|
||||
|
||||
memset(pad, ch, sizeof(pad));
|
||||
while (count > 0) {
|
||||
int avail = count;
|
||||
if (avail > padSize) {
|
||||
avail = padSize;
|
||||
}
|
||||
o->send(o->opaque, pad, avail);
|
||||
count -= avail;
|
||||
}
|
||||
}
|
||||
|
||||
/* forward declaration */
|
||||
static void
|
||||
out_vformat(Out *o, const char *format, va_list args);
|
||||
|
||||
/*** Bounded buffer output
|
||||
***/
|
||||
|
||||
typedef struct {
|
||||
Out out[1];
|
||||
char *buffer;
|
||||
char *pos;
|
||||
char *end;
|
||||
int total;
|
||||
} BufOut;
|
||||
|
||||
static void
|
||||
buf_out_send(void *opaque, const char *data, int len)
|
||||
{
|
||||
BufOut *bo = opaque;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen(data);
|
||||
|
||||
bo->total += len;
|
||||
|
||||
while (len > 0) {
|
||||
int avail = bo->end - bo->pos;
|
||||
if (avail == 0)
|
||||
break;
|
||||
if (avail > len)
|
||||
avail = len;
|
||||
memcpy(bo->pos, data, avail);
|
||||
bo->pos += avail;
|
||||
bo->pos[0] = '\0';
|
||||
len -= avail;
|
||||
}
|
||||
}
|
||||
|
||||
static Out*
|
||||
buf_out_init(BufOut *bo, char *buffer, size_t size)
|
||||
{
|
||||
if (size == 0)
|
||||
return NULL;
|
||||
|
||||
bo->out->opaque = bo;
|
||||
bo->out->send = buf_out_send;
|
||||
bo->buffer = buffer;
|
||||
bo->end = buffer + size - 1;
|
||||
bo->pos = bo->buffer;
|
||||
bo->pos[0] = '\0';
|
||||
bo->total = 0;
|
||||
|
||||
return bo->out;
|
||||
}
|
||||
|
||||
static int
|
||||
buf_out_length(BufOut *bo)
|
||||
{
|
||||
return bo->total;
|
||||
}
|
||||
|
||||
static int
|
||||
vformat_buffer(char *buff, size_t buffsize, const char *format, va_list args)
|
||||
{
|
||||
BufOut bo;
|
||||
Out *out;
|
||||
|
||||
out = buf_out_init(&bo, buff, buffsize);
|
||||
if (out == NULL)
|
||||
return 0;
|
||||
|
||||
out_vformat(out, format, args);
|
||||
|
||||
return buf_out_length(&bo);
|
||||
}
|
||||
|
||||
int
|
||||
format_buffer(char *buff, size_t buffsize, const char *format, ...)
|
||||
{
|
||||
va_list args;
|
||||
int ret;
|
||||
|
||||
va_start(args, format);
|
||||
ret = vformat_buffer(buff, buffsize, format, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* The __stack_chk_fail() function calls __libc_android_log_print()
|
||||
* which calls vsnprintf().
|
||||
*
|
||||
* We define our version of the function here to avoid dragging
|
||||
* about 25 KB of C library routines related to formatting.
|
||||
*/
|
||||
int
|
||||
vsnprintf(char *buff, size_t bufsize, const char *format, va_list args)
|
||||
{
|
||||
return format_buffer(buff, bufsize, format, args);
|
||||
}
|
||||
|
||||
#if LINKER_DEBUG
|
||||
|
||||
#if !LINKER_DEBUG_TO_LOG
|
||||
|
||||
/*** File descriptor output
|
||||
***/
|
||||
|
||||
typedef struct {
|
||||
Out out[1];
|
||||
int fd;
|
||||
int total;
|
||||
} FdOut;
|
||||
|
||||
static void
|
||||
fd_out_send(void *opaque, const char *data, int len)
|
||||
{
|
||||
FdOut *fdo = opaque;
|
||||
|
||||
if (len < 0)
|
||||
len = strlen(data);
|
||||
|
||||
while (len > 0) {
|
||||
int ret = write(fdo->fd, data, len);
|
||||
if (ret < 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
data += ret;
|
||||
len -= ret;
|
||||
fdo->total += ret;
|
||||
}
|
||||
}
|
||||
|
||||
static Out*
|
||||
fd_out_init(FdOut *fdo, int fd)
|
||||
{
|
||||
fdo->out->opaque = fdo;
|
||||
fdo->out->send = fd_out_send;
|
||||
fdo->fd = fd;
|
||||
fdo->total = 0;
|
||||
|
||||
return fdo->out;
|
||||
}
|
||||
|
||||
static int
|
||||
fd_out_length(FdOut *fdo)
|
||||
{
|
||||
return fdo->total;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
format_fd(int fd, const char *format, ...)
|
||||
{
|
||||
FdOut fdo;
|
||||
Out* out;
|
||||
va_list args;
|
||||
|
||||
out = fd_out_init(&fdo, fd);
|
||||
if (out == NULL)
|
||||
return 0;
|
||||
|
||||
va_start(args, format);
|
||||
out_vformat(out, format, args);
|
||||
va_end(args);
|
||||
|
||||
return fd_out_length(&fdo);
|
||||
}
|
||||
|
||||
#else /* LINKER_DEBUG_TO_LOG */
|
||||
|
||||
/*** Log output
|
||||
***/
|
||||
|
||||
/* We need our own version of __libc_android_log_vprint, otherwise
|
||||
* the log output is completely broken. Probably due to the fact
|
||||
* that the C library is not initialized yet.
|
||||
*
|
||||
* You can test that by setting CUSTOM_LOG_VPRINT to 0
|
||||
*/
|
||||
#define CUSTOM_LOG_VPRINT 1
|
||||
|
||||
#if CUSTOM_LOG_VPRINT
|
||||
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
static int log_vprint(int prio, const char *tag, const char *fmt, va_list args)
|
||||
{
|
||||
char buf[1024];
|
||||
int result;
|
||||
static int log_fd = -1;
|
||||
|
||||
result = vformat_buffer(buf, sizeof buf, fmt, args);
|
||||
|
||||
if (log_fd < 0) {
|
||||
log_fd = open("/dev/log/main", O_WRONLY);
|
||||
if (log_fd < 0)
|
||||
return result;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t ret;
|
||||
struct iovec vec[3];
|
||||
|
||||
vec[0].iov_base = (unsigned char *) &prio;
|
||||
vec[0].iov_len = 1;
|
||||
vec[1].iov_base = (void *) tag;
|
||||
vec[1].iov_len = strlen(tag) + 1;
|
||||
vec[2].iov_base = (void *) buf;
|
||||
vec[2].iov_len = strlen(buf) + 1;
|
||||
|
||||
do {
|
||||
ret = writev(log_fd, vec, 3);
|
||||
} while ((ret < 0) && (errno == EINTR));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
#define __libc_android_log_vprint log_vprint
|
||||
|
||||
#else /* !CUSTOM_LOG_VPRINT */
|
||||
|
||||
extern int __libc_android_log_vprint(int prio, const char* tag, const char* format, va_list ap);
|
||||
|
||||
#endif /* !CUSTOM_LOG_VPRINT */
|
||||
|
||||
int
|
||||
format_log(int prio, const char *tag, const char *format, ...)
|
||||
{
|
||||
int ret;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
ret = __libc_android_log_vprint(prio, tag, format, args);
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#endif /* LINKER_DEBUG_TO_LOG */
|
||||
|
||||
#endif /* LINKER_DEBUG */
|
||||
|
||||
/*** formatted output implementation
|
||||
***/
|
||||
|
||||
/* Parse a decimal string from 'format + *ppos',
|
||||
* return the value, and writes the new position past
|
||||
* the decimal string in '*ppos' on exit.
|
||||
*
|
||||
* NOTE: Does *not* handle a sign prefix.
|
||||
*/
|
||||
static unsigned
|
||||
parse_decimal(const char *format, int *ppos)
|
||||
{
|
||||
const char* p = format + *ppos;
|
||||
unsigned result = 0;
|
||||
|
||||
for (;;) {
|
||||
int ch = *p;
|
||||
unsigned d = (unsigned)(ch - '0');
|
||||
|
||||
if (d >= 10U)
|
||||
break;
|
||||
|
||||
result = result*10 + d;
|
||||
p++;
|
||||
}
|
||||
*ppos = p - format;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* write an octal/decimal/number into a bounded buffer.
|
||||
* assumes that bufsize > 0, and 'digits' is a string of
|
||||
* digits of at least 'base' values.
|
||||
*/
|
||||
static void
|
||||
format_number(char *buffer, size_t bufsize, uint64_t value, int base, const char *digits)
|
||||
{
|
||||
char *pos = buffer;
|
||||
char *end = buffer + bufsize - 1;
|
||||
|
||||
/* generate digit string in reverse order */
|
||||
while (value) {
|
||||
unsigned d = value % base;
|
||||
value /= base;
|
||||
if (pos < end) {
|
||||
*pos++ = digits[d];
|
||||
}
|
||||
}
|
||||
|
||||
/* special case for 0 */
|
||||
if (pos == buffer) {
|
||||
if (pos < end) {
|
||||
*pos++ = '0';
|
||||
}
|
||||
}
|
||||
pos[0] = '\0';
|
||||
|
||||
/* now reverse digit string in-place */
|
||||
end = pos - 1;
|
||||
pos = buffer;
|
||||
while (pos < end) {
|
||||
int ch = pos[0];
|
||||
pos[0] = end[0];
|
||||
end[0] = (char) ch;
|
||||
pos++;
|
||||
end--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write an integer (octal or decimal) into a buffer, assumes buffsize > 2 */
|
||||
static void
|
||||
format_integer(char *buffer, size_t buffsize, uint64_t value, int base, int isSigned)
|
||||
{
|
||||
if (isSigned && (int64_t)value < 0) {
|
||||
buffer[0] = '-';
|
||||
buffer += 1;
|
||||
buffsize -= 1;
|
||||
value = (uint64_t)(-(int64_t)value);
|
||||
}
|
||||
|
||||
format_number(buffer, buffsize, value, base, "0123456789");
|
||||
}
|
||||
|
||||
/* Write an octal into a buffer, assumes buffsize > 2 */
|
||||
static void
|
||||
format_octal(char *buffer, size_t buffsize, uint64_t value, int isSigned)
|
||||
{
|
||||
format_integer(buffer, buffsize, value, 8, isSigned);
|
||||
}
|
||||
|
||||
/* Write a decimal into a buffer, assumes buffsize > 2 */
|
||||
static void
|
||||
format_decimal(char *buffer, size_t buffsize, uint64_t value, int isSigned)
|
||||
{
|
||||
format_integer(buffer, buffsize, value, 10, isSigned);
|
||||
}
|
||||
|
||||
/* Write an hexadecimal into a buffer, isCap is true for capital alphas.
|
||||
* Assumes bufsize > 2 */
|
||||
static void
|
||||
format_hex(char *buffer, size_t buffsize, uint64_t value, int isCap)
|
||||
{
|
||||
const char *digits = isCap ? "0123456789ABCDEF" : "0123456789abcdef";
|
||||
|
||||
format_number(buffer, buffsize, value, 16, digits);
|
||||
}
|
||||
|
||||
|
||||
/* Perform formatted output to an output target 'o' */
|
||||
static void
|
||||
out_vformat(Out *o, const char *format, va_list args)
|
||||
{
|
||||
int nn = 0, mm;
|
||||
int padZero = 0;
|
||||
int padLeft = 0;
|
||||
char sign = '\0';
|
||||
int width = -1;
|
||||
int prec = -1;
|
||||
size_t bytelen = sizeof(int);
|
||||
const char* str;
|
||||
int slen;
|
||||
char buffer[32]; /* temporary buffer used to format numbers */
|
||||
|
||||
for (;;) {
|
||||
char c;
|
||||
|
||||
/* first, find all characters that are not 0 or '%' */
|
||||
/* then send them to the output directly */
|
||||
mm = nn;
|
||||
do {
|
||||
c = format[mm];
|
||||
if (c == '\0' || c == '%')
|
||||
break;
|
||||
mm++;
|
||||
} while (1);
|
||||
|
||||
if (mm > nn) {
|
||||
out_send(o, format+nn, mm-nn);
|
||||
nn = mm;
|
||||
}
|
||||
|
||||
/* is this it ? then exit */
|
||||
if (c == '\0')
|
||||
break;
|
||||
|
||||
/* nope, we are at a '%' modifier */
|
||||
nn++; // skip it
|
||||
|
||||
/* parse flags */
|
||||
for (;;) {
|
||||
c = format[nn++];
|
||||
if (c == '\0') { /* single trailing '%' ? */
|
||||
c = '%';
|
||||
out_send(o, &c, 1);
|
||||
return;
|
||||
}
|
||||
else if (c == '0') {
|
||||
padZero = 1;
|
||||
continue;
|
||||
}
|
||||
else if (c == '-') {
|
||||
padLeft = 1;
|
||||
continue;
|
||||
}
|
||||
else if (c == ' ' || c == '+') {
|
||||
sign = c;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* parse field width */
|
||||
if ((c >= '0' && c <= '9')) {
|
||||
nn --;
|
||||
width = (int)parse_decimal(format, &nn);
|
||||
c = format[nn++];
|
||||
}
|
||||
|
||||
/* parse precision */
|
||||
if (c == '.') {
|
||||
prec = (int)parse_decimal(format, &nn);
|
||||
c = format[nn++];
|
||||
}
|
||||
|
||||
/* length modifier */
|
||||
switch (c) {
|
||||
case 'h':
|
||||
bytelen = sizeof(short);
|
||||
if (format[nn] == 'h') {
|
||||
bytelen = sizeof(char);
|
||||
nn += 1;
|
||||
}
|
||||
c = format[nn++];
|
||||
break;
|
||||
case 'l':
|
||||
bytelen = sizeof(long);
|
||||
if (format[nn] == 'l') {
|
||||
bytelen = sizeof(long long);
|
||||
nn += 1;
|
||||
}
|
||||
c = format[nn++];
|
||||
break;
|
||||
case 'z':
|
||||
bytelen = sizeof(size_t);
|
||||
c = format[nn++];
|
||||
break;
|
||||
case 't':
|
||||
bytelen = sizeof(ptrdiff_t);
|
||||
c = format[nn++];
|
||||
break;
|
||||
case 'p':
|
||||
bytelen = sizeof(void*);
|
||||
c = format[nn++];
|
||||
default:
|
||||
;
|
||||
}
|
||||
|
||||
/* conversion specifier */
|
||||
if (c == 's') {
|
||||
/* string */
|
||||
str = va_arg(args, const char*);
|
||||
} else if (c == 'c') {
|
||||
/* character */
|
||||
/* NOTE: char is promoted to int when passed through the stack */
|
||||
buffer[0] = (char) va_arg(args, int);
|
||||
buffer[1] = '\0';
|
||||
str = buffer;
|
||||
} else if (c == 'p') {
|
||||
uint64_t value = (uint64_t)(ptrdiff_t) va_arg(args, void*);
|
||||
buffer[0] = '0';
|
||||
buffer[1] = 'x';
|
||||
format_hex(buffer + 2, sizeof buffer-2, value, 0);
|
||||
str = buffer;
|
||||
} else {
|
||||
/* integers - first read value from stack */
|
||||
uint64_t value;
|
||||
int isSigned = (c == 'd' || c == 'i' || c == 'o');
|
||||
|
||||
/* NOTE: int8_t and int16_t are promoted to int when passed
|
||||
* through the stack
|
||||
*/
|
||||
switch (bytelen) {
|
||||
case 1: value = (uint8_t) va_arg(args, int); break;
|
||||
case 2: value = (uint16_t) va_arg(args, int); break;
|
||||
case 4: value = va_arg(args, uint32_t); break;
|
||||
case 8: value = va_arg(args, uint64_t); break;
|
||||
default: return; /* should not happen */
|
||||
}
|
||||
|
||||
/* sign extension, if needed */
|
||||
if (isSigned) {
|
||||
int shift = 64 - 8*bytelen;
|
||||
value = (uint64_t)(((int64_t)(value << shift)) >> shift);
|
||||
}
|
||||
|
||||
/* format the number properly into our buffer */
|
||||
switch (c) {
|
||||
case 'i': case 'd':
|
||||
format_integer(buffer, sizeof buffer, value, 10, isSigned);
|
||||
break;
|
||||
case 'o':
|
||||
format_integer(buffer, sizeof buffer, value, 8, isSigned);
|
||||
break;
|
||||
case 'x': case 'X':
|
||||
format_hex(buffer, sizeof buffer, value, (c == 'X'));
|
||||
break;
|
||||
default:
|
||||
buffer[0] = '\0';
|
||||
}
|
||||
/* then point to it */
|
||||
str = buffer;
|
||||
}
|
||||
|
||||
/* if we are here, 'str' points to the content that must be
|
||||
* outputted. handle padding and alignment now */
|
||||
|
||||
slen = strlen(str);
|
||||
|
||||
if (slen < width && !padLeft) {
|
||||
char padChar = padZero ? '0' : ' ';
|
||||
out_send_repeat(o, padChar, width - slen);
|
||||
}
|
||||
|
||||
out_send(o, str, slen);
|
||||
|
||||
if (slen < width && padLeft) {
|
||||
char padChar = padZero ? '0' : ' ';
|
||||
out_send_repeat(o, padChar, width - slen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef UNIT_TESTS
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
static int gFails = 0;
|
||||
|
||||
#define MARGIN 40
|
||||
|
||||
#define UTEST_CHECK(condition,message) \
|
||||
printf("Checking %-*s: ", MARGIN, message); fflush(stdout); \
|
||||
if (!(condition)) { \
|
||||
printf("KO\n"); \
|
||||
gFails += 1; \
|
||||
} else { \
|
||||
printf("ok\n"); \
|
||||
}
|
||||
|
||||
static void
|
||||
utest_BufOut(void)
|
||||
{
|
||||
char buffer[16];
|
||||
BufOut bo[1];
|
||||
Out* out;
|
||||
int ret;
|
||||
|
||||
buffer[0] = '1';
|
||||
out = buf_out_init(bo, buffer, sizeof buffer);
|
||||
UTEST_CHECK(buffer[0] == '\0', "buf_out_init clears initial byte");
|
||||
out_send(out, "abc", 3);
|
||||
UTEST_CHECK(!memcmp(buffer, "abc", 4), "out_send() works with BufOut");
|
||||
out_send_repeat(out, 'X', 4);
|
||||
UTEST_CHECK(!memcmp(buffer, "abcXXXX", 8), "out_send_repeat() works with BufOut");
|
||||
buffer[sizeof buffer-1] = 'x';
|
||||
out_send_repeat(out, 'Y', 2*sizeof(buffer));
|
||||
UTEST_CHECK(buffer[sizeof buffer-1] == '\0', "overflows always zero-terminates");
|
||||
|
||||
out = buf_out_init(bo, buffer, sizeof buffer);
|
||||
out_send_repeat(out, 'X', 2*sizeof(buffer));
|
||||
ret = buf_out_length(bo);
|
||||
UTEST_CHECK(ret == 2*sizeof(buffer), "correct size returned on overflow");
|
||||
}
|
||||
|
||||
static void
|
||||
utest_expect(const char* result, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
BufOut bo[1];
|
||||
char buffer[256];
|
||||
Out* out = buf_out_init(bo, buffer, sizeof buffer);
|
||||
|
||||
printf("Checking %-*s: ", MARGIN, format); fflush(stdout);
|
||||
va_start(args, format);
|
||||
out_vformat(out, format, args);
|
||||
va_end(args);
|
||||
|
||||
if (strcmp(result, buffer)) {
|
||||
printf("KO. got '%s' expecting '%s'\n", buffer, result);
|
||||
gFails += 1;
|
||||
} else {
|
||||
printf("ok. got '%s'\n", result);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
utest_BufOut();
|
||||
utest_expect("", "");
|
||||
utest_expect("a", "a");
|
||||
utest_expect("01234", "01234", "");
|
||||
utest_expect("01234", "%s", "01234");
|
||||
utest_expect("aabbcc", "aa%scc", "bb");
|
||||
utest_expect("a", "%c", 'a');
|
||||
utest_expect("1234", "%d", 1234);
|
||||
utest_expect("-8123", "%d", -8123);
|
||||
utest_expect("16", "%hd", 0x7fff0010);
|
||||
utest_expect("16", "%hhd", 0x7fffff10);
|
||||
utest_expect("68719476736", "%lld", 0x1000000000);
|
||||
utest_expect("70000", "%ld", 70000);
|
||||
utest_expect("0xb0001234", "%p", (void*)0xb0001234);
|
||||
utest_expect("12ab", "%x", 0x12ab);
|
||||
utest_expect("12AB", "%X", 0x12ab);
|
||||
utest_expect("00123456", "%08x", 0x123456);
|
||||
utest_expect("01234", "0%d", 1234);
|
||||
utest_expect(" 1234", "%5d", 1234);
|
||||
utest_expect("01234", "%05d", 1234);
|
||||
utest_expect(" 1234", "%8d", 1234);
|
||||
utest_expect("1234 ", "%-8d", 1234);
|
||||
utest_expect("abcdef ", "%-11s", "abcdef");
|
||||
utest_expect("something:1234", "%s:%d", "something", 1234);
|
||||
return gFails != 0;
|
||||
}
|
||||
|
||||
#endif /* UNIT_TESTS */
|
41
other-licenses/android/linker_format.h
Normal file
41
other-licenses/android/linker_format.h
Normal file
@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (C) 2010 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
#ifndef _LINKER_FORMAT_H
|
||||
#define _LINKER_FORMAT_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/* Formatting routines for the dynamic linker's debug traces */
|
||||
/* We want to avoid dragging the whole C library fprintf() */
|
||||
/* implementation into the dynamic linker since this creates */
|
||||
/* issues (it uses malloc()/free()) and increases code size */
|
||||
|
||||
int format_buffer(char *buffer, size_t bufsize, const char *format, ...);
|
||||
|
||||
#endif /* _LINKER_FORMAT_H */
|
36
other-licenses/android/rt.c
Normal file
36
other-licenses/android/rt.c
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (C) 2008 The Android Open Source Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* 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
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "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
|
||||
* 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
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This function is an empty stub where GDB locates a breakpoint to get notified
|
||||
* about linker activity.
|
||||
*/
|
||||
void __attribute__((noinline)) rtld_db_dlactivity(void)
|
||||
{
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user