1f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved. 2f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 3f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// found in the LICENSE file. 4f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 5f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#ifndef CRAZY_LINKER_RDEBUG_H 6f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#define CRAZY_LINKER_RDEBUG_H 7f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#include <stdint.h> 9f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 10f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The system linker maintains two lists of libraries at runtime: 11f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 12f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - A list that is used by GDB and other tools to search for the 13f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// binaries that are loaded in the process. 14f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 15f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This list is accessible by looking at the DT_DEBUG field of the 16f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// dynamic section of any ELF binary loaded by the linker (including 17f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// itself). The field contains the address of a global '_r_debug' 18f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// variable. More on this later. 19f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 20f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - A list that is used internally to implement library and symbol 21f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// lookup. The list head and tail are called 'solist' and 'sonext' 22f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// in the linker sources, and their address is unknown (and randomized 23f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// by ASLR), and there is no point trying to change it. 24f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 25f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// This means that you cannot call the linker's dlsym() function to 26f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// lookup symbols in libraries that are not loaded through it, i.e. 27f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// any custom dynamic linker needs its own dlopen() / dlsym() and other 28f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// related functions, and ensure the loaded code only uses its own version. 29f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// (See support code in crazy_linker_wrappers.cpp) 30f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 31f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The global '_r_debug' variable is a r_debug structure, whose layout 32f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// must be known by GDB, with the following fields: 33f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 34f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// r_version -> version of the structure (must be 1) 35f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// r_map -> head of a linked list of 'link_map_t' entries, 36f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// one per ELF 'binary' in the process address space. 37f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// r_brk -> pointer to a specific debugging function (see below). 38f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// r_state -> state variable to be read in r_brk(). 39f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// r_ldbase -> unused by the system linker, should be 0. (?) 40f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 41f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The 'r_brk' field points to an empty function in the system linker 42f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// that is used to notify GDB of changes in the list of shared libraries, 43f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// this works as follows: 44f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 45f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - When the linker wants to add a new shared library to the list, 46f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// it first writes RT_ADD to 'r_state', then calls 'r_brk()'. 47f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 48f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// It modifies the list, then writes RT_CONSISTENT to 'r_state' and 49f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// calls 'r_brk()' again. 50f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 51f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - When unloading a library, RT_DELETE + RT_CONSISTENT are used 52f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// instead. 53f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 54f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// GDB will always place a breakpoint on the function pointed to by 55f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 'r_brk', and will be able to synchronize with the linker's 56f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// modifications. 57f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 58f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The 'r_map' field is a list of nodes with the following structure 59f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// describing each loaded shared library for GDB: 60f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 61f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// l_addr -> Load address of the first PT_LOAD segment in a 62f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// shared library. Note that this is 0 for the linker itself 63f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// and the load-bias for an executable. 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// l_name -> Name of the executable. This is _always_ a basename!! 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// l_ld -> Address of the dynamic table for this binary. 66f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// l_next -> Pointer to next item in 'r_map' list or NULL. 67f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// l_prev -> Pointer to previous item in 'r_map' list. 68f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that the system linker ensures that there are always at least 70f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// two items in this list: 71f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 72f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - The first item always describes the linker itself, the fields 73f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// actually point to a specially crafted fake entry for it called 74f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 'libdl_info' in the linker sources. 75f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 76f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - The second item describes the executable that was started by 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the kernel. For Android applications, it will always be 'app_process' 78f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// and completely uninteresting. 79f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 80f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// - Eventually, another entry for VDSOs on platforms that support them. 81f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 82f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// When implementing a custom linker, being able to debug the process 83f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// unfortunately requires modifying the 'r_map' list to also account 84f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// for libraries loading through it. 85f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 86f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// One issue with this is that the linker also uses another internal 87f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// variable, called '_r_debut_tail' that points to the last item in 88f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the list. And there is no way to access it directly. This can lead 89f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to problems when calling APIs that actually end up using the system's 90f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// own dlopen(). Consider this example: 91f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 92f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 1/ Program loads crazy_linker 93f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 94f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 2/ Program uses crazy_linker to load libfoo.so, this adds 95f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// a new entry at the end of the '_r_debug.r_map' list, but 96f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// '_r_debug.tail' is unmodified. 97f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 98f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 3/ libfoo.so or the Java portion of the program calls a system API 99f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// that ends up loading another library (e.g. libGLESv2_vendor.so), 100f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// this calls the system dlopen(). 101f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 102f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 4/ The system dlopen() adds a new entry to the "_r_debug.r_map" 103f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// list by updating the l_next / l_prev fields of the entry pointed 104f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// to by '_r_debug_tail', and this removes 'libfoo.so' from the list! 105f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// There is a simple work-around for this issue: Always insert our 107f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// libraries at the _start_ of the 'r_map' list, instead of appending 108f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// them to the end. The system linker doesn't know about custom-loaded 109f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// libraries and thus will never try to unload them. 110f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 111f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Note that the linker never uses the 'r_map' list (except or updating 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// it for GDB), it only uses 'solist / sonext' to actually perform its 113f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// operations. That's ok if our custom linker completely wraps and 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// re-implements these. 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// 116f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// The system linker expects to be the only item modifying the 'r_map' 117f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// list, and as such it may set the pages that contain the list readonly 118f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// outside of its own modifications. In threaded environments where the 119f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// system linker and the crazy linker are operating simultaneously on 120f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// different threads this may be a problem; we need these pages to be 121f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// writable when we have to update the list. We cannot track the system 122f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// linker's actions, so to avoid clashing with it we may need to try and 123f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// move 'r_map' updates to a different thread, to serialize them with 124f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// other system linker activity. 125f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)namespace crazy { 126f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 127f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct link_map_t { 128f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uintptr_t l_addr; 129f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) char* l_name; 130f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uintptr_t l_ld; 131f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) link_map_t* l_next; 132f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) link_map_t* l_prev; 133f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 134f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 135f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// Values for r_debug->r_state 136f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)enum { 137f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RT_CONSISTENT, 138f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RT_ADD, 139f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RT_DELETE 140f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 141f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 142f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)struct r_debug { 143f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t r_version; 144f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) link_map_t* r_map; 145f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void (*r_brk)(void); 146f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) int32_t r_state; 147f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) uintptr_t r_ldbase; 148f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 149f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 150f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A callback poster is a function that can be called to request a later 151f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// callback. Poster arguments are: an opaque pointer to the caller's 152f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// context, a pointer to a function with a single void* argument that will 153f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// handle the callback, and the opaque void* argument value to send with 154f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// the callback. 155f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef void (*crazy_callback_handler_t)(void* opaque); 156f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef bool (*rdebug_callback_poster_t)(void* context, 157f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) crazy_callback_handler_t, 158f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* opaque); 159f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 160f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// A callback handler is a static function, either AddEntryInternal() or 161f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// DelEntryInternal(). It calls the appropriate r_map update member 162f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)// function, AddEntryImpl() or DelEntryImpl(). 163f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class RDebug; 164f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)typedef void (*rdebug_callback_handler_t)(RDebug*, link_map_t*); 165f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 166f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)class RDebug { 167f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) public: 168f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RDebug() : r_debug_(NULL), init_(false), 169f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) readonly_entries_(false), post_for_later_execution_(NULL), 170f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) post_for_later_execution_context_(NULL) {} 171f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) ~RDebug() {} 172f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 173f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Add entries to and remove entries from the list. If post for later 174f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // execution is enabled, schedule callbacks and return. Otherwise 175f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // action immediately. 176f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void AddEntry(link_map_t* entry) { RunOrDelay(&AddEntryInternal, entry); } 177f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void DelEntry(link_map_t* entry) { RunOrDelay(&DelEntryInternal, entry); } 178f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 179f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Assign the function used to request a callback from another thread. 180f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // The context here is opaque, but is the API's crazy_context. 181f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void SetDelayedCallbackPoster(rdebug_callback_poster_t poster, 182f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* context) { 183f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) post_for_later_execution_ = poster; 184f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) post_for_later_execution_context_ = context; 185f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 186f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 187f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) r_debug* GetAddress() { return r_debug_; } 188f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 189f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) private: 190f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Try to find the address of the global _r_debug variable, even 191f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // though there is no symbol for it. Returns true on success. 192f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool Init(); 193f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 194f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Support for scheduling list manipulation through callbacks. 195f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // AddEntry() and DelEntry() pass the addresses of static functions to 196f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // to RunOrDelay(). This requests a callback if later execution 197f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // is enabled, otherwise it runs immediately on the current thread. 198f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // AddEntryImpl() and DelEntryImpl() are the member functions called 199f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // by the static ones to do the actual work. 200f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void AddEntryImpl(link_map_t* entry); 201f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void DelEntryImpl(link_map_t* entry); 202f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static void AddEntryInternal(RDebug* rdebug, link_map_t* entry) { 203f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rdebug->AddEntryImpl(entry); 204f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 205f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) static void DelEntryInternal(RDebug* rdebug, link_map_t* entry) { 206f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rdebug->DelEntryImpl(entry); 207f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 208f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 209f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Post handler for delayed execution. Return true if delayed execution 210f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // is enabled and posting succeeded. 211f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool PostCallback(rdebug_callback_handler_t handler, link_map_t* entry); 212f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 213f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) // Run handler as a callback if enabled, otherwise immediately. 214f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void RunOrDelay(rdebug_callback_handler_t handler, link_map_t* entry) { 215f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) if (!PostCallback(handler, entry)) 216f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) (*handler)(this, entry); 217f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) } 218f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 219f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RDebug(const RDebug&); 220f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) RDebug& operator=(const RDebug&); 221f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 222f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) r_debug* r_debug_; 223f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool init_; 224f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) bool readonly_entries_; 225f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) rdebug_callback_poster_t post_for_later_execution_; 226f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) void* post_for_later_execution_context_; 227f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)}; 228f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 229f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} // namespace crazy 230f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 231f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)#endif // CRAZY_LINKER_REDUG_H 232