am fdbecf3b: am 63696738: am b6a97196: Merge "More cleanup."

* commit 'fdbecf3b5a16f8e35e1ad67ec9c807eb66e2ac3b':
  More cleanup.
This commit is contained in:
Elliott Hughes 2012-08-14 15:13:10 -07:00 committed by Android Git Automerger
commit 0a3f66e9a0
4 changed files with 107 additions and 147 deletions

View file

@ -82,7 +82,7 @@ void *dlsym(void *handle, const char *symbol)
pthread_mutex_lock(&dl_lock);
if(unlikely(handle == 0)) {
if(unlikely(handle == 0)) {
set_dlerror(DL_ERR_INVALID_LIBRARY_HANDLE);
goto err;
}
@ -156,12 +156,11 @@ int dladdr(const void *addr, Dl_info *info)
return ret;
}
int dlclose(void *handle)
{
int dlclose(void* handle) {
pthread_mutex_lock(&dl_lock);
(void)soinfo_unload((soinfo*)handle);
int result = soinfo_unload((soinfo*)handle);
pthread_mutex_unlock(&dl_lock);
return 0;
return result;
}
#if defined(ANDROID_ARM_LINKER)
@ -261,4 +260,3 @@ soinfo libdl_info = {
bucket: libdl_buckets,
chain: libdl_chains,
};

View file

@ -108,14 +108,39 @@ int debug_verbosity;
static int pid;
/* This boolean is set if the program being loaded is setuid */
static int program_is_setuid;
static bool program_is_setuid;
enum RelocationKind {
kRelocAbsolute = 0,
kRelocRelative,
kRelocCopy,
kRelocSymbol,
kRelocMax
};
#if STATS
struct _link_stats linker_stats;
struct linker_stats_t {
int count[kRelocMax];
};
static linker_stats_t linker_stats;
static void count_relocation(RelocationKind kind) {
++linker_stats.count[kind];
}
#else
static void count_relocation(RelocationKind) {
}
#endif
#if COUNT_PAGES
unsigned bitmask[4096];
static unsigned bitmask[4096];
#define MARK(offset) \
do { \
bitmask[((offset) >> 12) >> 3] |= (1 << (((offset) >> 12) & 7)); \
} while(0)
#else
#define MARK(x) do {} while (0)
#endif
// You shouldn't try to call memory-allocating functions in the dynamic linker.
@ -156,19 +181,15 @@ const char *linker_get_error(void)
*/
extern "C" void __attribute__((noinline)) __attribute__((visibility("default"))) rtld_db_dlactivity(void);
static struct r_debug _r_debug = {1, NULL, &rtld_db_dlactivity,
static r_debug _r_debug = {1, NULL, &rtld_db_dlactivity,
RT_CONSISTENT, 0};
static struct link_map *r_debug_tail = 0;
static link_map* r_debug_tail = 0;
static pthread_mutex_t _r_debug_lock = PTHREAD_MUTEX_INITIALIZER;
static void insert_soinfo_into_debug_map(soinfo * info)
{
struct link_map * map;
/* Copy the necessary fields into the debug structure.
*/
map = &(info->linkmap);
static void insert_soinfo_into_debug_map(soinfo * info) {
// Copy the necessary fields into the debug structure.
link_map* map = &(info->linkmap);
map->l_addr = info->base;
map->l_name = (char*) info->name;
map->l_ld = (uintptr_t)info->dynamic;
@ -190,19 +211,22 @@ static void insert_soinfo_into_debug_map(soinfo * info)
r_debug_tail = map;
}
static void remove_soinfo_from_debug_map(soinfo * info)
{
struct link_map * map = &(info->linkmap);
static void remove_soinfo_from_debug_map(soinfo* info) {
link_map* map = &(info->linkmap);
if (r_debug_tail == map)
if (r_debug_tail == map) {
r_debug_tail = map->l_prev;
}
if (map->l_prev) map->l_prev->l_next = map->l_next;
if (map->l_next) map->l_next->l_prev = map->l_prev;
if (map->l_prev) {
map->l_prev->l_next = map->l_next;
}
if (map->l_next) {
map->l_next->l_prev = map->l_prev;
}
}
void notify_gdb_of_load(soinfo * info)
{
static void notify_gdb_of_load(soinfo* info) {
if (info->flags & FLAG_EXE) {
// GDB already knows about the main executable
return;
@ -221,8 +245,7 @@ void notify_gdb_of_load(soinfo * info)
pthread_mutex_unlock(&_r_debug_lock);
}
void notify_gdb_of_unload(soinfo * info)
{
static void notify_gdb_of_unload(soinfo* info) {
if (info->flags & FLAG_EXE) {
// GDB already knows about the main executable
return;
@ -313,16 +336,6 @@ static void soinfo_free(soinfo* si)
freelist = si;
}
const char *addr_to_name(unsigned addr)
{
for (soinfo* si = solist; si != 0; si = si->next) {
if ((addr >= si->base) && (addr < (si->base + si->size))) {
return si->name;
}
}
return "";
}
#ifdef ANDROID_ARM_LINKER
/* For a given PC, find the .so that it belongs to.
@ -354,21 +367,20 @@ _Unwind_Ptr dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount)
/* Here, we only have to provide a callback to iterate across all the
* loaded libraries. gcc_eh does the rest. */
int
dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data),
dl_iterate_phdr(int (*cb)(dl_phdr_info *info, size_t size, void *data),
void *data)
{
soinfo *si;
struct dl_phdr_info dl_info;
int rv = 0;
for (si = solist; si != NULL; si = si->next) {
for (soinfo* si = solist; si != NULL; si = si->next) {
dl_phdr_info dl_info;
dl_info.dlpi_addr = si->linkmap.l_addr;
dl_info.dlpi_name = si->linkmap.l_name;
dl_info.dlpi_phdr = si->phdr;
dl_info.dlpi_phnum = si->phnum;
rv = cb(&dl_info, sizeof (struct dl_phdr_info), data);
if (rv != 0)
rv = cb(&dl_info, sizeof(dl_phdr_info), data);
if (rv != 0) {
break;
}
}
return rv;
}
@ -434,7 +446,7 @@ soinfo_do_lookup(soinfo *si, const char *name, Elf32_Addr *offset,
* reason.
*
* Notes on weak symbols:
* The ELF specs are ambigious about treatment of weak definitions in
* The ELF specs are ambiguous about treatment of weak definitions in
* dynamic linking. Some systems return the first definition found
* and some the first non-weak definition. This is system dependent.
* Here we return the first definition found for simplicity. */
@ -581,17 +593,13 @@ static const char * const sopaths[] = {
0
};
static int _open_lib(const char *name)
{
int fd;
struct stat filestat;
if ((stat(name, &filestat) >= 0) && S_ISREG(filestat.st_mode)) {
if ((fd = TEMP_FAILURE_RETRY(open(name, O_RDONLY))) >= 0)
return fd;
static int _open_lib(const char* name) {
// TODO: why not just call open?
struct stat sb;
if (stat(name, &sb) == -1 || !S_ISREG(sb.st_mode)) {
return -1;
}
return -1;
return TEMP_FAILURE_RETRY(open(name, O_RDONLY));
}
static int open_library(const char *name)
@ -640,13 +648,13 @@ static bool is_prelinked(int fd, const char* name)
char tag[4]; // "PRE ".
};
off_t sz = lseek(fd, -sizeof(struct prelink_info_t), SEEK_END);
off_t sz = lseek(fd, -sizeof(prelink_info_t), SEEK_END);
if (sz < 0) {
DL_ERR("lseek failed: %s", strerror(errno));
return true;
}
struct prelink_info_t info;
prelink_info_t info;
int rc = TEMP_FAILURE_RETRY(read(fd, &info, sizeof(info)));
if (rc != sizeof(info)) {
DL_ERR("could not read prelink_info_t structure for \"%s\":", name, strerror(errno));
@ -834,9 +842,6 @@ init_library(soinfo *si)
pid, si->base, si->size, si->name);
if(soinfo_link_image(si)) {
/* We failed to link. However, we can only restore libbase
** if no additional libraries have moved it since we updated it.
*/
munmap((void *)si->base, si->size);
return NULL;
}
@ -893,29 +898,25 @@ soinfo *find_library(const char *name)
return init_library(si);
}
/* TODO:
* find a way to decrement libbase
*/
static void call_destructors(soinfo *si);
unsigned soinfo_unload(soinfo *si)
{
unsigned *d;
int soinfo_unload(soinfo* si) {
if (si->refcount == 1) {
TRACE("%5d unloading '%s'\n", pid, si->name);
call_destructors(si);
for(d = si->dynamic; *d; d += 2) {
for (unsigned* d = si->dynamic; *d; d += 2) {
if(d[0] == DT_NEEDED){
soinfo *lsi = find_loaded_library(si->strtab + d[1]);
if (lsi) {
TRACE("%5d %s needs to unload %s\n", pid,
si->name, lsi->name);
soinfo_unload(lsi);
}
else
} else {
// TODO: should we return -1 in this case?
DL_ERR("\"%s\": could not unload dependent library",
si->name);
}
}
}
@ -923,13 +924,12 @@ unsigned soinfo_unload(soinfo *si)
notify_gdb_of_unload(si);
soinfo_free(si);
si->refcount = 0;
}
else {
} else {
si->refcount--;
PRINT("%5d not unloading '%s', decrementing refcount to %d\n",
pid, si->name, si->refcount);
}
return si->refcount;
return 0;
}
/* TODO: don't use unsigned for addrs below. It works, but is not
@ -978,7 +978,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
During linking, the value of an undefined weak reference is:
- Zero if the relocation type is absolute
- The address of the place if the relocation is pc-relative
- The address of nominial base address if the relocation
- The address of nominal base address if the relocation
type is base-relative.
*/
@ -1027,7 +1027,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
#endif
sym_addr = (unsigned)(s->st_value + offset);
}
COUNT_RELOC(RELOC_SYMBOL);
count_relocation(kRelocSymbol);
} else {
s = NULL;
}
@ -1038,28 +1038,28 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
switch(type){
#if defined(ANDROID_ARM_LINKER)
case R_ARM_JUMP_SLOT:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
*((unsigned*)reloc) = sym_addr;
break;
case R_ARM_GLOB_DAT:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
*((unsigned*)reloc) = sym_addr;
break;
case R_ARM_ABS32:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO ABS %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
*((unsigned*)reloc) += sym_addr;
break;
case R_ARM_REL32:
COUNT_RELOC(RELOC_RELATIVE);
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x - %08x %s\n", pid,
reloc, sym_addr, rel->r_offset, sym_name);
@ -1067,14 +1067,14 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
break;
#elif defined(ANDROID_X86_LINKER)
case R_386_JMP_SLOT:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
*((unsigned*)reloc) = sym_addr;
break;
case R_386_GLOB_DAT:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO GLOB_DAT %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
@ -1082,14 +1082,14 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
break;
#elif defined(ANDROID_MIPS_LINKER)
case R_MIPS_JUMP_SLOT:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO JMP_SLOT %08x <- %08x %s\n", pid,
reloc, sym_addr, sym_name);
*((unsigned*)reloc) = sym_addr;
break;
case R_MIPS_REL32:
COUNT_RELOC(RELOC_ABSOLUTE);
count_relocation(kRelocAbsolute);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO REL32 %08x <- %08x %s\n", pid,
reloc, sym_addr, (sym_name) ? sym_name : "*SECTIONHDR*");
@ -1106,7 +1106,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
#elif defined(ANDROID_X86_LINKER)
case R_386_RELATIVE:
#endif /* ANDROID_*_LINKER */
COUNT_RELOC(RELOC_RELATIVE);
count_relocation(kRelocRelative);
MARK(rel->r_offset);
if (sym) {
DL_ERR("odd RELATIVE form...", pid);
@ -1119,7 +1119,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
#if defined(ANDROID_X86_LINKER)
case R_386_32:
COUNT_RELOC(RELOC_RELATIVE);
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO R_386_32 %08x <- +%08x %s\n", pid,
@ -1128,7 +1128,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
break;
case R_386_PC32:
COUNT_RELOC(RELOC_RELATIVE);
count_relocation(kRelocRelative);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO R_386_PC32 %08x <- "
"+%08x (%08x - %08x) %s\n", pid, reloc,
@ -1139,7 +1139,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
#ifdef ANDROID_ARM_LINKER
case R_ARM_COPY:
COUNT_RELOC(RELOC_COPY);
count_relocation(kRelocCopy);
MARK(rel->r_offset);
TRACE_TYPE(RELO, "%5d RELO %08x <- %d @ %08x %s\n", pid,
reloc, s->st_size, sym_addr, sym_name);
@ -1157,8 +1157,7 @@ static int soinfo_relocate(soinfo *si, Elf32_Rel *rel, unsigned count,
}
#ifdef ANDROID_MIPS_LINKER
int mips_relocate_got(struct soinfo *si, soinfo *needed[])
{
static int mips_relocate_got(soinfo* si, soinfo* needed[]) {
unsigned *got;
unsigned local_gotno, gotsym, symtabno;
Elf32_Sym *symtab, *sym;
@ -1173,7 +1172,7 @@ int mips_relocate_got(struct soinfo *si, soinfo *needed[])
/*
* got[0] is address of lazy resolver function
* got[1] may be used for a GNU extension
* set it to a recognisable address in case someone calls it
* set it to a recognizable address in case someone calls it
* (should be _rtld_bind_start)
* FIXME: maybe this should be in a separate routine
*/
@ -1481,7 +1480,7 @@ static int soinfo_link_image(soinfo *si)
break;
case DT_DEBUG:
#if !defined(ANDROID_MIPS_LINKER)
// Set the DT_DEBUG entry to the addres of _r_debug for GDB
// Set the DT_DEBUG entry to the address of _r_debug for GDB
*d = (int) &_r_debug;
#endif
break;
@ -1532,9 +1531,9 @@ static int soinfo_link_image(soinfo *si)
case DT_RELENT:
break;
case DT_MIPS_RLD_MAP:
/* Set the DT_MIPS_RLD_MAP entry to the addres of _r_debug for GDB */
// Set the DT_MIPS_RLD_MAP entry to the address of _r_debug for GDB.
{
struct r_debug **dp = (struct r_debug **)*d;
r_debug** dp = (r_debug**) *d;
*dp = &_r_debug;
}
break;
@ -1736,7 +1735,6 @@ static unsigned __linker_init_post_relocation(unsigned **elfdata, unsigned linke
unsigned *v;
soinfo *si;
int i;
struct link_map * map;
const char *ldpath_env = NULL;
const char *ldpreload_env = NULL;
@ -1775,8 +1773,9 @@ static unsigned __linker_init_post_relocation(unsigned **elfdata, unsigned linke
sanitize:
/* Sanitize environment if we're loading a setuid program */
if (program_is_setuid)
if (program_is_setuid) {
linker_env_secure();
}
debugger_init();
@ -1807,7 +1806,7 @@ sanitize:
/* bootstrap the link map, the main exe always needs to be first */
si->flags |= FLAG_EXE;
map = &(si->linkmap);
link_map* map = &(si->linkmap);
map->l_addr = 0;
map->l_name = argv[0];
@ -1910,10 +1909,10 @@ sanitize:
#endif
#if STATS
PRINT("RELO STATS: %s: %d abs, %d rel, %d copy, %d symbol\n", argv[0],
linker_stats.reloc[RELOC_ABSOLUTE],
linker_stats.reloc[RELOC_RELATIVE],
linker_stats.reloc[RELOC_COPY],
linker_stats.reloc[RELOC_SYMBOL]);
linker_stats.count[kRelocAbsolute],
linker_stats.count[kRelocRelative],
linker_stats.count[kRelocCopy],
linker_stats.count[kRelocSymbol]);
#endif
#if COUNT_PAGES
{

View file

@ -60,7 +60,6 @@ extern "C" {
#define PAGE_END(x) PAGE_START((x) + (PAGE_SIZE-1))
void debugger_init();
const char *addr_to_name(unsigned addr);
/* magic shared structures that GDB knows about */
@ -237,7 +236,7 @@ Elf32_Sym *lookup(const char *name, soinfo **found, soinfo *start);
soinfo *find_containing_library(const void *addr);
const char *linker_get_error(void);
unsigned soinfo_unload(soinfo *si);
int soinfo_unload(soinfo* si);
Elf32_Sym *soinfo_find_symbol(soinfo* si, const void *addr);
Elf32_Sym *soinfo_lookup(soinfo *si, const char *name);
void soinfo_call_constructors(soinfo *si);

View file

@ -55,10 +55,6 @@
/*********************************************************************/
#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().
@ -68,13 +64,13 @@
extern int debug_verbosity;
#if LINKER_DEBUG_TO_LOG
extern int format_log(int, const char *, const char *, ...);
#define _PRINTVF(v,f,x...) \
#define _PRINTVF(v,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...) \
#define _PRINTVF(v,x...) \
do { \
if (debug_verbosity > (v)) format_fd(1, x); \
} while (0)
@ -83,17 +79,17 @@ extern int format_fd(int, const char *, ...);
#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 PRINT(x...) _PRINTVF(-1, x)
#define INFO(x...) _PRINTVF(0, x)
#define TRACE(x...) _PRINTVF(1, x)
#define WARN(fmt,args...) \
_PRINTVF(-1, TRUE, "%s:%d| WARNING: " fmt, __FILE__, __LINE__, ## args)
_PRINTVF(-1, "%s:%d| WARNING: " fmt, __FILE__, __LINE__, ## args)
#define ERROR(fmt,args...) \
_PRINTVF(-1, TRUE, "%s:%d| ERROR: " fmt, __FILE__, __LINE__, ## args)
_PRINTVF(-1, "%s:%d| ERROR: " fmt, __FILE__, __LINE__, ## args)
#if TRACE_DEBUG
#define DEBUG(x...) _PRINTVF(2, TRUE, "DEBUG: " x)
#define DEBUG(x...) _PRINTVF(2, "DEBUG: " x)
#else /* !TRACE_DEBUG */
#define DEBUG(x...) do {} while (0)
#endif /* TRACE_DEBUG */
@ -104,43 +100,11 @@ extern int format_fd(int, const char *, ...);
#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)); \