Initial Contribution
This commit is contained in:
68
linker/Android.mk
Normal file
68
linker/Android.mk
Normal file
@@ -0,0 +1,68 @@
|
||||
LOCAL_PATH:= $(call my-dir)
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_SRC_FILES:= \
|
||||
arch/$(TARGET_ARCH)/begin.S \
|
||||
linker.c \
|
||||
rt.c \
|
||||
dlfcn.c \
|
||||
debugger.c
|
||||
|
||||
LINKER_TEXT_BASE := 0xB0000100
|
||||
|
||||
# The maximum size set aside for the linker, from
|
||||
# LINKER_TEXT_BASE rounded down to a megabyte.
|
||||
LINKER_AREA_SIZE := 0x01000000
|
||||
|
||||
LOCAL_LDFLAGS := -Wl,-Ttext,$(LINKER_TEXT_BASE)
|
||||
|
||||
LOCAL_CFLAGS += -DPRELINK -DLINKER_TEXT_BASE=$(LINKER_TEXT_BASE) -DLINKER_AREA_SIZE=$(LINKER_AREA_SIZE)
|
||||
|
||||
ifeq ($(TARGET_ARCH),arm)
|
||||
LOCAL_CFLAGS += -DANDROID_ARM_LINKER
|
||||
else
|
||||
ifeq ($(TARGET_ARCH),x86)
|
||||
LOCAL_CFLAGS += -DANDROID_X86_LINKER
|
||||
else
|
||||
$(error Unsupported TARGET_ARCH $(TARGET_ARCH))
|
||||
endif
|
||||
endif
|
||||
|
||||
LOCAL_MODULE:= linker
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := libcutils libc
|
||||
|
||||
#LOCAL_FORCE_STATIC_EXECUTABLE := true # not necessary when not including BUILD_EXECUTABLE
|
||||
|
||||
#
|
||||
# include $(BUILD_EXECUTABLE)
|
||||
#
|
||||
# Instead of including $(BUILD_EXECUTABLE), we execute the steps to create an executable by
|
||||
# hand, as we want to insert an extra step that is not supported by the build system, and
|
||||
# is probably specific the linker only, so there's no need to modify the build system for
|
||||
# the purpose.
|
||||
|
||||
LOCAL_MODULE_CLASS := EXECUTABLES
|
||||
LOCAL_MODULE_SUFFIX := $(TARGET_EXECUTABLE_SUFFIX)
|
||||
|
||||
# Executables are not prelinked.
|
||||
LOCAL_PRELINK_MODULE := false
|
||||
|
||||
include $(BUILD_SYSTEM)/dynamic_binary.mk
|
||||
|
||||
$(linked_module): $(TARGET_CRTBEGIN_STATIC_O) $(all_objects) $(all_libraries) $(TARGET_CRTEND_O)
|
||||
$(transform-o-to-static-executable)
|
||||
@echo "target PrefixSymbols: $(PRIVATE_MODULE) ($@)"
|
||||
$(hide) $(TARGET_OBJCOPY) --prefix-symbols=__dl_ $@
|
||||
|
||||
#
|
||||
# end of BUILD_EXECUTABLE hack
|
||||
#
|
||||
|
||||
# we don't want crtbegin.o (because we have begin.o), so unset it
|
||||
# just for this module
|
||||
$(LOCAL_BUILT_MODULE): TARGET_CRTBEGIN_STATIC_O :=
|
||||
# This line is not strictly necessary because the dynamic linker is built
|
||||
# as a static executable, but it won't hurt if in the future we start
|
||||
# building the linker as a dynamic one.
|
||||
$(LOCAL_BUILT_MODULE): TARGET_CRTBEGIN_DYNAMIC_O :=
|
||||
0
linker/MODULE_LICENSE_APACHE2
Normal file
0
linker/MODULE_LICENSE_APACHE2
Normal file
190
linker/NOTICE
Normal file
190
linker/NOTICE
Normal file
@@ -0,0 +1,190 @@
|
||||
|
||||
Copyright (c) 2005-2008, The Android Open Source Project
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
|
||||
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.
|
||||
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
17
linker/arch/arm/begin.S
Normal file
17
linker/arch/arm/begin.S
Normal file
@@ -0,0 +1,17 @@
|
||||
.text
|
||||
.align 4
|
||||
.type _start,#function
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
mov r0, sp
|
||||
mov r1, #0
|
||||
bl __linker_init
|
||||
|
||||
/* linker init returns the _entry address in the main image */
|
||||
mov pc, r0
|
||||
|
||||
.section .ctors, "wa"
|
||||
.globl __CTOR_LIST__
|
||||
__CTOR_LIST__:
|
||||
.long -1
|
||||
23
linker/arch/x86/begin.S
Normal file
23
linker/arch/x86/begin.S
Normal file
@@ -0,0 +1,23 @@
|
||||
.text
|
||||
.align 4
|
||||
.type _start, @function
|
||||
.globl _start
|
||||
|
||||
_start:
|
||||
/* save the elfdata ptr to %eax, AND push it onto the stack */
|
||||
mov %esp, %eax
|
||||
pushl %esp
|
||||
|
||||
pushl %eax
|
||||
call __linker_init
|
||||
|
||||
/* linker init returns (%eax) the _entry address in the main image */
|
||||
/* entry point expects sp to point to elfdata */
|
||||
popl %esp
|
||||
jmp *%eax
|
||||
|
||||
.section .ctors, "wa"
|
||||
.globl __CTOR_LIST__
|
||||
|
||||
__CTOR_LIST__:
|
||||
.long -1
|
||||
52
linker/debugger.c
Normal file
52
linker/debugger.c
Normal file
@@ -0,0 +1,52 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <signal.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "linker.h"
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <cutils/sockets.h>
|
||||
|
||||
void notify_gdb_of_libraries();
|
||||
|
||||
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
|
||||
*/
|
||||
write(s, &tid, sizeof(unsigned));
|
||||
|
||||
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);
|
||||
}
|
||||
212
linker/dlfcn.c
Normal file
212
linker/dlfcn.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* 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 "linker.h"
|
||||
|
||||
/* This file hijacks the symbols stubbed out in libdl.so. */
|
||||
|
||||
#define DL_SUCCESS 0
|
||||
#define DL_ERR_CANNOT_FIND_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 const char *dl_errors[] = {
|
||||
[DL_SUCCESS] = NULL,
|
||||
[DL_ERR_CANNOT_FIND_LIBRARY] = "Cannot find 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",
|
||||
};
|
||||
|
||||
static int dl_last_err = DL_SUCCESS;
|
||||
|
||||
#define likely(expr) __builtin_expect (expr, 1)
|
||||
#define unlikely(expr) __builtin_expect (expr, 0)
|
||||
|
||||
static pthread_mutex_t dl_lock = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
void *dlopen(const char *filename, int flag)
|
||||
{
|
||||
soinfo *ret;
|
||||
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
ret = find_library(filename);
|
||||
if (unlikely(ret == NULL)) {
|
||||
dl_last_err = DL_ERR_CANNOT_FIND_LIBRARY;
|
||||
} else {
|
||||
ret->refcount++;
|
||||
}
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const char *dlerror(void)
|
||||
{
|
||||
const char *err = dl_errors[dl_last_err];
|
||||
dl_last_err = DL_SUCCESS;
|
||||
return err;
|
||||
}
|
||||
|
||||
void *dlsym(void *handle, const char *symbol)
|
||||
{
|
||||
unsigned base;
|
||||
Elf32_Sym *sym;
|
||||
unsigned bind;
|
||||
|
||||
pthread_mutex_lock(&dl_lock);
|
||||
|
||||
if(unlikely(handle == 0)) {
|
||||
dl_last_err = DL_ERR_INVALID_LIBRARY_HANDLE;
|
||||
goto err;
|
||||
}
|
||||
if(unlikely(symbol == 0)) {
|
||||
dl_last_err = DL_ERR_BAD_SYMBOL_NAME;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if(handle == RTLD_DEFAULT) {
|
||||
sym = lookup(symbol, &base);
|
||||
} else if(handle == RTLD_NEXT) {
|
||||
sym = lookup(symbol, &base);
|
||||
} else {
|
||||
sym = lookup_in_library((soinfo*) handle, symbol);
|
||||
base = ((soinfo*) handle)->base;
|
||||
}
|
||||
|
||||
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 + base;
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return (void*)ret;
|
||||
}
|
||||
|
||||
dl_last_err = DL_ERR_SYMBOL_NOT_GLOBAL;
|
||||
}
|
||||
else dl_last_err = DL_ERR_SYMBOL_NOT_FOUND;
|
||||
|
||||
err:
|
||||
pthread_mutex_unlock(&dl_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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 233333333334444444444
|
||||
// 0123456 78901234 567890 12345678 901234567890123456789
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\0dl_unwind_find_exidx\0"
|
||||
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
// 0000000 00011111 111112 22222222 2333333333344444
|
||||
// 0123456 78901234 567890 12345678 9012345678901234
|
||||
#define ANDROID_LIBDL_STRTAB \
|
||||
"dlopen\0dlclose\0dlsym\0dlerror\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,
|
||||
},
|
||||
#ifdef ANDROID_ARM_LINKER
|
||||
{ st_name: 29,
|
||||
st_value: (Elf32_Addr) &dl_unwind_find_exidx,
|
||||
st_info: STB_GLOBAL << 4,
|
||||
st_shndx: 1,
|
||||
},
|
||||
#elif defined(ANDROID_X86_LINKER)
|
||||
{ st_name: 29,
|
||||
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[6] = { 0, 2, 3, 4, 5, 0 };
|
||||
|
||||
soinfo libdl_info = {
|
||||
name: "libdl.so",
|
||||
flags: FLAG_LINKED,
|
||||
|
||||
strtab: ANDROID_LIBDL_STRTAB,
|
||||
symtab: libdl_symtab,
|
||||
|
||||
nbucket: 1,
|
||||
nchain: 6,
|
||||
bucket: libdl_buckets,
|
||||
chain: libdl_chains,
|
||||
};
|
||||
|
||||
1702
linker/linker.c
Normal file
1702
linker/linker.c
Normal file
File diff suppressed because it is too large
Load Diff
185
linker/linker.h
Normal file
185
linker/linker.h
Normal file
@@ -0,0 +1,185 @@
|
||||
#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;
|
||||
|
||||
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;
|
||||
|
||||
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 */
|
||||
#define LIBBASE 0x80000000
|
||||
#define LIBLAST 0x90000000
|
||||
#define LIBINC 0x00100000
|
||||
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
/* in theory we only need the above relative relocations,
|
||||
but in practice the following one turns up from time
|
||||
to time. fushigi na.
|
||||
*/
|
||||
#define R_ARM_ABS32 2
|
||||
|
||||
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, unsigned *base);
|
||||
|
||||
#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)
|
||||
int dl_iterate_phdr(int (*cb)(struct dl_phdr_info *, size_t, void *), void *);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
111
linker/linker_debug.h
Normal file
111
linker/linker_debug.h
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef _LINKER_DEBUG_H_
|
||||
#define _LINKER_DEBUG_H_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* WARNING: For linker debugging only.. Be careful not to leave any of
|
||||
* this on when submitting back to repository */
|
||||
#define LINKER_DEBUG 0
|
||||
#define TRACE_DEBUG 0
|
||||
#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
|
||||
extern int debug_verbosity;
|
||||
#warning "*** LINKER IS USING printf(); DO NOT CHECK THIS IN ***"
|
||||
#define _PRINTVF(v,f,x...) do { \
|
||||
(debug_verbosity > (v)) && (printf(x), ((f) && fflush(stdout))); \
|
||||
} while (0)
|
||||
#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_ */
|
||||
8
linker/rt.c
Normal file
8
linker/rt.c
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* This function is an empty stub where GDB locates a breakpoint to get notified
|
||||
* about linker activity.
|
||||
*/
|
||||
void __attribute__((noinline)) rtld_db_dlactivity(void)
|
||||
{
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user