root/headers/private/runtime_loader/runtime_loader.h
/*
 * Copyright 2008-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
 * Copyright 2003-2011, Axel Dörfler, axeld@pinc-software.de.
 * Distributed under the terms of the MIT License.
 *
 * Copyright 2002, Manuel J. Petit. All rights reserved.
 * Copyright 2001, Travis Geiselbrecht. All rights reserved.
 * Distributed under the terms of the NewOS License.
 */

#ifndef _RUNTIME_LOADER_H
#define _RUNTIME_LOADER_H


#include <image.h>
#include <OS.h>

#include <elf_private.h>


// #pragma mark - runtime loader libroot interface


struct user_space_program_args;
struct SymbolLookupInfo;

struct rld_export {
        // runtime loader API export
        image_id (*load_add_on)(char const *path, uint32 flags);
        status_t (*unload_add_on)(image_id imageID);
        image_id (*load_library)(char const *path, uint32 flags, void* caller,
                void **_handle);
        status_t (*unload_library)(void* handle);
        status_t (*get_image_symbol)(image_id imageID, char const *symbolName,
                int32 symbolType, bool recursive, image_id *_inImage, void **_location);
        status_t (*get_library_symbol)(void* handle, void* caller,
                const char* symbolName, void **_location);
        status_t (*get_nth_image_symbol)(image_id imageID, int32 num,
                char *symbolName, int32 *nameLength, int32 *symbolType,
                void **_location);
        status_t (*get_nearest_symbol_at_address)(void* address,
                image_id* _imageID,     char** _imagePath, char** _imageName,
                char** _symbolName, int32* _type, void** _location, bool* _exactMatch);
        status_t (*test_executable)(const char *path, char *interpreter);
        status_t (*get_executable_architecture)(const char *path,
                const char** _architecture);
        status_t (*get_next_image_dependency)(image_id id, uint32 *cookie,
                const char **_name);
        void* (*get_tls_address)(unsigned dso, addr_t offset);
        void (*destroy_thread_tls)();

        status_t (*reinit_after_fork)();

        void (*call_atexit_hooks_for_range)(addr_t start, addr_t size);

        void (*call_termination_hooks)();

        const struct user_space_program_args *program_args;
        const void* commpage_address;
        int abi_version;
        int api_version;
};

extern struct rld_export *__gRuntimeLoader;


// #pragma mark - runtime loader debugger interface


struct RuntimeLoaderSymbolPatcher;

typedef struct elf_region_t {
        area_id         id;
        addr_t          start;
        addr_t          size;
        addr_t          vmstart;
        addr_t          vmsize;
        addr_t          fdstart;
        addr_t          fdsize;
        long            delta;
        uint32          flags;
} elf_region_t;

typedef struct elf_version_info {
        uint32          hash;                   // version name hash
        const char      *name;                  // version name
        const char      *file_name;             // dependency file name (needed versions only)
} elf_version_info;

