Bug 747033 - Implement dl_iterate_phdr in the custom linker. r=froydnj

--HG--
rename : mozglue/linker/CustomElf.h => mozglue/linker/Elfxx.h
This commit is contained in:
Mike Hommey 2012-04-25 09:05:02 +02:00
parent 7cc9baa6ef
commit 91480beb18
5 changed files with 315 additions and 226 deletions

View File

@ -291,6 +291,8 @@ CustomElf::GetSymbolPtrInDeps(const char *symbol) const
return FunctionPtr(__wrap_dlsym);
if (strcmp(symbol + 2, "addr") == 0)
return FunctionPtr(__wrap_dladdr);
if (strcmp(symbol + 2, "_iterate_phdr") == 0)
return FunctionPtr(__wrap_dl_iterate_phdr);
} else if (symbol[0] == '_' && symbol[1] == '_') {
/* Resolve a few C++ ABI specific functions to point to ours */
#ifdef __ARM_EABI__

View File

@ -5,234 +5,9 @@
#ifndef CustomElf_h
#define CustomElf_h
/**
* Android system headers have two different elf.h file. The one under linux/
* is the most complete.
*/
#ifdef ANDROID
#include <linux/elf.h>
#else
#include <elf.h>
#endif
#include <endian.h>
#include "ElfLoader.h"
#include "Logging.h"
/**
* Generic ELF macros for the target system
*/
#ifdef HAVE_64BIT_OS
#define Elf_(type) Elf64_ ## type
#define ELFCLASS ELFCLASS64
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_SYM ELF64_R_SYM
#ifndef ELF_ST_BIND
#define ELF_ST_BIND ELF64_ST_BIND
#endif
#define PRIxAddr "lx"
#else
#define Elf_(type) Elf32_ ## type
#define ELFCLASS ELFCLASS32
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_SYM ELF32_R_SYM
#ifndef ELF_ST_BIND
#define ELF_ST_BIND ELF32_ST_BIND
#endif
#define PRIxAddr "x"
#endif
#ifndef __BYTE_ORDER
#error Cannot find endianness
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ELFDATA ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ELFDATA ELFDATA2MSB
#endif
#ifdef __linux__
#define ELFOSABI ELFOSABI_LINUX
#ifdef EI_ABIVERSION
#define ELFABIVERSION 0
#endif
#else
#error Unknown ELF OSABI
#endif
#if defined(__i386__)
#define ELFMACHINE EM_386
// Doing this way probably doesn't scale to other architectures
#define R_ABS R_386_32
#define R_GLOB_DAT R_386_GLOB_DAT
#define R_JMP_SLOT R_386_JMP_SLOT
#define R_RELATIVE R_386_RELATIVE
#define RELOC(n) DT_REL ## n
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
#define STR_RELOC(n) "DT_REL" # n
#define Reloc Rel
#elif defined(__x86_64__)
#define ELFMACHINE EM_X86_64
#define R_ABS R_X86_64_64
#define R_GLOB_DAT R_X86_64_GLOB_DAT
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
#define R_RELATIVE R_X86_64_RELATIVE
#define RELOC(n) DT_RELA ## n
#define UNSUPPORTED_RELOC(n) DT_REL ## n
#define STR_RELOC(n) "DT_RELA" # n
#define Reloc Rela
#elif defined(__arm__)
#define ELFMACHINE EM_ARM
#ifndef R_ARM_ABS32
#define R_ARM_ABS32 2
#endif
#ifndef R_ARM_GLOB_DAT
#define R_ARM_GLOB_DAT 21
#endif
#ifndef R_ARM_JUMP_SLOT
#define R_ARM_JUMP_SLOT 22
#endif
#ifndef R_ARM_RELATIVE
#define R_ARM_RELATIVE 23
#endif
#define R_ABS R_ARM_ABS32
#define R_GLOB_DAT R_ARM_GLOB_DAT
#define R_JMP_SLOT R_ARM_JUMP_SLOT
#define R_RELATIVE R_ARM_RELATIVE
#define RELOC(n) DT_REL ## n
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
#define STR_RELOC(n) "DT_REL" # n
#define Reloc Rel
#else
#error Unknown ELF machine type
#endif
/**
* Android system headers don't have all definitions
*/
#ifndef STN_UNDEF
#define STN_UNDEF 0
#endif
#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_RELACOUNT
#define DT_RELACOUNT 0x6ffffff9
#endif
#ifndef DT_RELCOUNT
#define DT_RELCOUNT 0x6ffffffa
#endif
#ifndef DT_VERSYM
#define DT_VERSYM 0x6ffffff0
#endif
#ifndef DT_VERDEF
#define DT_VERDEF 0x6ffffffc
#endif
#ifndef DT_VERDEFNUM
#define DT_VERDEFNUM 0x6ffffffd
#endif
#ifndef DT_VERNEED
#define DT_VERNEED 0x6ffffffe
#endif
#ifndef DT_VERNEEDNUM
#define DT_VERNEEDNUM 0x6fffffff
#endif
#ifndef DT_FLAGS
#define DT_FLAGS 30
#endif
#ifndef DF_SYMBOLIC
#define DF_SYMBOLIC 0x00000002
#endif
#ifndef DF_TEXTREL
#define DF_TEXTREL 0x00000004
#endif
namespace Elf {
/**
* Define a few basic Elf Types
*/
typedef Elf_(Phdr) Phdr;
typedef Elf_(Dyn) Dyn;
typedef Elf_(Sym) Sym;
typedef Elf_(Addr) Addr;
typedef Elf_(Word) Word;
/**
* Helper class around the standard Elf header struct
*/
struct Ehdr: public Elf_(Ehdr)
{
/**
* Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
* checking that this is indeed an Elf header and that the Elf type
* corresponds to that of the system
*/
static const Ehdr *validate(const void *buf);
};
/**
* Elf String table
*/
class Strtab: public UnsizedArray<const char>
{
public:
/**
* Returns the string at the given index in the table
*/
const char *GetStringAt(off_t index) const
{
return &UnsizedArray<const char>::operator[](index);
}
};
/**
* Helper class around Elf relocation.
*/
struct Rel: public Elf_(Rel)
{
/**
* Returns the addend for the relocation, which is the value stored
* at r_offset.
*/
Addr GetAddend(void *base) const
{
return *(reinterpret_cast<const Addr *>(
reinterpret_cast<const char *>(base) + r_offset));
}
};
/**
* Helper class around Elf relocation with addend.
*/
struct Rela: public Elf_(Rela)
{
/**
* Returns the addend for the relocation.
*/
Addr GetAddend(void *base) const
{
return r_addend;
}
};
} /* namespace Elf */
#include "Elfxx.h"
class Mappable;

View File

@ -92,6 +92,26 @@ __wrap_dladdr(void *addr, Dl_info *info)
return 1;
}
int
__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data)
{
if (ElfLoader::Singleton.dbg == NULL)
return -1;
for (ElfLoader::r_debug::iterator it = ElfLoader::Singleton.dbg->begin();
it < ElfLoader::Singleton.dbg->end(); ++it) {
dl_phdr_info info;
info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr);
info.dlpi_name = it->l_name;
info.dlpi_phdr = NULL;
info.dlpi_phnum = 0;
int ret = callback(&info, sizeof(dl_phdr_info), data);
if (ret)
return ret;
}
return 0;
}
namespace {
/**

View File

@ -10,6 +10,7 @@
#include <signal.h>
#include "mozilla/RefPtr.h"
#include "Zip.h"
#include "Elfxx.h"
/**
* dlfcn.h replacement functions
@ -33,6 +34,16 @@ extern "C" {
sighandler_t __wrap_signal(int signum, sighandler_t handler);
int __wrap_sigaction(int signum, const struct sigaction *act,
struct sigaction *oldact);
struct dl_phdr_info {
Elf::Addr dlpi_addr;
const char *dlpi_name;
const Elf::Phdr *dlpi_phdr;
Elf::Half dlpi_phnum;
};
typedef int (*dl_phdr_cb)(struct dl_phdr_info *, size_t, void *);
int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
}
/**
@ -356,6 +367,8 @@ private:
/* Keep track of Zips used for library loading */
ZipCollection zips;
/* Forward declaration, see further below */
class r_debug;
public:
/* Loaded object descriptor for the debugger interface below*/
struct link_map {
@ -365,6 +378,9 @@ public:
const char *l_name;
/* Address of the PT_DYNAMIC segment. */
const void *l_ld;
private:
friend class ElfLoader::r_debug;
/* Double linked list of loaded objects. */
link_map *l_next, *l_prev;
};
@ -381,6 +397,45 @@ private:
/* Make the debugger aware of the unloading of an object */
void Remove(link_map *map);
/* Iterates over all link_maps */
class iterator
{
public:
const link_map *operator ->() const
{
return item;
}
const link_map &operator ++()
{
item = item->l_next;
return *item;
}
bool operator<(const iterator &other) const
{
if (other.item == NULL)
return item ? true : false;
MOZ_NOT_REACHED("r_debug::iterator::operator< called with something else than r_debug::end()");
}
protected:
friend class r_debug;
iterator(const link_map *item): item(item) { }
private:
const link_map *item;
};
iterator begin() const
{
return iterator(r_map);
}
iterator end() const
{
return iterator(NULL);
}
private:
/* Version number of the protocol. */
int r_version;
@ -401,6 +456,7 @@ private:
RT_DELETE /* Beginning to remove an object */
} r_state;
};
friend int __wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data);
r_debug *dbg;
/**

236
mozglue/linker/Elfxx.h Normal file
View File

@ -0,0 +1,236 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef Elfxx_h
#define Elfxx_h
/**
* Android system headers have two different elf.h file. The one under linux/
* is the most complete.
*/
#ifdef ANDROID
#include <linux/elf.h>
#else
#include <elf.h>
#endif
#include <endian.h>
/**
* Generic ELF macros for the target system
*/
#ifdef HAVE_64BIT_OS
#define Elf_(type) Elf64_ ## type
#define ELFCLASS ELFCLASS64
#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_SYM ELF64_R_SYM
#ifndef ELF_ST_BIND
#define ELF_ST_BIND ELF64_ST_BIND
#endif
#define PRIxAddr "lx"
#else
#define Elf_(type) Elf32_ ## type
#define ELFCLASS ELFCLASS32
#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_SYM ELF32_R_SYM
#ifndef ELF_ST_BIND
#define ELF_ST_BIND ELF32_ST_BIND
#endif
#define PRIxAddr "x"
#endif
#ifndef __BYTE_ORDER
#error Cannot find endianness
#endif
#if __BYTE_ORDER == __LITTLE_ENDIAN
#define ELFDATA ELFDATA2LSB
#elif __BYTE_ORDER == __BIG_ENDIAN
#define ELFDATA ELFDATA2MSB
#endif
#ifdef __linux__
#define ELFOSABI ELFOSABI_LINUX
#ifdef EI_ABIVERSION
#define ELFABIVERSION 0
#endif
#else
#error Unknown ELF OSABI
#endif
#if defined(__i386__)
#define ELFMACHINE EM_386
// Doing this way probably doesn't scale to other architectures
#define R_ABS R_386_32
#define R_GLOB_DAT R_386_GLOB_DAT
#define R_JMP_SLOT R_386_JMP_SLOT
#define R_RELATIVE R_386_RELATIVE
#define RELOC(n) DT_REL ## n
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
#define STR_RELOC(n) "DT_REL" # n
#define Reloc Rel
#elif defined(__x86_64__)
#define ELFMACHINE EM_X86_64
#define R_ABS R_X86_64_64
#define R_GLOB_DAT R_X86_64_GLOB_DAT
#define R_JMP_SLOT R_X86_64_JUMP_SLOT
#define R_RELATIVE R_X86_64_RELATIVE
#define RELOC(n) DT_RELA ## n
#define UNSUPPORTED_RELOC(n) DT_REL ## n
#define STR_RELOC(n) "DT_RELA" # n
#define Reloc Rela
#elif defined(__arm__)
#define ELFMACHINE EM_ARM
#ifndef R_ARM_ABS32
#define R_ARM_ABS32 2
#endif
#ifndef R_ARM_GLOB_DAT
#define R_ARM_GLOB_DAT 21
#endif
#ifndef R_ARM_JUMP_SLOT
#define R_ARM_JUMP_SLOT 22
#endif
#ifndef R_ARM_RELATIVE
#define R_ARM_RELATIVE 23
#endif
#define R_ABS R_ARM_ABS32
#define R_GLOB_DAT R_ARM_GLOB_DAT
#define R_JMP_SLOT R_ARM_JUMP_SLOT
#define R_RELATIVE R_ARM_RELATIVE
#define RELOC(n) DT_REL ## n
#define UNSUPPORTED_RELOC(n) DT_RELA ## n
#define STR_RELOC(n) "DT_REL" # n
#define Reloc Rel
#else
#error Unknown ELF machine type
#endif
/**
* Android system headers don't have all definitions
*/
#ifndef STN_UNDEF
#define STN_UNDEF 0
#endif
#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_RELACOUNT
#define DT_RELACOUNT 0x6ffffff9
#endif
#ifndef DT_RELCOUNT
#define DT_RELCOUNT 0x6ffffffa
#endif
#ifndef DT_VERSYM
#define DT_VERSYM 0x6ffffff0
#endif
#ifndef DT_VERDEF
#define DT_VERDEF 0x6ffffffc
#endif
#ifndef DT_VERDEFNUM
#define DT_VERDEFNUM 0x6ffffffd
#endif
#ifndef DT_VERNEED
#define DT_VERNEED 0x6ffffffe
#endif
#ifndef DT_VERNEEDNUM
#define DT_VERNEEDNUM 0x6fffffff
#endif
#ifndef DT_FLAGS
#define DT_FLAGS 30
#endif
#ifndef DF_SYMBOLIC
#define DF_SYMBOLIC 0x00000002
#endif
#ifndef DF_TEXTREL
#define DF_TEXTREL 0x00000004
#endif
namespace Elf {
/**
* Define a few basic Elf Types
*/
typedef Elf_(Phdr) Phdr;
typedef Elf_(Dyn) Dyn;
typedef Elf_(Sym) Sym;
typedef Elf_(Addr) Addr;
typedef Elf_(Word) Word;
typedef Elf_(Half) Half;
/**
* Helper class around the standard Elf header struct
*/
struct Ehdr: public Elf_(Ehdr)
{
/**
* Equivalent to reinterpret_cast<const Ehdr *>(buf), but additionally
* checking that this is indeed an Elf header and that the Elf type
* corresponds to that of the system
*/
static const Ehdr *validate(const void *buf);
};
/**
* Elf String table
*/
class Strtab: public UnsizedArray<const char>
{
public:
/**
* Returns the string at the given index in the table
*/
const char *GetStringAt(off_t index) const
{
return &UnsizedArray<const char>::operator[](index);
}
};
/**
* Helper class around Elf relocation.
*/
struct Rel: public Elf_(Rel)
{
/**
* Returns the addend for the relocation, which is the value stored
* at r_offset.
*/
Addr GetAddend(void *base) const
{
return *(reinterpret_cast<const Addr *>(
reinterpret_cast<const char *>(base) + r_offset));
}
};
/**
* Helper class around Elf relocation with addend.
*/
struct Rela: public Elf_(Rela)
{
/**
* Returns the addend for the relocation.
*/
Addr GetAddend(void *base) const
{
return r_addend;
}
};
} /* namespace Elf */
#endif /* Elfxx_h */