1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/mozglue/linker/ElfLoader.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1126 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this file, 1.6 + * You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +#include <string> 1.9 +#include <cstring> 1.10 +#include <cstdlib> 1.11 +#include <cstdio> 1.12 +#include <dlfcn.h> 1.13 +#include <unistd.h> 1.14 +#include <algorithm> 1.15 +#include <fcntl.h> 1.16 +#include "ElfLoader.h" 1.17 +#include "CustomElf.h" 1.18 +#include "Mappable.h" 1.19 +#include "Logging.h" 1.20 +#include <inttypes.h> 1.21 + 1.22 +#if defined(ANDROID) 1.23 +#include <sys/syscall.h> 1.24 + 1.25 +#include <android/api-level.h> 1.26 +#if __ANDROID_API__ < 8 1.27 +/* Android API < 8 doesn't provide sigaltstack */ 1.28 + 1.29 +extern "C" { 1.30 + 1.31 +inline int sigaltstack(const stack_t *ss, stack_t *oss) { 1.32 + return syscall(__NR_sigaltstack, ss, oss); 1.33 +} 1.34 + 1.35 +} /* extern "C" */ 1.36 +#endif /* __ANDROID_API__ */ 1.37 +#endif /* ANDROID */ 1.38 + 1.39 +#ifdef __ARM_EABI__ 1.40 +extern "C" const void * 1.41 +__gnu_Unwind_Find_exidx(void *pc, int *pcount) __attribute__((weak)); 1.42 +#endif 1.43 + 1.44 +using namespace mozilla; 1.45 + 1.46 +/** 1.47 + * dlfcn.h replacements functions 1.48 + */ 1.49 + 1.50 +void * 1.51 +__wrap_dlopen(const char *path, int flags) 1.52 +{ 1.53 + RefPtr<LibHandle> handle = ElfLoader::Singleton.Load(path, flags); 1.54 + if (handle) 1.55 + handle->AddDirectRef(); 1.56 + return handle; 1.57 +} 1.58 + 1.59 +const char * 1.60 +__wrap_dlerror(void) 1.61 +{ 1.62 + const char *error = ElfLoader::Singleton.lastError; 1.63 + ElfLoader::Singleton.lastError = nullptr; 1.64 + return error; 1.65 +} 1.66 + 1.67 +void * 1.68 +__wrap_dlsym(void *handle, const char *symbol) 1.69 +{ 1.70 + if (!handle) { 1.71 + ElfLoader::Singleton.lastError = "dlsym(NULL, sym) unsupported"; 1.72 + return nullptr; 1.73 + } 1.74 + if (handle != RTLD_DEFAULT && handle != RTLD_NEXT) { 1.75 + LibHandle *h = reinterpret_cast<LibHandle *>(handle); 1.76 + return h->GetSymbolPtr(symbol); 1.77 + } 1.78 + return dlsym(handle, symbol); 1.79 +} 1.80 + 1.81 +int 1.82 +__wrap_dlclose(void *handle) 1.83 +{ 1.84 + if (!handle) { 1.85 + ElfLoader::Singleton.lastError = "No handle given to dlclose()"; 1.86 + return -1; 1.87 + } 1.88 + reinterpret_cast<LibHandle *>(handle)->ReleaseDirectRef(); 1.89 + return 0; 1.90 +} 1.91 + 1.92 +int 1.93 +__wrap_dladdr(void *addr, Dl_info *info) 1.94 +{ 1.95 + RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(addr); 1.96 + if (!handle) 1.97 + return 0; 1.98 + info->dli_fname = handle->GetPath(); 1.99 + return 1; 1.100 +} 1.101 + 1.102 +int 1.103 +__wrap_dl_iterate_phdr(dl_phdr_cb callback, void *data) 1.104 +{ 1.105 + if (!ElfLoader::Singleton.dbg) 1.106 + return -1; 1.107 + 1.108 + for (ElfLoader::DebuggerHelper::iterator it = ElfLoader::Singleton.dbg.begin(); 1.109 + it < ElfLoader::Singleton.dbg.end(); ++it) { 1.110 + dl_phdr_info info; 1.111 + info.dlpi_addr = reinterpret_cast<Elf::Addr>(it->l_addr); 1.112 + info.dlpi_name = it->l_name; 1.113 + info.dlpi_phdr = nullptr; 1.114 + info.dlpi_phnum = 0; 1.115 + 1.116 + // Assuming l_addr points to Elf headers (in most cases, this is true), 1.117 + // get the Phdr location from there. 1.118 + uint8_t mapped; 1.119 + // If the page is not mapped, mincore returns an error. 1.120 + if (!mincore(const_cast<void*>(it->l_addr), PageSize(), &mapped)) { 1.121 + const Elf::Ehdr *ehdr = Elf::Ehdr::validate(it->l_addr); 1.122 + if (ehdr) { 1.123 + info.dlpi_phdr = reinterpret_cast<const Elf::Phdr *>( 1.124 + reinterpret_cast<const char *>(ehdr) + ehdr->e_phoff); 1.125 + info.dlpi_phnum = ehdr->e_phnum; 1.126 + } 1.127 + } 1.128 + 1.129 + int ret = callback(&info, sizeof(dl_phdr_info), data); 1.130 + if (ret) 1.131 + return ret; 1.132 + } 1.133 + return 0; 1.134 +} 1.135 + 1.136 +#ifdef __ARM_EABI__ 1.137 +const void * 1.138 +__wrap___gnu_Unwind_Find_exidx(void *pc, int *pcount) 1.139 +{ 1.140 + RefPtr<LibHandle> handle = ElfLoader::Singleton.GetHandleByPtr(pc); 1.141 + if (handle) 1.142 + return handle->FindExidx(pcount); 1.143 + if (__gnu_Unwind_Find_exidx) 1.144 + return __gnu_Unwind_Find_exidx(pc, pcount); 1.145 + *pcount = 0; 1.146 + return nullptr; 1.147 +} 1.148 +#endif 1.149 + 1.150 +/** 1.151 + * faulty.lib public API 1.152 + */ 1.153 + 1.154 +MFBT_API size_t 1.155 +__dl_get_mappable_length(void *handle) { 1.156 + if (!handle) 1.157 + return 0; 1.158 + return reinterpret_cast<LibHandle *>(handle)->GetMappableLength(); 1.159 +} 1.160 + 1.161 +MFBT_API void * 1.162 +__dl_mmap(void *handle, void *addr, size_t length, off_t offset) 1.163 +{ 1.164 + if (!handle) 1.165 + return nullptr; 1.166 + return reinterpret_cast<LibHandle *>(handle)->MappableMMap(addr, length, 1.167 + offset); 1.168 +} 1.169 + 1.170 +MFBT_API void 1.171 +__dl_munmap(void *handle, void *addr, size_t length) 1.172 +{ 1.173 + if (!handle) 1.174 + return; 1.175 + return reinterpret_cast<LibHandle *>(handle)->MappableMUnmap(addr, length); 1.176 +} 1.177 + 1.178 +MFBT_API bool 1.179 +IsSignalHandlingBroken() 1.180 +{ 1.181 + return ElfLoader::Singleton.isSignalHandlingBroken(); 1.182 +} 1.183 + 1.184 +namespace { 1.185 + 1.186 +/** 1.187 + * Returns the part after the last '/' for the given path 1.188 + */ 1.189 +const char * 1.190 +LeafName(const char *path) 1.191 +{ 1.192 + const char *lastSlash = strrchr(path, '/'); 1.193 + if (lastSlash) 1.194 + return lastSlash + 1; 1.195 + return path; 1.196 +} 1.197 + 1.198 +} /* Anonymous namespace */ 1.199 + 1.200 +/** 1.201 + * LibHandle 1.202 + */ 1.203 +LibHandle::~LibHandle() 1.204 +{ 1.205 + free(path); 1.206 +} 1.207 + 1.208 +const char * 1.209 +LibHandle::GetName() const 1.210 +{ 1.211 + return path ? LeafName(path) : nullptr; 1.212 +} 1.213 + 1.214 +size_t 1.215 +LibHandle::GetMappableLength() const 1.216 +{ 1.217 + if (!mappable) 1.218 + mappable = GetMappable(); 1.219 + if (!mappable) 1.220 + return 0; 1.221 + return mappable->GetLength(); 1.222 +} 1.223 + 1.224 +void * 1.225 +LibHandle::MappableMMap(void *addr, size_t length, off_t offset) const 1.226 +{ 1.227 + if (!mappable) 1.228 + mappable = GetMappable(); 1.229 + if (!mappable) 1.230 + return MAP_FAILED; 1.231 + void* mapped = mappable->mmap(addr, length, PROT_READ, MAP_PRIVATE, offset); 1.232 + if (mapped != MAP_FAILED) { 1.233 + /* Ensure the availability of all pages within the mapping */ 1.234 + for (size_t off = 0; off < length; off += PageSize()) { 1.235 + mappable->ensure(reinterpret_cast<char *>(mapped) + off); 1.236 + } 1.237 + } 1.238 + return mapped; 1.239 +} 1.240 + 1.241 +void 1.242 +LibHandle::MappableMUnmap(void *addr, size_t length) const 1.243 +{ 1.244 + if (mappable) 1.245 + mappable->munmap(addr, length); 1.246 +} 1.247 + 1.248 +/** 1.249 + * SystemElf 1.250 + */ 1.251 +TemporaryRef<LibHandle> 1.252 +SystemElf::Load(const char *path, int flags) 1.253 +{ 1.254 + /* The Android linker returns a handle when the file name matches an 1.255 + * already loaded library, even when the full path doesn't exist */ 1.256 + if (path && path[0] == '/' && (access(path, F_OK) == -1)){ 1.257 + DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, (void *)nullptr); 1.258 + return nullptr; 1.259 + } 1.260 + 1.261 + void *handle = dlopen(path, flags); 1.262 + DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path, flags, handle); 1.263 + ElfLoader::Singleton.lastError = dlerror(); 1.264 + if (handle) { 1.265 + SystemElf *elf = new SystemElf(path, handle); 1.266 + ElfLoader::Singleton.Register(elf); 1.267 + return elf; 1.268 + } 1.269 + return nullptr; 1.270 +} 1.271 + 1.272 +SystemElf::~SystemElf() 1.273 +{ 1.274 + if (!dlhandle) 1.275 + return; 1.276 + DEBUG_LOG("dlclose(%p [\"%s\"])", dlhandle, GetPath()); 1.277 + dlclose(dlhandle); 1.278 + ElfLoader::Singleton.lastError = dlerror(); 1.279 + ElfLoader::Singleton.Forget(this); 1.280 +} 1.281 + 1.282 +void * 1.283 +SystemElf::GetSymbolPtr(const char *symbol) const 1.284 +{ 1.285 + void *sym = dlsym(dlhandle, symbol); 1.286 + DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle, GetPath(), symbol, sym); 1.287 + ElfLoader::Singleton.lastError = dlerror(); 1.288 + return sym; 1.289 +} 1.290 + 1.291 +Mappable * 1.292 +SystemElf::GetMappable() const 1.293 +{ 1.294 + const char *path = GetPath(); 1.295 + if (!path) 1.296 + return nullptr; 1.297 +#ifdef ANDROID 1.298 + /* On Android, if we don't have the full path, try in /system/lib */ 1.299 + const char *name = LeafName(path); 1.300 + std::string systemPath; 1.301 + if (name == path) { 1.302 + systemPath = "/system/lib/"; 1.303 + systemPath += path; 1.304 + path = systemPath.c_str(); 1.305 + } 1.306 +#endif 1.307 + 1.308 + return MappableFile::Create(path); 1.309 +} 1.310 + 1.311 +#ifdef __ARM_EABI__ 1.312 +const void * 1.313 +SystemElf::FindExidx(int *pcount) const 1.314 +{ 1.315 + /* TODO: properly implement when ElfLoader::GetHandleByPtr 1.316 + does return SystemElf handles */ 1.317 + *pcount = 0; 1.318 + return nullptr; 1.319 +} 1.320 +#endif 1.321 + 1.322 +/** 1.323 + * ElfLoader 1.324 + */ 1.325 + 1.326 +/* Unique ElfLoader instance */ 1.327 +ElfLoader ElfLoader::Singleton; 1.328 + 1.329 +TemporaryRef<LibHandle> 1.330 +ElfLoader::Load(const char *path, int flags, LibHandle *parent) 1.331 +{ 1.332 + /* Ensure logging is initialized or refresh if environment changed. */ 1.333 + Logging::Init(); 1.334 + 1.335 + RefPtr<LibHandle> handle; 1.336 + 1.337 + /* Handle dlopen(nullptr) directly. */ 1.338 + if (!path) { 1.339 + handle = SystemElf::Load(nullptr, flags); 1.340 + return handle; 1.341 + } 1.342 + 1.343 + /* TODO: Handle relative paths correctly */ 1.344 + const char *name = LeafName(path); 1.345 + 1.346 + /* Search the list of handles we already have for a match. When the given 1.347 + * path is not absolute, compare file names, otherwise compare full paths. */ 1.348 + if (name == path) { 1.349 + for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) 1.350 + if ((*it)->GetName() && (strcmp((*it)->GetName(), name) == 0)) 1.351 + return *it; 1.352 + } else { 1.353 + for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) 1.354 + if ((*it)->GetPath() && (strcmp((*it)->GetPath(), path) == 0)) 1.355 + return *it; 1.356 + } 1.357 + 1.358 + char *abs_path = nullptr; 1.359 + const char *requested_path = path; 1.360 + 1.361 + /* When the path is not absolute and the library is being loaded for 1.362 + * another, first try to load the library from the directory containing 1.363 + * that parent library. */ 1.364 + if ((name == path) && parent) { 1.365 + const char *parentPath = parent->GetPath(); 1.366 + abs_path = new char[strlen(parentPath) + strlen(path)]; 1.367 + strcpy(abs_path, parentPath); 1.368 + char *slash = strrchr(abs_path, '/'); 1.369 + strcpy(slash + 1, path); 1.370 + path = abs_path; 1.371 + } 1.372 + 1.373 + Mappable *mappable = GetMappableFromPath(path); 1.374 + 1.375 + /* Try loading with the custom linker if we have a Mappable */ 1.376 + if (mappable) 1.377 + handle = CustomElf::Load(mappable, path, flags); 1.378 + 1.379 + /* Try loading with the system linker if everything above failed */ 1.380 + if (!handle) 1.381 + handle = SystemElf::Load(path, flags); 1.382 + 1.383 + /* If we didn't have an absolute path and haven't been able to load 1.384 + * a library yet, try in the system search path */ 1.385 + if (!handle && abs_path) 1.386 + handle = SystemElf::Load(name, flags); 1.387 + 1.388 + delete [] abs_path; 1.389 + DEBUG_LOG("ElfLoader::Load(\"%s\", 0x%x, %p [\"%s\"]) = %p", requested_path, flags, 1.390 + reinterpret_cast<void *>(parent), parent ? parent->GetPath() : "", 1.391 + static_cast<void *>(handle)); 1.392 + 1.393 + return handle; 1.394 +} 1.395 + 1.396 +mozilla::TemporaryRef<LibHandle> 1.397 +ElfLoader::GetHandleByPtr(void *addr) 1.398 +{ 1.399 + /* Scan the list of handles we already have for a match */ 1.400 + for (LibHandleList::iterator it = handles.begin(); it < handles.end(); ++it) { 1.401 + if ((*it)->Contains(addr)) 1.402 + return *it; 1.403 + } 1.404 + return nullptr; 1.405 +} 1.406 + 1.407 +Mappable * 1.408 +ElfLoader::GetMappableFromPath(const char *path) 1.409 +{ 1.410 + const char *name = LeafName(path); 1.411 + Mappable *mappable = nullptr; 1.412 + RefPtr<Zip> zip; 1.413 + const char *subpath; 1.414 + if ((subpath = strchr(path, '!'))) { 1.415 + char *zip_path = strndup(path, subpath - path); 1.416 + while (*(++subpath) == '/') { } 1.417 + zip = ZipCollection::GetZip(zip_path); 1.418 + Zip::Stream s; 1.419 + if (zip && zip->GetStream(subpath, &s)) { 1.420 + /* When the MOZ_LINKER_EXTRACT environment variable is set to "1", 1.421 + * compressed libraries are going to be (temporarily) extracted as 1.422 + * files, in the directory pointed by the MOZ_LINKER_CACHE 1.423 + * environment variable. */ 1.424 + const char *extract = getenv("MOZ_LINKER_EXTRACT"); 1.425 + if (extract && !strncmp(extract, "1", 2 /* Including '\0' */)) 1.426 + mappable = MappableExtractFile::Create(name, zip, &s); 1.427 + if (!mappable) { 1.428 + if (s.GetType() == Zip::Stream::DEFLATE) { 1.429 + mappable = MappableDeflate::Create(name, zip, &s); 1.430 + } else if (s.GetType() == Zip::Stream::STORE) { 1.431 + mappable = MappableSeekableZStream::Create(name, zip, &s); 1.432 + } 1.433 + } 1.434 + } 1.435 + } 1.436 + /* If we couldn't load above, try with a MappableFile */ 1.437 + if (!mappable && !zip) 1.438 + mappable = MappableFile::Create(path); 1.439 + 1.440 + return mappable; 1.441 +} 1.442 + 1.443 +void 1.444 +ElfLoader::Register(LibHandle *handle) 1.445 +{ 1.446 + handles.push_back(handle); 1.447 + if (dbg && !handle->IsSystemElf()) 1.448 + dbg.Add(static_cast<CustomElf *>(handle)); 1.449 +} 1.450 + 1.451 +void 1.452 +ElfLoader::Forget(LibHandle *handle) 1.453 +{ 1.454 + /* Ensure logging is initialized or refresh if environment changed. */ 1.455 + Logging::Init(); 1.456 + 1.457 + LibHandleList::iterator it = std::find(handles.begin(), handles.end(), handle); 1.458 + if (it != handles.end()) { 1.459 + DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"])", reinterpret_cast<void *>(handle), 1.460 + handle->GetPath()); 1.461 + if (dbg && !handle->IsSystemElf()) 1.462 + dbg.Remove(static_cast<CustomElf *>(handle)); 1.463 + handles.erase(it); 1.464 + } else { 1.465 + DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found", 1.466 + reinterpret_cast<void *>(handle), handle->GetPath()); 1.467 + } 1.468 +} 1.469 + 1.470 +ElfLoader::~ElfLoader() 1.471 +{ 1.472 + LibHandleList list; 1.473 + /* Build up a list of all library handles with direct (external) references. 1.474 + * We actually skip system library handles because we want to keep at least 1.475 + * some of these open. Most notably, Mozilla codebase keeps a few libgnome 1.476 + * libraries deliberately open because of the mess that libORBit destruction 1.477 + * is. dlclose()ing these libraries actually leads to problems. */ 1.478 + for (LibHandleList::reverse_iterator it = handles.rbegin(); 1.479 + it < handles.rend(); ++it) { 1.480 + if ((*it)->DirectRefCount()) { 1.481 + if ((*it)->IsSystemElf()) { 1.482 + static_cast<SystemElf *>(*it)->Forget(); 1.483 + } else { 1.484 + list.push_back(*it); 1.485 + } 1.486 + } 1.487 + } 1.488 + /* Force release all external references to the handles collected above */ 1.489 + for (LibHandleList::iterator it = list.begin(); it < list.end(); ++it) { 1.490 + while ((*it)->ReleaseDirectRef()) { } 1.491 + } 1.492 + /* Remove the remaining system handles. */ 1.493 + if (handles.size()) { 1.494 + list = handles; 1.495 + for (LibHandleList::reverse_iterator it = list.rbegin(); 1.496 + it < list.rend(); ++it) { 1.497 + if ((*it)->IsSystemElf()) { 1.498 + DEBUG_LOG("ElfLoader::~ElfLoader(): Remaining handle for \"%s\" " 1.499 + "[%d direct refs, %d refs total]", (*it)->GetPath(), 1.500 + (*it)->DirectRefCount(), (*it)->refCount()); 1.501 + } else { 1.502 + DEBUG_LOG("ElfLoader::~ElfLoader(): Unexpected remaining handle for \"%s\" " 1.503 + "[%d direct refs, %d refs total]", (*it)->GetPath(), 1.504 + (*it)->DirectRefCount(), (*it)->refCount()); 1.505 + /* Not removing, since it could have references to other libraries, 1.506 + * destroying them as a side effect, and possibly leaving dangling 1.507 + * pointers in the handle list we're scanning */ 1.508 + } 1.509 + } 1.510 + } 1.511 +} 1.512 + 1.513 +void 1.514 +ElfLoader::stats(const char *when) 1.515 +{ 1.516 + for (LibHandleList::iterator it = Singleton.handles.begin(); 1.517 + it < Singleton.handles.end(); ++it) 1.518 + if (!(*it)->IsSystemElf()) 1.519 + static_cast<CustomElf *>(*it)->stats(when); 1.520 +} 1.521 + 1.522 +#ifdef __ARM_EABI__ 1.523 +int 1.524 +ElfLoader::__wrap_aeabi_atexit(void *that, ElfLoader::Destructor destructor, 1.525 + void *dso_handle) 1.526 +{ 1.527 + Singleton.destructors.push_back( 1.528 + DestructorCaller(destructor, that, dso_handle)); 1.529 + return 0; 1.530 +} 1.531 +#else 1.532 +int 1.533 +ElfLoader::__wrap_cxa_atexit(ElfLoader::Destructor destructor, void *that, 1.534 + void *dso_handle) 1.535 +{ 1.536 + Singleton.destructors.push_back( 1.537 + DestructorCaller(destructor, that, dso_handle)); 1.538 + return 0; 1.539 +} 1.540 +#endif 1.541 + 1.542 +void 1.543 +ElfLoader::__wrap_cxa_finalize(void *dso_handle) 1.544 +{ 1.545 + /* Call all destructors for the given DSO handle in reverse order they were 1.546 + * registered. */ 1.547 + std::vector<DestructorCaller>::reverse_iterator it; 1.548 + for (it = Singleton.destructors.rbegin(); 1.549 + it < Singleton.destructors.rend(); ++it) { 1.550 + if (it->IsForHandle(dso_handle)) { 1.551 + it->Call(); 1.552 + } 1.553 + } 1.554 +} 1.555 + 1.556 +void 1.557 +ElfLoader::DestructorCaller::Call() 1.558 +{ 1.559 + if (destructor) { 1.560 + DEBUG_LOG("ElfLoader::DestructorCaller::Call(%p, %p, %p)", 1.561 + FunctionPtr(destructor), object, dso_handle); 1.562 + destructor(object); 1.563 + destructor = nullptr; 1.564 + } 1.565 +} 1.566 + 1.567 +ElfLoader::DebuggerHelper::DebuggerHelper(): dbg(nullptr) 1.568 +{ 1.569 + /* Find ELF auxiliary vectors. 1.570 + * 1.571 + * The kernel stores the following data on the stack when starting a 1.572 + * program: 1.573 + * argc 1.574 + * argv[0] (pointer into argv strings defined below) 1.575 + * argv[1] (likewise) 1.576 + * ... 1.577 + * argv[argc - 1] (likewise) 1.578 + * nullptr 1.579 + * envp[0] (pointer into environment strings defined below) 1.580 + * envp[1] (likewise) 1.581 + * ... 1.582 + * envp[n] (likewise) 1.583 + * nullptr 1.584 + * ... (more NULLs on some platforms such as Android 4.3) 1.585 + * auxv[0] (first ELF auxiliary vector) 1.586 + * auxv[1] (second ELF auxiliary vector) 1.587 + * ... 1.588 + * auxv[p] (last ELF auxiliary vector) 1.589 + * (AT_NULL, nullptr) 1.590 + * padding 1.591 + * argv strings, separated with '\0' 1.592 + * environment strings, separated with '\0' 1.593 + * nullptr 1.594 + * 1.595 + * What we are after are the auxv values defined by the following struct. 1.596 + */ 1.597 + struct AuxVector { 1.598 + Elf::Addr type; 1.599 + Elf::Addr value; 1.600 + }; 1.601 + 1.602 + /* Pointer to the environment variables list */ 1.603 + extern char **environ; 1.604 + 1.605 + /* The environment may have changed since the program started, in which 1.606 + * case the environ variables list isn't the list the kernel put on stack 1.607 + * anymore. But in this new list, variables that didn't change still point 1.608 + * to the strings the kernel put on stack. It is quite unlikely that two 1.609 + * modified environment variables point to two consecutive strings in memory, 1.610 + * so we assume that if two consecutive environment variables point to two 1.611 + * consecutive strings, we found strings the kernel put on stack. */ 1.612 + char **env; 1.613 + for (env = environ; *env; env++) 1.614 + if (*env + strlen(*env) + 1 == env[1]) 1.615 + break; 1.616 + if (!*env) 1.617 + return; 1.618 + 1.619 + /* Next, we scan the stack backwards to find a pointer to one of those 1.620 + * strings we found above, which will give us the location of the original 1.621 + * envp list. As we are looking for pointers, we need to look at 32-bits or 1.622 + * 64-bits aligned values, depening on the architecture. */ 1.623 + char **scan = reinterpret_cast<char **>( 1.624 + reinterpret_cast<uintptr_t>(*env) & ~(sizeof(void *) - 1)); 1.625 + while (*env != *scan) 1.626 + scan--; 1.627 + 1.628 + /* Finally, scan forward to find the last environment variable pointer and 1.629 + * thus the first auxiliary vector. */ 1.630 + while (*scan++); 1.631 + 1.632 + /* Some platforms have more NULLs here, so skip them if we encounter them */ 1.633 + while (!*scan) 1.634 + scan++; 1.635 + 1.636 + AuxVector *auxv = reinterpret_cast<AuxVector *>(scan); 1.637 + 1.638 + /* The two values of interest in the auxiliary vectors are AT_PHDR and 1.639 + * AT_PHNUM, which gives us the the location and size of the ELF program 1.640 + * headers. */ 1.641 + Array<Elf::Phdr> phdrs; 1.642 + char *base = nullptr; 1.643 + while (auxv->type) { 1.644 + if (auxv->type == AT_PHDR) { 1.645 + phdrs.Init(reinterpret_cast<Elf::Phdr*>(auxv->value)); 1.646 + /* Assume the base address is the first byte of the same page */ 1.647 + base = reinterpret_cast<char *>(PageAlignedPtr(auxv->value)); 1.648 + } 1.649 + if (auxv->type == AT_PHNUM) 1.650 + phdrs.Init(auxv->value); 1.651 + auxv++; 1.652 + } 1.653 + 1.654 + if (!phdrs) { 1.655 + DEBUG_LOG("Couldn't find program headers"); 1.656 + return; 1.657 + } 1.658 + 1.659 + /* In some cases, the address for the program headers we get from the 1.660 + * auxiliary vectors is not mapped, because of the PT_LOAD segments 1.661 + * definitions in the program executable. Trying to map anonymous memory 1.662 + * with a hint giving the base address will return a different address 1.663 + * if something is mapped there, and the base address otherwise. */ 1.664 + MappedPtr mem(MemoryRange::mmap(base, PageSize(), PROT_NONE, 1.665 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); 1.666 + if (mem == base) { 1.667 + /* If program headers aren't mapped, try to map them */ 1.668 + int fd = open("/proc/self/exe", O_RDONLY); 1.669 + if (fd == -1) { 1.670 + DEBUG_LOG("Failed to open /proc/self/exe"); 1.671 + return; 1.672 + } 1.673 + mem.Assign(MemoryRange::mmap(base, PageSize(), PROT_READ, MAP_PRIVATE, 1.674 + fd, 0)); 1.675 + /* If we don't manage to map at the right address, just give up. */ 1.676 + if (mem != base) { 1.677 + DEBUG_LOG("Couldn't read program headers"); 1.678 + return; 1.679 + } 1.680 + } 1.681 + /* Sanity check: the first bytes at the base address should be an ELF 1.682 + * header. */ 1.683 + if (!Elf::Ehdr::validate(base)) { 1.684 + DEBUG_LOG("Couldn't find program base"); 1.685 + return; 1.686 + } 1.687 + 1.688 + /* Search for the program PT_DYNAMIC segment */ 1.689 + Array<Elf::Dyn> dyns; 1.690 + for (Array<Elf::Phdr>::iterator phdr = phdrs.begin(); phdr < phdrs.end(); 1.691 + ++phdr) { 1.692 + /* While the program headers are expected within the first mapped page of 1.693 + * the program executable, the executable PT_LOADs may actually make them 1.694 + * loaded at an address that is not the wanted base address of the 1.695 + * library. We thus need to adjust the base address, compensating for the 1.696 + * virtual address of the PT_LOAD segment corresponding to offset 0. */ 1.697 + if (phdr->p_type == PT_LOAD && phdr->p_offset == 0) 1.698 + base -= phdr->p_vaddr; 1.699 + if (phdr->p_type == PT_DYNAMIC) 1.700 + dyns.Init(base + phdr->p_vaddr, phdr->p_filesz); 1.701 + } 1.702 + if (!dyns) { 1.703 + DEBUG_LOG("Failed to find PT_DYNAMIC section in program"); 1.704 + return; 1.705 + } 1.706 + 1.707 + /* Search for the DT_DEBUG information */ 1.708 + for (Array<Elf::Dyn>::iterator dyn = dyns.begin(); dyn < dyns.end(); ++dyn) { 1.709 + if (dyn->d_tag == DT_DEBUG) { 1.710 + dbg = reinterpret_cast<r_debug *>(dyn->d_un.d_ptr); 1.711 + break; 1.712 + } 1.713 + } 1.714 + DEBUG_LOG("DT_DEBUG points at %p", static_cast<void *>(dbg)); 1.715 +} 1.716 + 1.717 +/** 1.718 + * Helper class to ensure the given pointer is writable within the scope of 1.719 + * an instance. Permissions to the memory page where the pointer lies are 1.720 + * restored to their original value when the instance is destroyed. 1.721 + */ 1.722 +class EnsureWritable 1.723 +{ 1.724 +public: 1.725 + template <typename T> 1.726 + EnsureWritable(T *ptr, size_t length_ = sizeof(T)) 1.727 + { 1.728 + MOZ_ASSERT(length_ < PageSize()); 1.729 + prot = -1; 1.730 + page = MAP_FAILED; 1.731 + 1.732 + char *firstPage = PageAlignedPtr(reinterpret_cast<char *>(ptr)); 1.733 + char *lastPageEnd = PageAlignedEndPtr(reinterpret_cast<char *>(ptr) + length_); 1.734 + length = lastPageEnd - firstPage; 1.735 + uintptr_t start = reinterpret_cast<uintptr_t>(firstPage); 1.736 + uintptr_t end; 1.737 + 1.738 + prot = getProt(start, &end); 1.739 + if (prot == -1 || (start + length) > end) 1.740 + MOZ_CRASH(); 1.741 + 1.742 + if (prot & PROT_WRITE) 1.743 + return; 1.744 + 1.745 + page = firstPage; 1.746 + mprotect(page, length, prot | PROT_WRITE); 1.747 + } 1.748 + 1.749 + ~EnsureWritable() 1.750 + { 1.751 + if (page != MAP_FAILED) { 1.752 + mprotect(page, length, prot); 1.753 +} 1.754 + } 1.755 + 1.756 +private: 1.757 + int getProt(uintptr_t addr, uintptr_t *end) 1.758 + { 1.759 + /* The interesting part of the /proc/self/maps format looks like: 1.760 + * startAddr-endAddr rwxp */ 1.761 + int result = 0; 1.762 + AutoCloseFILE f(fopen("/proc/self/maps", "r")); 1.763 + while (f) { 1.764 + unsigned long long startAddr, endAddr; 1.765 + char perms[5]; 1.766 + if (fscanf(f, "%llx-%llx %4s %*1024[^\n] ", &startAddr, &endAddr, perms) != 3) 1.767 + return -1; 1.768 + if (addr < startAddr || addr >= endAddr) 1.769 + continue; 1.770 + if (perms[0] == 'r') 1.771 + result |= PROT_READ; 1.772 + else if (perms[0] != '-') 1.773 + return -1; 1.774 + if (perms[1] == 'w') 1.775 + result |= PROT_WRITE; 1.776 + else if (perms[1] != '-') 1.777 + return -1; 1.778 + if (perms[2] == 'x') 1.779 + result |= PROT_EXEC; 1.780 + else if (perms[2] != '-') 1.781 + return -1; 1.782 + *end = endAddr; 1.783 + return result; 1.784 + } 1.785 + return -1; 1.786 + } 1.787 + 1.788 + int prot; 1.789 + void *page; 1.790 + size_t length; 1.791 +}; 1.792 + 1.793 +/** 1.794 + * The system linker maintains a doubly linked list of library it loads 1.795 + * for use by the debugger. Unfortunately, it also uses the list pointers 1.796 + * in a lot of operations and adding our data in the list is likely to 1.797 + * trigger crashes when the linker tries to use data we don't provide or 1.798 + * that fall off the amount data we allocated. Fortunately, the linker only 1.799 + * traverses the list forward and accesses the head of the list from a 1.800 + * private pointer instead of using the value in the r_debug structure. 1.801 + * This means we can safely add members at the beginning of the list. 1.802 + * Unfortunately, gdb checks the coherency of l_prev values, so we have 1.803 + * to adjust the l_prev value for the first element the system linker 1.804 + * knows about. Fortunately, it doesn't use l_prev, and the first element 1.805 + * is not ever going to be released before our elements, since it is the 1.806 + * program executable, so the system linker should not be changing 1.807 + * r_debug::r_map. 1.808 + */ 1.809 +void 1.810 +ElfLoader::DebuggerHelper::Add(ElfLoader::link_map *map) 1.811 +{ 1.812 + if (!dbg->r_brk) 1.813 + return; 1.814 + dbg->r_state = r_debug::RT_ADD; 1.815 + dbg->r_brk(); 1.816 + map->l_prev = nullptr; 1.817 + map->l_next = dbg->r_map; 1.818 + if (!firstAdded) { 1.819 + firstAdded = map; 1.820 + /* When adding a library for the first time, r_map points to data 1.821 + * handled by the system linker, and that data may be read-only */ 1.822 + EnsureWritable w(&dbg->r_map->l_prev); 1.823 + dbg->r_map->l_prev = map; 1.824 + } else 1.825 + dbg->r_map->l_prev = map; 1.826 + dbg->r_map = map; 1.827 + dbg->r_state = r_debug::RT_CONSISTENT; 1.828 + dbg->r_brk(); 1.829 +} 1.830 + 1.831 +void 1.832 +ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map *map) 1.833 +{ 1.834 + if (!dbg->r_brk) 1.835 + return; 1.836 + dbg->r_state = r_debug::RT_DELETE; 1.837 + dbg->r_brk(); 1.838 + if (dbg->r_map == map) 1.839 + dbg->r_map = map->l_next; 1.840 + else 1.841 + map->l_prev->l_next = map->l_next; 1.842 + if (map == firstAdded) { 1.843 + firstAdded = map->l_prev; 1.844 + /* When removing the first added library, its l_next is going to be 1.845 + * data handled by the system linker, and that data may be read-only */ 1.846 + EnsureWritable w(&map->l_next->l_prev); 1.847 + map->l_next->l_prev = map->l_prev; 1.848 + } else 1.849 + map->l_next->l_prev = map->l_prev; 1.850 + dbg->r_state = r_debug::RT_CONSISTENT; 1.851 + dbg->r_brk(); 1.852 +} 1.853 + 1.854 +#if defined(ANDROID) 1.855 +/* As some system libraries may be calling signal() or sigaction() to 1.856 + * set a SIGSEGV handler, effectively breaking MappableSeekableZStream, 1.857 + * or worse, restore our SIGSEGV handler with wrong flags (which using 1.858 + * signal() will do), we want to hook into the system's sigaction() to 1.859 + * replace it with our own wrapper instead, so that our handler is never 1.860 + * replaced. We used to only do that with libraries this linker loads, 1.861 + * but it turns out at least one system library does call signal() and 1.862 + * breaks us (libsc-a3xx.so on the Samsung Galaxy S4). 1.863 + * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction 1.864 + * under the hood, instead of calling the signal system call directly, 1.865 + * we only need to hook sigaction. This is true for both bionic and 1.866 + * glibc. 1.867 + */ 1.868 + 1.869 +/* libc's sigaction */ 1.870 +extern "C" int 1.871 +sigaction(int signum, const struct sigaction *act, 1.872 + struct sigaction *oldact); 1.873 + 1.874 +/* Simple reimplementation of sigaction. This is roughly equivalent 1.875 + * to the assembly that comes in bionic, but not quite equivalent to 1.876 + * glibc's implementation, so we only use this on Android. */ 1.877 +int 1.878 +sys_sigaction(int signum, const struct sigaction *act, 1.879 + struct sigaction *oldact) 1.880 +{ 1.881 + return syscall(__NR_sigaction, signum, act, oldact); 1.882 +} 1.883 + 1.884 +/* Replace the first instructions of the given function with a jump 1.885 + * to the given new function. */ 1.886 +template <typename T> 1.887 +static bool 1.888 +Divert(T func, T new_func) 1.889 +{ 1.890 + void *ptr = FunctionPtr(func); 1.891 + uintptr_t addr = reinterpret_cast<uintptr_t>(ptr); 1.892 + 1.893 +#if defined(__i386__) 1.894 + // A 32-bit jump is a 5 bytes instruction. 1.895 + EnsureWritable w(ptr, 5); 1.896 + *reinterpret_cast<unsigned char *>(addr) = 0xe9; // jmp 1.897 + *reinterpret_cast<intptr_t *>(addr + 1) = 1.898 + reinterpret_cast<uintptr_t>(new_func) - addr - 5; // target displacement 1.899 + return true; 1.900 +#elif defined(__arm__) 1.901 + const unsigned char trampoline[] = { 1.902 + // .thumb 1.903 + 0x46, 0x04, // nop 1.904 + 0x78, 0x47, // bx pc 1.905 + 0x46, 0x04, // nop 1.906 + // .arm 1.907 + 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4] 1.908 + // .word <new_func> 1.909 + }; 1.910 + const unsigned char *start; 1.911 + if (addr & 0x01) { 1.912 + /* Function is thumb, the actual address of the code is without the 1.913 + * least significant bit. */ 1.914 + addr--; 1.915 + /* The arm part of the trampoline needs to be 32-bit aligned */ 1.916 + if (addr & 0x02) 1.917 + start = trampoline; 1.918 + else 1.919 + start = trampoline + 2; 1.920 + } else { 1.921 + /* Function is arm, we only need the arm part of the trampoline */ 1.922 + start = trampoline + 6; 1.923 + } 1.924 + 1.925 + size_t len = sizeof(trampoline) - (start - trampoline); 1.926 + EnsureWritable w(reinterpret_cast<void *>(addr), len + sizeof(void *)); 1.927 + memcpy(reinterpret_cast<void *>(addr), start, len); 1.928 + *reinterpret_cast<void **>(addr + len) = FunctionPtr(new_func); 1.929 + cacheflush(addr, addr + len + sizeof(void *), 0); 1.930 + return true; 1.931 +#else 1.932 + return false; 1.933 +#endif 1.934 +} 1.935 +#else 1.936 +#define sys_sigaction sigaction 1.937 +template <typename T> 1.938 +static bool 1.939 +Divert(T func, T new_func) 1.940 +{ 1.941 + return false; 1.942 +} 1.943 +#endif 1.944 + 1.945 +namespace { 1.946 + 1.947 +/* Clock that only accounts for time spent in the current process. */ 1.948 +static uint64_t ProcessTimeStamp_Now() 1.949 +{ 1.950 + struct timespec ts; 1.951 + int rv = clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &ts); 1.952 + 1.953 + if (rv != 0) { 1.954 + return 0; 1.955 + } 1.956 + 1.957 + uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000; 1.958 + return baseNs + (uint64_t)ts.tv_nsec; 1.959 +} 1.960 + 1.961 +} 1.962 + 1.963 +/* Data structure used to pass data to the temporary signal handler, 1.964 + * as well as triggering a test crash. */ 1.965 +struct TmpData { 1.966 + volatile int crash_int; 1.967 + volatile uint64_t crash_timestamp; 1.968 +}; 1.969 + 1.970 +SEGVHandler::SEGVHandler() 1.971 +: registeredHandler(false), signalHandlingBroken(false) 1.972 +, signalHandlingSlow(false) 1.973 +{ 1.974 + /* Initialize oldStack.ss_flags to an invalid value when used to set 1.975 + * an alternative stack, meaning we haven't got information about the 1.976 + * original alternative stack and thus don't mean to restore it */ 1.977 + oldStack.ss_flags = SS_ONSTACK; 1.978 + if (!Divert(sigaction, __wrap_sigaction)) 1.979 + return; 1.980 + 1.981 + /* Get the current segfault signal handler. */ 1.982 + sys_sigaction(SIGSEGV, nullptr, &this->action); 1.983 + 1.984 + /* Some devices don't provide useful information to their SIGSEGV handlers, 1.985 + * making it impossible for on-demand decompression to work. To check if 1.986 + * we're on such a device, setup a temporary handler and deliberately 1.987 + * trigger a segfault. The handler will set signalHandlingBroken if the 1.988 + * provided information is bogus. 1.989 + * Some other devices have a kernel option enabled that makes SIGSEGV handler 1.990 + * have an overhead so high that it affects how on-demand decompression 1.991 + * performs. The handler will also set signalHandlingSlow if the triggered 1.992 + * SIGSEGV took too much time. */ 1.993 + struct sigaction action; 1.994 + action.sa_sigaction = &SEGVHandler::test_handler; 1.995 + sigemptyset(&action.sa_mask); 1.996 + action.sa_flags = SA_SIGINFO | SA_NODEFER; 1.997 + action.sa_restorer = nullptr; 1.998 + stackPtr.Assign(MemoryRange::mmap(nullptr, PageSize(), 1.999 + PROT_READ | PROT_WRITE, 1.1000 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); 1.1001 + if (stackPtr.get() == MAP_FAILED) 1.1002 + return; 1.1003 + if (sys_sigaction(SIGSEGV, &action, nullptr)) 1.1004 + return; 1.1005 + 1.1006 + TmpData *data = reinterpret_cast<TmpData*>(stackPtr.get()); 1.1007 + data->crash_timestamp = ProcessTimeStamp_Now(); 1.1008 + mprotect(stackPtr, stackPtr.GetLength(), PROT_NONE); 1.1009 + data->crash_int = 123; 1.1010 + /* Restore the original segfault signal handler. */ 1.1011 + sys_sigaction(SIGSEGV, &this->action, nullptr); 1.1012 + stackPtr.Assign(MAP_FAILED, 0); 1.1013 + if (signalHandlingBroken || signalHandlingSlow) 1.1014 + return; 1.1015 + 1.1016 + /* Setup an alternative stack if the already existing one is not big 1.1017 + * enough, or if there is none. */ 1.1018 + if (sigaltstack(nullptr, &oldStack) == 0) { 1.1019 + if (oldStack.ss_flags == SS_ONSTACK) 1.1020 + oldStack.ss_flags = 0; 1.1021 + if (!oldStack.ss_sp || oldStack.ss_size < stackSize) { 1.1022 + stackPtr.Assign(MemoryRange::mmap(nullptr, stackSize, 1.1023 + PROT_READ | PROT_WRITE, 1.1024 + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)); 1.1025 + if (stackPtr.get() == MAP_FAILED) 1.1026 + return; 1.1027 + stack_t stack; 1.1028 + stack.ss_sp = stackPtr; 1.1029 + stack.ss_size = stackSize; 1.1030 + stack.ss_flags = 0; 1.1031 + if (sigaltstack(&stack, nullptr) != 0) 1.1032 + return; 1.1033 + } 1.1034 + } 1.1035 + /* Register our own handler, and store the already registered one in 1.1036 + * SEGVHandler's struct sigaction member */ 1.1037 + action.sa_sigaction = &SEGVHandler::handler; 1.1038 + action.sa_flags = SA_SIGINFO | SA_NODEFER | SA_ONSTACK; 1.1039 + registeredHandler = !sys_sigaction(SIGSEGV, &action, nullptr); 1.1040 +} 1.1041 + 1.1042 +SEGVHandler::~SEGVHandler() 1.1043 +{ 1.1044 + /* Restore alternative stack for signals */ 1.1045 + if (oldStack.ss_flags != SS_ONSTACK) 1.1046 + sigaltstack(&oldStack, nullptr); 1.1047 + /* Restore original signal handler */ 1.1048 + if (registeredHandler) 1.1049 + sys_sigaction(SIGSEGV, &this->action, nullptr); 1.1050 +} 1.1051 + 1.1052 +/* Test handler for a deliberately triggered SIGSEGV that determines whether 1.1053 + * useful information is provided to signal handlers, particularly whether 1.1054 + * si_addr is filled in properly, and whether the segfault handler is called 1.1055 + * quickly enough. */ 1.1056 +void SEGVHandler::test_handler(int signum, siginfo_t *info, void *context) 1.1057 +{ 1.1058 + SEGVHandler &that = ElfLoader::Singleton; 1.1059 + if (signum != SIGSEGV || 1.1060 + info == nullptr || info->si_addr != that.stackPtr.get()) 1.1061 + that.signalHandlingBroken = true; 1.1062 + mprotect(that.stackPtr, that.stackPtr.GetLength(), PROT_READ | PROT_WRITE); 1.1063 + TmpData *data = reinterpret_cast<TmpData*>(that.stackPtr.get()); 1.1064 + uint64_t latency = ProcessTimeStamp_Now() - data->crash_timestamp; 1.1065 + DEBUG_LOG("SEGVHandler latency: %" PRIu64, latency); 1.1066 + /* See bug 886736 for timings on different devices, 150 µs is reasonably above 1.1067 + * the latency on "working" devices and seems to be reasonably fast to incur 1.1068 + * a huge overhead to on-demand decompression. */ 1.1069 + if (latency > 150000) 1.1070 + that.signalHandlingSlow = true; 1.1071 +} 1.1072 + 1.1073 +/* TODO: "properly" handle signal masks and flags */ 1.1074 +void SEGVHandler::handler(int signum, siginfo_t *info, void *context) 1.1075 +{ 1.1076 + //ASSERT(signum == SIGSEGV); 1.1077 + DEBUG_LOG("Caught segmentation fault @%p", info->si_addr); 1.1078 + 1.1079 + /* Check whether we segfaulted in the address space of a CustomElf. We're 1.1080 + * only expecting that to happen as an access error. */ 1.1081 + if (info->si_code == SEGV_ACCERR) { 1.1082 + mozilla::RefPtr<LibHandle> handle = 1.1083 + ElfLoader::Singleton.GetHandleByPtr(info->si_addr); 1.1084 + if (handle && !handle->IsSystemElf()) { 1.1085 + DEBUG_LOG("Within the address space of a CustomElf"); 1.1086 + CustomElf *elf = static_cast<CustomElf *>(static_cast<LibHandle *>(handle)); 1.1087 + if (elf->mappable->ensure(info->si_addr)) 1.1088 + return; 1.1089 + } 1.1090 + } 1.1091 + 1.1092 + /* Redispatch to the registered handler */ 1.1093 + SEGVHandler &that = ElfLoader::Singleton; 1.1094 + if (that.action.sa_flags & SA_SIGINFO) { 1.1095 + DEBUG_LOG("Redispatching to registered handler @%p", 1.1096 + FunctionPtr(that.action.sa_sigaction)); 1.1097 + that.action.sa_sigaction(signum, info, context); 1.1098 + } else if (that.action.sa_handler == SIG_DFL) { 1.1099 + DEBUG_LOG("Redispatching to default handler"); 1.1100 + /* Reset the handler to the default one, and trigger it. */ 1.1101 + sys_sigaction(signum, &that.action, nullptr); 1.1102 + raise(signum); 1.1103 + } else if (that.action.sa_handler != SIG_IGN) { 1.1104 + DEBUG_LOG("Redispatching to registered handler @%p", 1.1105 + FunctionPtr(that.action.sa_handler)); 1.1106 + that.action.sa_handler(signum); 1.1107 + } else { 1.1108 + DEBUG_LOG("Ignoring"); 1.1109 + } 1.1110 +} 1.1111 + 1.1112 +int 1.1113 +SEGVHandler::__wrap_sigaction(int signum, const struct sigaction *act, 1.1114 + struct sigaction *oldact) 1.1115 +{ 1.1116 + SEGVHandler &that = ElfLoader::Singleton; 1.1117 + 1.1118 + /* Use system sigaction() function for all but SIGSEGV signals. */ 1.1119 + if (!that.registeredHandler || (signum != SIGSEGV)) 1.1120 + return sys_sigaction(signum, act, oldact); 1.1121 + 1.1122 + if (oldact) 1.1123 + *oldact = that.action; 1.1124 + if (act) 1.1125 + that.action = *act; 1.1126 + return 0; 1.1127 +} 1.1128 + 1.1129 +Logging Logging::Singleton;