typedef struct image_t {
        // image identification
        char                            path[B_PATH_NAME_LENGTH];
        char                            name[B_FILE_NAME_LENGTH];
        image_id                        id;
        image_type                      type;

        struct image_t          *next;
        struct image_t          *prev;
        int32                           ref_count;
        uint32                          flags;

        uint32                          api_version;
        uint32                          abi;

        addr_t                          entry_point;
        addr_t                          init_routine;
        addr_t                          term_routine;
        addr_t                          dynamic_ptr;    // pointer to the dynamic section

        // needed images
        uint32                          num_needed;
        struct image_t          **needed;

        // symbol participation data structures
        uint32                          *symhash;
        elf_sym                         *syms;
        char                            *strtab;
        struct {
                uint32                  mask_words_count_mask;
                uint32                  shift2;
                uint32                  bucket_count;
                elf_addr                *bloom;
                uint32                  *buckets;
                uint32                  *chain0;
        } gnuhash;

        // relocation information
        elf_rel                         *rel;
        int                                     rel_len;
        elf_rela                        *rela;
        int                                     rela_len;
        elf_rel                         *pltrel;
        int                                     pltrel_len;

        // init/term functions
        addr_t                          *init_array;
        int                                     init_array_len;
        addr_t                          *preinit_array;
        int                                     preinit_array_len;
        addr_t                          *term_array;
        int                                     term_array_len;

        // versioning related structures
        uint32                          num_version_definitions;
        elf_verdef                      *version_definitions;
        uint32                          num_needed_versions;
        elf_verneed                     *needed_versions;
        elf_versym                      *symbol_versions;
        elf_version_info        *versions;
        uint32                          num_versions;

        // thread-local storage
        unsigned                        dso_tls_id;

#ifdef __cplusplus
        elf_sym*                        (*find_undefined_symbol)(struct image_t* rootImage,
                                                        struct image_t* image,
                                                        const SymbolLookupInfo& lookupInfo,
                                                        struct image_t** foundInImage);
#else
        elf_sym*                        (*find_undefined_symbol)(struct image_t* rootImage,
                                                        struct image_t* image,
                                                        const struct SymbolLookupInfo* lookupInfo,
                                                        struct image_t** foundInImage);
#endif

        // Singly-linked list of symbol patchers for symbols defined respectively
        // referenced by this image.
        struct RuntimeLoaderSymbolPatcher       *defined_symbol_patchers;
        struct RuntimeLoaderSymbolPatcher       *undefined_symbol_patchers;

        // describes the text and data regions
        uint32                          num_regions;
        elf_region_t            regions[1];
} image_t;

typedef struct image_queue_t {
        image_t *head;
        image_t *tail;
} image_queue_t;

// image_t::flags
#define IMAGE_FLAG_RTLD_MASK                    0x03
                        // RTLD_{LAZY,NOW} | RTLD_{LOCAL,GLOBAL}

#define STRING(image, offset) ((char*)(&(image)->strtab[(offset)]))
#define SYMNAME(image, sym) STRING(image, (sym)->st_name)
#define SYMBOL(image, num) (&(image)->syms[num])
#define HASHTABSIZE(image) ((image)->symhash[0])
#define HASHBUCKETS(image) ((unsigned int*)&(image)->symhash[2])
#define HASHCHAINS(image) ((unsigned int*)&(image)->symhash[2+HASHTABSIZE(image)])


// The name of the area the runtime loader creates for debugging purposes.
#define RUNTIME_LOADER_DEBUG_AREA_NAME  "_rld_debug_"

// The contents of the runtime loader debug area.
typedef struct runtime_loader_debug_area {
        image_queue_t   *loaded_images;
} runtime_loader_debug_area;


// #pragma mark - runtime loader add-on interface


// symbol patcher callback
typedef void runtime_loader_symbol_patcher(void* cookie,
        struct image_t* rootImage, struct image_t* image, const char* name,
        struct image_t** foundInImage, void** symbol, int32* type);

// interface provided to add-ons
struct runtime_loader_add_on_export {
        status_t        (*register_defined_symbol_patcher)(struct image_t* image,
                                        runtime_loader_symbol_patcher* patcher, void* cookie);
        void            (*unregister_defined_symbol_patcher)(struct image_t* image,
                                        runtime_loader_symbol_patcher* patcher, void* cookie);
        status_t        (*register_undefined_symbol_patcher)(struct image_t* image,
                                        runtime_loader_symbol_patcher* patcher, void* cookie);
        void            (*unregister_undefined_symbol_patcher)(struct image_t* image,
                                        runtime_loader_symbol_patcher* patcher, void* cookie);
};


#define RUNTIME_LOADER_ADD_ON_VERSION   1

typedef struct runtime_loader_add_on {
        uint32  version;
        uint32  flags;

        // called after the add-on image has been loaded
        void    (*init)(struct rld_export* standardInterface,
                                struct runtime_loader_add_on_export* addOnInterface);

        // called whenever the respective image event occurs
        void    (*image_loaded)(struct image_t* image);
        void    (*image_relocated)(struct image_t* image);
        void    (*image_initialized)(struct image_t* image);
        void    (*image_uninitializing)(struct image_t* image);
        void    (*image_unloading)(struct image_t* image);
} runtime_loader_add_on;

// This is the variable a preloaded shared object has to export to get picked up
// by the runtime loader as an add-on.
extern runtime_loader_add_on __gRuntimeLoaderAddOn;

#endif  // _RUNTIME_LOADER_H