OLD | NEW |
(Empty) | |
| 1 // Copyright (c) 2013 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 #include <crazy_linker.h> |
| 6 |
| 7 #include <string.h> |
| 8 |
| 9 #include "crazy_linker_error.h" |
| 10 #include "crazy_linker_globals.h" |
| 11 #include "crazy_linker_proc_maps.h" |
| 12 #include "crazy_linker_search_path_list.h" |
| 13 #include "crazy_linker_shared_library.h" |
| 14 #include "crazy_linker_thread.h" |
| 15 #include "crazy_linker_util.h" |
| 16 #include "crazy_linker_library_view.h" |
| 17 #include "crazy_linker_system.h" |
| 18 |
| 19 using crazy::Globals; |
| 20 using crazy::Error; |
| 21 using crazy::SearchPathList; |
| 22 using crazy::ScopedGlobalLock; |
| 23 using crazy::LibraryView; |
| 24 |
| 25 // |
| 26 // crazy_context_t |
| 27 // |
| 28 |
| 29 struct crazy_context_t { |
| 30 public: |
| 31 crazy_context_t() |
| 32 : load_address(0), |
| 33 file_offset(0), |
| 34 error(), |
| 35 search_paths() { |
| 36 ResetSearchPaths(); |
| 37 } |
| 38 |
| 39 void ResetSearchPaths(); |
| 40 |
| 41 size_t load_address; |
| 42 size_t file_offset; |
| 43 Error error; |
| 44 SearchPathList search_paths; |
| 45 }; |
| 46 |
| 47 void crazy_context_t::ResetSearchPaths() { |
| 48 search_paths.Reset(); |
| 49 const char* env = crazy::GetEnv("LD_LIBRARY_PATH"); |
| 50 if (env && env[0]) |
| 51 search_paths.AddPaths(env); |
| 52 } |
| 53 |
| 54 // |
| 55 // API functions |
| 56 // |
| 57 |
| 58 extern "C" { |
| 59 |
| 60 crazy_context_t* crazy_context_create(void) { |
| 61 return new crazy_context_t(); |
| 62 } |
| 63 |
| 64 const char* crazy_context_get_error(crazy_context_t* context) { |
| 65 const char* error = context->error.c_str(); |
| 66 return (error[0] != '\0') ? error : NULL; |
| 67 } |
| 68 |
| 69 // Clear error in a given context. |
| 70 void crazy_context_clear_error(crazy_context_t* context) { |
| 71 context->error = ""; |
| 72 } |
| 73 |
| 74 void crazy_context_set_load_address(crazy_context_t* context, |
| 75 size_t load_address) { |
| 76 context->load_address = load_address; |
| 77 } |
| 78 |
| 79 size_t crazy_context_get_load_address(crazy_context_t* context) { |
| 80 return context->load_address; |
| 81 } |
| 82 |
| 83 void crazy_context_set_file_offset(crazy_context_t* context, |
| 84 size_t file_offset) { |
| 85 context->file_offset = file_offset; |
| 86 } |
| 87 |
| 88 size_t crazy_context_get_file_offset(crazy_context_t* context) { |
| 89 return context->file_offset; |
| 90 } |
| 91 |
| 92 crazy_status_t crazy_context_add_search_path(crazy_context_t* context, |
| 93 const char* file_path) { |
| 94 context->search_paths.AddPaths(file_path); |
| 95 return CRAZY_STATUS_OK; |
| 96 } |
| 97 |
| 98 crazy_status_t crazy_context_add_search_path_for_address( |
| 99 crazy_context_t* context, |
| 100 void* address) { |
| 101 uintptr_t load_address; |
| 102 char path[512]; |
| 103 char* p; |
| 104 |
| 105 if (crazy::FindElfBinaryForAddress( |
| 106 address, &load_address, path, sizeof(path)) && |
| 107 (p = strrchr(path, '/')) != NULL && p[1]) { |
| 108 *p = '\0'; |
| 109 return crazy_context_add_search_path(context, path); |
| 110 } |
| 111 |
| 112 context->error.Format( |
| 113 "Could not find ELF binary at address @%p", address); |
| 114 return CRAZY_STATUS_KO; |
| 115 } |
| 116 |
| 117 void crazy_context_reset_search_paths(crazy_context_t* context) { |
| 118 context->ResetSearchPaths(); |
| 119 } |
| 120 |
| 121 void crazy_context_destroy(crazy_context_t* context) { |
| 122 delete context; |
| 123 } |
| 124 |
| 125 crazy_status_t crazy_library_open(crazy_library_t** library, |
| 126 const char* lib_name, |
| 127 crazy_context_t* context) { |
| 128 ScopedGlobalLock lock; |
| 129 LibraryView* wrap = |
| 130 crazy::Globals::GetLibraries()->LoadLibrary(lib_name, |
| 131 RTLD_NOW, |
| 132 context->load_address, |
| 133 context->file_offset, |
| 134 &context->search_paths, |
| 135 &context->error); |
| 136 if (!wrap) |
| 137 return CRAZY_STATUS_KO; |
| 138 |
| 139 *library = reinterpret_cast<crazy_library_t*>(wrap); |
| 140 return CRAZY_STATUS_OK; |
| 141 } |
| 142 |
| 143 crazy_status_t crazy_library_get_info(crazy_library_t* library, |
| 144 crazy_context_t* context, |
| 145 crazy_library_info_t* info) { |
| 146 if (!library) { |
| 147 context->error = "Invalid library file handle"; |
| 148 return CRAZY_STATUS_KO; |
| 149 } |
| 150 |
| 151 LibraryView* wrap = reinterpret_cast<LibraryView*>(library); |
| 152 if (!wrap->GetInfo(&info->load_address, |
| 153 &info->load_size, |
| 154 &info->relro_start, |
| 155 &info->relro_size, |
| 156 &info->relro_fd, |
| 157 &context->error)) { |
| 158 return CRAZY_STATUS_KO; |
| 159 } |
| 160 |
| 161 return CRAZY_STATUS_OK; |
| 162 } |
| 163 |
| 164 crazy_status_t crazy_library_enable_relro_sharing( |
| 165 crazy_library_t* library, |
| 166 crazy_context_t* context) { |
| 167 LibraryView* wrap = |
| 168 reinterpret_cast<LibraryView*>(library); |
| 169 |
| 170 if (!library) { |
| 171 context->error = "Invalid library file handle"; |
| 172 return CRAZY_STATUS_KO; |
| 173 } |
| 174 |
| 175 if (!wrap->EnableSharedRelro(&context->error)) |
| 176 return CRAZY_STATUS_KO; |
| 177 |
| 178 return CRAZY_STATUS_OK; |
| 179 } |
| 180 |
| 181 crazy_status_t crazy_library_use_relro_sharing( |
| 182 crazy_library_t* library, |
| 183 size_t relro_start, |
| 184 size_t relro_size, |
| 185 int relro_fd, |
| 186 crazy_context_t* context) { |
| 187 LibraryView* wrap = |
| 188 reinterpret_cast<LibraryView*>(library); |
| 189 |
| 190 if (!library) { |
| 191 context->error = "Invalid library file handle"; |
| 192 return CRAZY_STATUS_KO; |
| 193 } |
| 194 |
| 195 if (!wrap->UseSharedRelro(relro_start, |
| 196 relro_size, |
| 197 relro_fd, |
| 198 &context->error)) { |
| 199 return CRAZY_STATUS_KO; |
| 200 } |
| 201 |
| 202 return CRAZY_STATUS_OK; |
| 203 } |
| 204 |
| 205 crazy_status_t crazy_library_find_by_name(const char* library_name, |
| 206 crazy_library_t** library) { |
| 207 { |
| 208 ScopedGlobalLock lock; |
| 209 LibraryView* wrap = |
| 210 Globals::GetLibraries()->FindLibraryByName(library_name); |
| 211 if (!wrap) |
| 212 return CRAZY_STATUS_KO; |
| 213 |
| 214 wrap->AddRef(); |
| 215 *library = reinterpret_cast<crazy_library_t*>(wrap); |
| 216 } |
| 217 return CRAZY_STATUS_OK; |
| 218 } |
| 219 |
| 220 crazy_status_t crazy_library_find_symbol( |
| 221 crazy_library_t* library, |
| 222 const char* symbol_name, |
| 223 void** symbol_address) { |
| 224 LibraryView* wrap = |
| 225 reinterpret_cast<LibraryView*>(library); |
| 226 |
| 227 // TODO(digit): Handle NULL symbols properly. |
| 228 *symbol_address = wrap->LookupSymbol(symbol_name); |
| 229 return (*symbol_address == NULL) ? CRAZY_STATUS_KO : CRAZY_STATUS_OK; |
| 230 } |
| 231 |
| 232 crazy_status_t crazy_linker_find_symbol( |
| 233 const char* symbol_name, |
| 234 void** symbol_address) { |
| 235 // TODO(digit): Implement this. |
| 236 return CRAZY_STATUS_KO; |
| 237 } |
| 238 |
| 239 crazy_status_t crazy_library_find_from_address( |
| 240 void* address, crazy_library_t** library) { |
| 241 { |
| 242 ScopedGlobalLock lock; |
| 243 LibraryView* wrap = |
| 244 Globals::GetLibraries()->FindLibraryForAddress(address); |
| 245 if (!wrap) |
| 246 return CRAZY_STATUS_KO; |
| 247 |
| 248 wrap->AddRef(); |
| 249 |
| 250 *library = reinterpret_cast<crazy_library_t*>(wrap); |
| 251 return CRAZY_STATUS_OK; |
| 252 } |
| 253 } |
| 254 |
| 255 void crazy_library_close(crazy_library_t* library) { |
| 256 if (library) { |
| 257 ScopedGlobalLock lock; |
| 258 LibraryView* wrap = |
| 259 reinterpret_cast<LibraryView*>(library); |
| 260 |
| 261 Globals::GetLibraries()->UnloadLibrary(wrap); |
| 262 } |
| 263 } |
| 264 |
| 265 } // extern "C" |
OLD | NEW |