1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef CRAZY_LINKER_RDEBUG_H
6 #define CRAZY_LINKER_RDEBUG_H
7 
8 #include <stdint.h>
9 
10 // The system linker maintains two lists of libraries at runtime:
11 //
12 // - A list that is used by GDB and other tools to search for the
13 //   binaries that are loaded in the process.
14 //
15 //   This list is accessible by looking at the DT_DEBUG field of the
16 //   dynamic section of any ELF binary loaded by the linker (including
17 //   itself). The field contains the address of a global '_r_debug'
18 //   variable. More on this later.
19 //
20 // - A list that is used internally to implement library and symbol
21 //   lookup. The list head and tail are called 'solist' and 'sonext'
22 //   in the linker sources, and their address is unknown (and randomized
23 //   by ASLR), and there is no point trying to change it.
24 //
25 // This means that you cannot call the linker's dlsym() function to
26 // lookup symbols in libraries that are not loaded through it, i.e.
27 // any custom dynamic linker needs its own dlopen() / dlsym() and other
28 // related functions, and ensure the loaded code only uses its own version.
29 // (See support code in crazy_linker_wrappers.cpp)
30 //
31 // The global '_r_debug' variable is a r_debug structure, whose layout
32 // must be known by GDB, with the following fields:
33 //
34 //     r_version   -> version of the structure (must be 1)
35 //     r_map       -> head of a linked list of 'link_map_t' entries,
36 //                    one per ELF 'binary' in the process address space.
37 //     r_brk       -> pointer to a specific debugging function (see below).
38 //     r_state     -> state variable to be read in r_brk().
39 //     r_ldbase    -> unused by the system linker, should be 0. (?)
40 //
41 // The 'r_brk' field points to an empty function in the system linker
42 // that is used to notify GDB of changes in the list of shared libraries,
43 // this works as follows:
44 //
45 //   - When the linker wants to add a new shared library to the list,
46 //     it first writes RT_ADD to 'r_state', then calls 'r_brk()'.
47 //
48 //     It modifies the list, then writes RT_CONSISTENT to 'r_state' and
49 //     calls 'r_brk()' again.
50 //
51 //   - When unloading a library, RT_DELETE + RT_CONSISTENT are used
52 //     instead.
53 //
54 // GDB will always place a breakpoint on the function pointed to by
55 // 'r_brk', and will be able to synchronize with the linker's
56 // modifications.
57 //
58 // The 'r_map' field is a list of nodes with the following structure
59 // describing each loaded shared library for GDB:
60 //
61 //   l_addr  -> Load address of the first PT_LOAD segment in a
62 //              shared library. Note that this is 0 for the linker itself
63 //              and the load-bias for an executable.
64 //   l_name  -> Name of the executable. This is _always_ a basename!!
65 //   l_ld    -> Address of the dynamic table for this binary.
66 //   l_next  -> Pointer to next item in 'r_map' list or NULL.
67 //   l_prev  -> Pointer to previous item in 'r_map' list.
68 //
69 // Note that the system linker ensures that there are always at least
70 // two items in this list:
71 //
72 // - The first item always describes the linker itself, the fields
73 //   actually point to a specially crafted fake entry for it called
74 //   'libdl_info' in the linker sources.
75 //
76 // - The second item describes the executable that was started by
77 //   the kernel. For Android applications, it will always be 'app_process'
78 //   and completely uninteresting.
79 //
80 // - Eventually, another entry for VDSOs on platforms that support them.
81 //
82 // When implementing a custom linker, being able to debug the process
83 // unfortunately requires modifying the 'r_map' list to also account
84 // for libraries loading through it.
85 //
86 // One issue with this is that the linker also uses another internal
87 // variable, called '_r_debut_tail' that points to the last item in
88 // the list. And there is no way to access it directly. This can lead
89 // to problems when calling APIs that actually end up using the system's
90 // own dlopen(). Consider this example:
91 //
92 //  1/ Program loads crazy_linker
93 //
94 //  2/ Program uses crazy_linker to load libfoo.so, this adds
95 //     a new entry at the end of the '_r_debug.r_map' list, but
96 //     '_r_debug.tail' is unmodified.
97 //
98 //  3/ libfoo.so or the Java portion of the program calls a system API
99 //     that ends up loading another library (e.g. libGLESv2_vendor.so),
100 //     this calls the system dlopen().
101 //
102 //  4/ The system dlopen() adds a new entry to the "_r_debug.r_map"
103 //     list by updating the l_next / l_prev fields of the entry pointed
104 //     to by '_r_debug_tail', and this removes 'libfoo.so' from the list!
105 //
106 // There is a simple work-around for this issue: Always insert our
107 // libraries at the _start_ of the 'r_map' list, instead of appending
108 // them to the end. The system linker doesn't know about custom-loaded
109 // libraries and thus will never try to unload them.
110 //
111 // Note that the linker never uses the 'r_map' list (except or updating
112 // it for GDB), it only uses 'solist / sonext' to actually perform its
113 // operations. That's ok if our custom linker completely wraps and
114 // re-implements these.
115 //
116 // The system linker expects to be the only item modifying the 'r_map'
117 // list, and as such it may set the pages that contain the list readonly
118 // outside of its own modifications. In threaded environments where the
119 // system linker and the crazy linker are operating simultaneously on
120 // different threads this may be a problem; we need these pages to be
121 // writable when we have to update the list.
122 //
123 // TECHNICAL NOTE: If CRAZY_DISABLE_R_BRK is defined at compile time,
124 // then the crazy linker will never try to call the r_brk() GDB Hook
125 // function. This can be useful to avoid runtime crashes on certain
126 // Android devices with x86 processors, running ARM binaries with
127 // a machine translator like Houdini. See http://crbug.com/796938
128 //
129 namespace crazy {
130 
131 struct link_map_t {
132   uintptr_t l_addr;
133   char* l_name;
134   uintptr_t l_ld;
135   link_map_t* l_next;
136   link_map_t* l_prev;
137 };
138 
139 // Values for r_debug->r_state
140 enum {
141   RT_CONSISTENT,
142   RT_ADD,
143   RT_DELETE
144 };
145 
146 struct r_debug {
147   int32_t r_version;
148   link_map_t* r_map;
149   void (*r_brk)(void);
150   int32_t r_state;
151   uintptr_t r_ldbase;
152 };
153 
154 class RDebug {
155  public:
156   RDebug() = default;
157   ~RDebug() = default;
158 
159   RDebug(const RDebug&) = delete;
160   RDebug& operator=(const RDebug&) = delete;
161 
162   // Add entries to and remove entries from the list.
163   void AddEntry(link_map_t* entry);
164   void DelEntry(link_map_t* entry);
165 
166   // Return address of current global _r_debug variable, or nullptr if not
167   // available.
168   r_debug* GetAddress();
169 
170  private:
171   // Try to find the address of the global _r_debug variable, even
172   // though there is no symbol for it. Returns true on success.
173   bool Init();
174 
175   // Call the debugger hook function |r_debug_->r_brk|.
176   // |state| is the value to write to |r_debug_->r_state|
177   // before that. This is done to coordinate with the
178   // debugger when modifications of the global |r_debug_|
179   // list are performed.
180   void CallRBrk(int state);
181 
182   r_debug* r_debug_ = nullptr;
183   bool init_ = false;
184 };
185 
186 }  // namespace crazy
187 
188 #endif  // CRAZY_LINKER_REDUG_H
189