/**
* \brief Generic linker definitions
* \author Sebastian Sumpf
* \date 2014-10-24
*/
/*
* Copyright (C) 2014 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU General Public License version 2.
*/
#ifndef _INCLUDE__LINKER_H_
#define _INCLUDE__LINKER_H_
#include
#include
#include
#include
#include
#include
#include
/**
* Debugging
*/
constexpr bool verbose_lookup = false;
constexpr bool verbose_link_map = false;
constexpr bool verbose_relocation = false;
constexpr bool verbose_exception = false;
constexpr bool verbose_shared = false;
constexpr bool verbose_loading = false;
/**
* Forward declartions and helpers
*/
namespace Linker
{
class Object;
struct Phdr;
struct File;
struct Root_object;
struct Dag;
struct Elf_object;
/**
* Find symbol via index
*
* \param sym_index Symbol index within object
* \param dag Directed acyclic graph of object
* \param base Returned address of symbol
* \param undef True, return undefined symbol; False return defined
* symbols only
* \param other True, search for symbol in other objects; False, search
* for symbol in given object as well.
*
* \throw Not_found Symbol not found
*
* \return Symbol information
*/
Elf::Sym const *locate_symbol(unsigned sym_index, Dag const *, Elf::Addr *base,
bool undef = false, bool other = false);
/**
* Find symbol via name
*
* \param name Symbol name
* \param dag Directed acyclic graph of object
* \param base Returned address of symbol
* \param undef True, return undefined symbol; False return defined
* symbols only
* \param other True, search for symbol in other objects; False, search
* for symbol in given object as well.
*
* \throw Not_found Symbol not found
*
* \return Symbol information
*/
Elf::Sym const *search_symbol(char const *name, Dag const *dag, Elf::Addr *base,
bool undef = false, bool other = false);
/**
* Load object
*
* \param path Path of object
* \param load True, load binary; False, load ELF header only
*
* \throw Invalid_file Segment is neither read-only/executable or read/write
* \throw Region_conflict There is already something at the given address
* \throw Incompatible Not an ELF
*
* \return File descriptor
*/
File const *load(char const *path, bool load = true);
/**
* Exceptions
*/
class Incompatible : Genode::Exception { };
class Invalid_file : Genode::Exception { };
class Not_found : Genode::Exception { };
/**
* Page handling
*/
template
static inline T trunc_page(T addr) {
return addr & Genode::_align_mask((T)12); }
template
static inline T round_page(T addr) {
return Genode::align_addr(addr, (T)12); }
/**
* Extract file name from path
*/
inline char const *file(char const *path)
{
/* strip directories */
char const *f, *r = path;
for (f = r; *f; f++)
if (*f == '/')
r = f + 1;
return r;
}
/**
* Invariants
*/
constexpr char const *binary_name() { return "binary"; }
constexpr char const *linker_name() { return "ld.lib.so"; }
}
struct Linker::Phdr
{
enum { MAX_PHDR = 10 };
Elf::Phdr phdr[MAX_PHDR];
unsigned count = 0;
};
struct Linker::File
{
typedef void (*Entry)(void);
Phdr phdr;
Entry entry;
Elf::Addr reloc_base = 0;
Elf::Addr start = 0;
Elf::Size size = 0;
virtual ~File() { }
Elf::Phdr const *elf_phdr(unsigned index) const
{
if (index < phdr.count)
return &phdr.phdr[index];
return 0;
}
unsigned elf_phdr_count() const { return phdr.count; }
};
class Linker::Object : public Genode::Fifo