1 /* This Source Code Form is subject to the terms of the Mozilla Public
2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
13 #include "ElfLoader.h"
14 #include "CustomElf.h"
20 #include <sys/syscall.h>
22 #include <android/api-level.h>
23 #if __ANDROID_API__ < 8
24 /* Android API < 8 doesn't provide sigaltstack */
28 inline int sigaltstack(const stack_t
*ss
, stack_t
*oss
) {
29 return syscall(__NR_sigaltstack
, ss
, oss
);
33 #endif /* __ANDROID_API__ */
37 extern "C" MOZ_EXPORT
const void *
38 __gnu_Unwind_Find_exidx(void *pc
, int *pcount
) __attribute__((weak
));
41 using namespace mozilla
;
44 * dlfcn.h replacements functions
48 __wrap_dlopen(const char *path
, int flags
)
50 RefPtr
<LibHandle
> handle
= ElfLoader::Singleton
.Load(path
, flags
);
52 handle
->AddDirectRef();
59 const char *error
= ElfLoader::Singleton
.lastError
;
60 ElfLoader::Singleton
.lastError
= nullptr;
65 __wrap_dlsym(void *handle
, const char *symbol
)
68 ElfLoader::Singleton
.lastError
= "dlsym(NULL, sym) unsupported";
71 if (handle
!= RTLD_DEFAULT
&& handle
!= RTLD_NEXT
) {
72 LibHandle
*h
= reinterpret_cast<LibHandle
*>(handle
);
73 return h
->GetSymbolPtr(symbol
);
75 return dlsym(handle
, symbol
);
79 __wrap_dlclose(void *handle
)
82 ElfLoader::Singleton
.lastError
= "No handle given to dlclose()";
85 reinterpret_cast<LibHandle
*>(handle
)->ReleaseDirectRef();
90 __wrap_dladdr(void *addr
, Dl_info
*info
)
92 RefPtr
<LibHandle
> handle
= ElfLoader::Singleton
.GetHandleByPtr(addr
);
95 info
->dli_fname
= handle
->GetPath();
100 __wrap_dl_iterate_phdr(dl_phdr_cb callback
, void *data
)
102 if (!ElfLoader::Singleton
.dbg
)
105 for (ElfLoader::DebuggerHelper::iterator it
= ElfLoader::Singleton
.dbg
.begin();
106 it
< ElfLoader::Singleton
.dbg
.end(); ++it
) {
108 info
.dlpi_addr
= reinterpret_cast<Elf::Addr
>(it
->l_addr
);
109 info
.dlpi_name
= it
->l_name
;
110 info
.dlpi_phdr
= nullptr;
113 // Assuming l_addr points to Elf headers (in most cases, this is true),
114 // get the Phdr location from there.
116 // If the page is not mapped, mincore returns an error.
117 if (!mincore(const_cast<void*>(it
->l_addr
), PageSize(), &mapped
)) {
118 const Elf::Ehdr
*ehdr
= Elf::Ehdr::validate(it
->l_addr
);
120 info
.dlpi_phdr
= reinterpret_cast<const Elf::Phdr
*>(
121 reinterpret_cast<const char *>(ehdr
) + ehdr
->e_phoff
);
122 info
.dlpi_phnum
= ehdr
->e_phnum
;
126 int ret
= callback(&info
, sizeof(dl_phdr_info
), data
);
135 __wrap___gnu_Unwind_Find_exidx(void *pc
, int *pcount
)
137 RefPtr
<LibHandle
> handle
= ElfLoader::Singleton
.GetHandleByPtr(pc
);
139 return handle
->FindExidx(pcount
);
140 if (__gnu_Unwind_Find_exidx
)
141 return __gnu_Unwind_Find_exidx(pc
, pcount
);
148 * faulty.lib public API
152 __dl_get_mappable_length(void *handle
) {
155 return reinterpret_cast<LibHandle
*>(handle
)->GetMappableLength();
159 __dl_mmap(void *handle
, void *addr
, size_t length
, off_t offset
)
163 return reinterpret_cast<LibHandle
*>(handle
)->MappableMMap(addr
, length
,
168 __dl_munmap(void *handle
, void *addr
, size_t length
)
172 return reinterpret_cast<LibHandle
*>(handle
)->MappableMUnmap(addr
, length
);
176 IsSignalHandlingBroken()
178 return ElfLoader::Singleton
.isSignalHandlingBroken();
184 * Returns the part after the last '/' for the given path
187 LeafName(const char *path
)
189 const char *lastSlash
= strrchr(path
, '/');
191 return lastSlash
+ 1;
195 } /* Anonymous namespace */
200 LibHandle::~LibHandle()
206 LibHandle::GetName() const
208 return path
? LeafName(path
) : nullptr;
212 LibHandle::GetMappableLength() const
215 mappable
= GetMappable();
218 return mappable
->GetLength();
222 LibHandle::MappableMMap(void *addr
, size_t length
, off_t offset
) const
225 mappable
= GetMappable();
228 void* mapped
= mappable
->mmap(addr
, length
, PROT_READ
, MAP_PRIVATE
, offset
);
229 if (mapped
!= MAP_FAILED
) {
230 /* Ensure the availability of all pages within the mapping */
231 for (size_t off
= 0; off
< length
; off
+= PageSize()) {
232 mappable
->ensure(reinterpret_cast<char *>(mapped
) + off
);
239 LibHandle::MappableMUnmap(void *addr
, size_t length
) const
242 mappable
->munmap(addr
, length
);
248 TemporaryRef
<LibHandle
>
249 SystemElf::Load(const char *path
, int flags
)
251 /* The Android linker returns a handle when the file name matches an
252 * already loaded library, even when the full path doesn't exist */
253 if (path
&& path
[0] == '/' && (access(path
, F_OK
) == -1)){
254 DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path
, flags
, (void *)nullptr);
258 void *handle
= dlopen(path
, flags
);
259 DEBUG_LOG("dlopen(\"%s\", 0x%x) = %p", path
, flags
, handle
);
260 ElfLoader::Singleton
.lastError
= dlerror();
262 SystemElf
*elf
= new SystemElf(path
, handle
);
263 ElfLoader::Singleton
.Register(elf
);
269 SystemElf::~SystemElf()
273 DEBUG_LOG("dlclose(%p [\"%s\"])", dlhandle
, GetPath());
275 ElfLoader::Singleton
.lastError
= dlerror();
276 ElfLoader::Singleton
.Forget(this);
280 SystemElf::GetSymbolPtr(const char *symbol
) const
282 void *sym
= dlsym(dlhandle
, symbol
);
283 DEBUG_LOG("dlsym(%p [\"%s\"], \"%s\") = %p", dlhandle
, GetPath(), symbol
, sym
);
284 ElfLoader::Singleton
.lastError
= dlerror();
289 SystemElf::GetMappable() const
291 const char *path
= GetPath();
295 /* On Android, if we don't have the full path, try in /system/lib */
296 const char *name
= LeafName(path
);
297 std::string systemPath
;
299 systemPath
= "/system/lib/";
301 path
= systemPath
.c_str();
305 return MappableFile::Create(path
);
310 SystemElf::FindExidx(int *pcount
) const
312 /* TODO: properly implement when ElfLoader::GetHandleByPtr
313 does return SystemElf handles */
323 /* Unique ElfLoader instance */
324 ElfLoader
ElfLoader::Singleton
;
326 TemporaryRef
<LibHandle
>
327 ElfLoader::Load(const char *path
, int flags
, LibHandle
*parent
)
329 /* Ensure logging is initialized or refresh if environment changed. */
332 RefPtr
<LibHandle
> handle
;
334 /* Handle dlopen(nullptr) directly. */
336 handle
= SystemElf::Load(nullptr, flags
);
340 /* TODO: Handle relative paths correctly */
341 const char *name
= LeafName(path
);
343 /* Search the list of handles we already have for a match. When the given
344 * path is not absolute, compare file names, otherwise compare full paths. */
346 for (LibHandleList::iterator it
= handles
.begin(); it
< handles
.end(); ++it
)
347 if ((*it
)->GetName() && (strcmp((*it
)->GetName(), name
) == 0))
350 for (LibHandleList::iterator it
= handles
.begin(); it
< handles
.end(); ++it
)
351 if ((*it
)->GetPath() && (strcmp((*it
)->GetPath(), path
) == 0))
355 char *abs_path
= nullptr;
356 const char *requested_path
= path
;
358 /* When the path is not absolute and the library is being loaded for
359 * another, first try to load the library from the directory containing
360 * that parent library. */
361 if ((name
== path
) && parent
) {
362 const char *parentPath
= parent
->GetPath();
363 abs_path
= new char[strlen(parentPath
) + strlen(path
)];
364 strcpy(abs_path
, parentPath
);
365 char *slash
= strrchr(abs_path
, '/');
366 strcpy(slash
+ 1, path
);
370 Mappable
*mappable
= GetMappableFromPath(path
);
372 /* Try loading with the custom linker if we have a Mappable */
374 handle
= CustomElf::Load(mappable
, path
, flags
);
376 /* Try loading with the system linker if everything above failed */
378 handle
= SystemElf::Load(path
, flags
);
380 /* If we didn't have an absolute path and haven't been able to load
381 * a library yet, try in the system search path */
382 if (!handle
&& abs_path
)
383 handle
= SystemElf::Load(name
, flags
);
386 DEBUG_LOG("ElfLoader::Load(\"%s\", 0x%x, %p [\"%s\"]) = %p", requested_path
, flags
,
387 reinterpret_cast<void *>(parent
), parent
? parent
->GetPath() : "",
388 static_cast<void *>(handle
));
393 mozilla::TemporaryRef
<LibHandle
>
394 ElfLoader::GetHandleByPtr(void *addr
)
396 /* Scan the list of handles we already have for a match */
397 for (LibHandleList::iterator it
= handles
.begin(); it
< handles
.end(); ++it
) {
398 if ((*it
)->Contains(addr
))
405 ElfLoader::GetMappableFromPath(const char *path
)
407 const char *name
= LeafName(path
);
408 Mappable
*mappable
= nullptr;
411 if ((subpath
= strchr(path
, '!'))) {
412 char *zip_path
= strndup(path
, subpath
- path
);
413 while (*(++subpath
) == '/') { }
414 zip
= ZipCollection::GetZip(zip_path
);
416 if (zip
&& zip
->GetStream(subpath
, &s
)) {
417 /* When the MOZ_LINKER_EXTRACT environment variable is set to "1",
418 * compressed libraries are going to be (temporarily) extracted as
419 * files, in the directory pointed by the MOZ_LINKER_CACHE
420 * environment variable. */
421 const char *extract
= getenv("MOZ_LINKER_EXTRACT");
422 if (extract
&& !strncmp(extract
, "1", 2 /* Including '\0' */))
423 mappable
= MappableExtractFile::Create(name
, zip
, &s
);
425 if (s
.GetType() == Zip::Stream::DEFLATE
) {
426 mappable
= MappableDeflate::Create(name
, zip
, &s
);
427 } else if (s
.GetType() == Zip::Stream::STORE
) {
428 mappable
= MappableSeekableZStream::Create(name
, zip
, &s
);
433 /* If we couldn't load above, try with a MappableFile */
434 if (!mappable
&& !zip
)
435 mappable
= MappableFile::Create(path
);
441 ElfLoader::Register(LibHandle
*handle
)
443 handles
.push_back(handle
);
444 if (dbg
&& !handle
->IsSystemElf())
445 dbg
.Add(static_cast<CustomElf
*>(handle
));
449 ElfLoader::Forget(LibHandle
*handle
)
451 /* Ensure logging is initialized or refresh if environment changed. */
454 LibHandleList::iterator it
= std::find(handles
.begin(), handles
.end(), handle
);
455 if (it
!= handles
.end()) {
456 DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"])", reinterpret_cast<void *>(handle
),
458 if (dbg
&& !handle
->IsSystemElf())
459 dbg
.Remove(static_cast<CustomElf
*>(handle
));
462 DEBUG_LOG("ElfLoader::Forget(%p [\"%s\"]): Handle not found",
463 reinterpret_cast<void *>(handle
), handle
->GetPath());
467 ElfLoader::~ElfLoader()
470 /* Build up a list of all library handles with direct (external) references.
471 * We actually skip system library handles because we want to keep at least
472 * some of these open. Most notably, Mozilla codebase keeps a few libgnome
473 * libraries deliberately open because of the mess that libORBit destruction
474 * is. dlclose()ing these libraries actually leads to problems. */
475 for (LibHandleList::reverse_iterator it
= handles
.rbegin();
476 it
< handles
.rend(); ++it
) {
477 if ((*it
)->DirectRefCount()) {
478 if ((*it
)->IsSystemElf()) {
479 static_cast<SystemElf
*>(*it
)->Forget();
485 /* Force release all external references to the handles collected above */
486 for (LibHandleList::iterator it
= list
.begin(); it
< list
.end(); ++it
) {
487 while ((*it
)->ReleaseDirectRef()) { }
489 /* Remove the remaining system handles. */
490 if (handles
.size()) {
492 for (LibHandleList::reverse_iterator it
= list
.rbegin();
493 it
< list
.rend(); ++it
) {
494 if ((*it
)->IsSystemElf()) {
495 DEBUG_LOG("ElfLoader::~ElfLoader(): Remaining handle for \"%s\" "
496 "[%d direct refs, %d refs total]", (*it
)->GetPath(),
497 (*it
)->DirectRefCount(), (*it
)->refCount());
499 DEBUG_LOG("ElfLoader::~ElfLoader(): Unexpected remaining handle for \"%s\" "
500 "[%d direct refs, %d refs total]", (*it
)->GetPath(),
501 (*it
)->DirectRefCount(), (*it
)->refCount());
502 /* Not removing, since it could have references to other libraries,
503 * destroying them as a side effect, and possibly leaving dangling
504 * pointers in the handle list we're scanning */
511 ElfLoader::stats(const char *when
)
513 for (LibHandleList::iterator it
= Singleton
.handles
.begin();
514 it
< Singleton
.handles
.end(); ++it
)
515 if (!(*it
)->IsSystemElf())
516 static_cast<CustomElf
*>(*it
)->stats(when
);
521 ElfLoader::__wrap_aeabi_atexit(void *that
, ElfLoader::Destructor destructor
,
524 Singleton
.destructors
.push_back(
525 DestructorCaller(destructor
, that
, dso_handle
));
530 ElfLoader::__wrap_cxa_atexit(ElfLoader::Destructor destructor
, void *that
,
533 Singleton
.destructors
.push_back(
534 DestructorCaller(destructor
, that
, dso_handle
));
540 ElfLoader::__wrap_cxa_finalize(void *dso_handle
)
542 /* Call all destructors for the given DSO handle in reverse order they were
544 std::vector
<DestructorCaller
>::reverse_iterator it
;
545 for (it
= Singleton
.destructors
.rbegin();
546 it
< Singleton
.destructors
.rend(); ++it
) {
547 if (it
->IsForHandle(dso_handle
)) {
554 ElfLoader::DestructorCaller::Call()
557 DEBUG_LOG("ElfLoader::DestructorCaller::Call(%p, %p, %p)",
558 FunctionPtr(destructor
), object
, dso_handle
);
560 destructor
= nullptr;
564 ElfLoader::DebuggerHelper::DebuggerHelper(): dbg(nullptr)
566 /* Find ELF auxiliary vectors.
568 * The kernel stores the following data on the stack when starting a
571 * argv[0] (pointer into argv strings defined below)
574 * argv[argc - 1] (likewise)
576 * envp[0] (pointer into environment strings defined below)
581 * ... (more NULLs on some platforms such as Android 4.3)
582 * auxv[0] (first ELF auxiliary vector)
583 * auxv[1] (second ELF auxiliary vector)
585 * auxv[p] (last ELF auxiliary vector)
588 * argv strings, separated with '\0'
589 * environment strings, separated with '\0'
592 * What we are after are the auxv values defined by the following struct.
599 /* Pointer to the environment variables list */
600 extern char **environ
;
602 /* The environment may have changed since the program started, in which
603 * case the environ variables list isn't the list the kernel put on stack
604 * anymore. But in this new list, variables that didn't change still point
605 * to the strings the kernel put on stack. It is quite unlikely that two
606 * modified environment variables point to two consecutive strings in memory,
607 * so we assume that if two consecutive environment variables point to two
608 * consecutive strings, we found strings the kernel put on stack. */
610 for (env
= environ
; *env
; env
++)
611 if (*env
+ strlen(*env
) + 1 == env
[1])
616 /* Next, we scan the stack backwards to find a pointer to one of those
617 * strings we found above, which will give us the location of the original
618 * envp list. As we are looking for pointers, we need to look at 32-bits or
619 * 64-bits aligned values, depening on the architecture. */
620 char **scan
= reinterpret_cast<char **>(
621 reinterpret_cast<uintptr_t>(*env
) & ~(sizeof(void *) - 1));
622 while (*env
!= *scan
)
625 /* Finally, scan forward to find the last environment variable pointer and
626 * thus the first auxiliary vector. */
629 /* Some platforms have more NULLs here, so skip them if we encounter them */
633 AuxVector
*auxv
= reinterpret_cast<AuxVector
*>(scan
);
635 /* The two values of interest in the auxiliary vectors are AT_PHDR and
636 * AT_PHNUM, which gives us the the location and size of the ELF program
638 Array
<Elf::Phdr
> phdrs
;
639 char *base
= nullptr;
641 if (auxv
->type
== AT_PHDR
) {
642 phdrs
.Init(reinterpret_cast<Elf::Phdr
*>(auxv
->value
));
643 /* Assume the base address is the first byte of the same page */
644 base
= reinterpret_cast<char *>(PageAlignedPtr(auxv
->value
));
646 if (auxv
->type
== AT_PHNUM
)
647 phdrs
.Init(auxv
->value
);
652 DEBUG_LOG("Couldn't find program headers");
656 /* In some cases, the address for the program headers we get from the
657 * auxiliary vectors is not mapped, because of the PT_LOAD segments
658 * definitions in the program executable. Trying to map anonymous memory
659 * with a hint giving the base address will return a different address
660 * if something is mapped there, and the base address otherwise. */
661 MappedPtr
mem(MemoryRange::mmap(base
, PageSize(), PROT_NONE
,
662 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0));
664 /* If program headers aren't mapped, try to map them */
665 int fd
= open("/proc/self/exe", O_RDONLY
);
667 DEBUG_LOG("Failed to open /proc/self/exe");
670 mem
.Assign(MemoryRange::mmap(base
, PageSize(), PROT_READ
, MAP_PRIVATE
,
672 /* If we don't manage to map at the right address, just give up. */
674 DEBUG_LOG("Couldn't read program headers");
678 /* Sanity check: the first bytes at the base address should be an ELF
680 if (!Elf::Ehdr::validate(base
)) {
681 DEBUG_LOG("Couldn't find program base");
685 /* Search for the program PT_DYNAMIC segment */
686 Array
<Elf::Dyn
> dyns
;
687 for (Array
<Elf::Phdr
>::iterator phdr
= phdrs
.begin(); phdr
< phdrs
.end();
689 /* While the program headers are expected within the first mapped page of
690 * the program executable, the executable PT_LOADs may actually make them
691 * loaded at an address that is not the wanted base address of the
692 * library. We thus need to adjust the base address, compensating for the
693 * virtual address of the PT_LOAD segment corresponding to offset 0. */
694 if (phdr
->p_type
== PT_LOAD
&& phdr
->p_offset
== 0)
695 base
-= phdr
->p_vaddr
;
696 if (phdr
->p_type
== PT_DYNAMIC
)
697 dyns
.Init(base
+ phdr
->p_vaddr
, phdr
->p_filesz
);
700 DEBUG_LOG("Failed to find PT_DYNAMIC section in program");
704 /* Search for the DT_DEBUG information */
705 for (Array
<Elf::Dyn
>::iterator dyn
= dyns
.begin(); dyn
< dyns
.end(); ++dyn
) {
706 if (dyn
->d_tag
== DT_DEBUG
) {
707 dbg
= reinterpret_cast<r_debug
*>(dyn
->d_un
.d_ptr
);
711 DEBUG_LOG("DT_DEBUG points at %p", static_cast<void *>(dbg
));
715 * Helper class to ensure the given pointer is writable within the scope of
716 * an instance. Permissions to the memory page where the pointer lies are
717 * restored to their original value when the instance is destroyed.
722 template <typename T
>
723 EnsureWritable(T
*ptr
, size_t length_
= sizeof(T
))
725 MOZ_ASSERT(length_
< PageSize());
729 char *firstPage
= PageAlignedPtr(reinterpret_cast<char *>(ptr
));
730 char *lastPageEnd
= PageAlignedEndPtr(reinterpret_cast<char *>(ptr
) + length_
);
731 length
= lastPageEnd
- firstPage
;
732 uintptr_t start
= reinterpret_cast<uintptr_t>(firstPage
);
735 prot
= getProt(start
, &end
);
736 if (prot
== -1 || (start
+ length
) > end
)
739 if (prot
& PROT_WRITE
)
743 mprotect(page
, length
, prot
| PROT_WRITE
);
748 if (page
!= MAP_FAILED
) {
749 mprotect(page
, length
, prot
);
754 int getProt(uintptr_t addr
, uintptr_t *end
)
756 /* The interesting part of the /proc/self/maps format looks like:
757 * startAddr-endAddr rwxp */
759 AutoCloseFILE
f(fopen("/proc/self/maps", "r"));
761 unsigned long long startAddr
, endAddr
;
763 if (fscanf(f
, "%llx-%llx %4s %*1024[^\n] ", &startAddr
, &endAddr
, perms
) != 3)
765 if (addr
< startAddr
|| addr
>= endAddr
)
769 else if (perms
[0] != '-')
772 result
|= PROT_WRITE
;
773 else if (perms
[1] != '-')
777 else if (perms
[2] != '-')
791 * The system linker maintains a doubly linked list of library it loads
792 * for use by the debugger. Unfortunately, it also uses the list pointers
793 * in a lot of operations and adding our data in the list is likely to
794 * trigger crashes when the linker tries to use data we don't provide or
795 * that fall off the amount data we allocated. Fortunately, the linker only
796 * traverses the list forward and accesses the head of the list from a
797 * private pointer instead of using the value in the r_debug structure.
798 * This means we can safely add members at the beginning of the list.
799 * Unfortunately, gdb checks the coherency of l_prev values, so we have
800 * to adjust the l_prev value for the first element the system linker
801 * knows about. Fortunately, it doesn't use l_prev, and the first element
802 * is not ever going to be released before our elements, since it is the
803 * program executable, so the system linker should not be changing
807 ElfLoader::DebuggerHelper::Add(ElfLoader::link_map
*map
)
811 dbg
->r_state
= r_debug::RT_ADD
;
813 map
->l_prev
= nullptr;
814 map
->l_next
= dbg
->r_map
;
817 /* When adding a library for the first time, r_map points to data
818 * handled by the system linker, and that data may be read-only */
819 EnsureWritable
w(&dbg
->r_map
->l_prev
);
820 dbg
->r_map
->l_prev
= map
;
822 dbg
->r_map
->l_prev
= map
;
824 dbg
->r_state
= r_debug::RT_CONSISTENT
;
829 ElfLoader::DebuggerHelper::Remove(ElfLoader::link_map
*map
)
833 dbg
->r_state
= r_debug::RT_DELETE
;
835 if (dbg
->r_map
== map
)
836 dbg
->r_map
= map
->l_next
;
838 map
->l_prev
->l_next
= map
->l_next
;
839 if (map
== firstAdded
) {
840 firstAdded
= map
->l_prev
;
841 /* When removing the first added library, its l_next is going to be
842 * data handled by the system linker, and that data may be read-only */
843 EnsureWritable
w(&map
->l_next
->l_prev
);
844 map
->l_next
->l_prev
= map
->l_prev
;
846 map
->l_next
->l_prev
= map
->l_prev
;
847 dbg
->r_state
= r_debug::RT_CONSISTENT
;
852 /* As some system libraries may be calling signal() or sigaction() to
853 * set a SIGSEGV handler, effectively breaking MappableSeekableZStream,
854 * or worse, restore our SIGSEGV handler with wrong flags (which using
855 * signal() will do), we want to hook into the system's sigaction() to
856 * replace it with our own wrapper instead, so that our handler is never
857 * replaced. We used to only do that with libraries this linker loads,
858 * but it turns out at least one system library does call signal() and
859 * breaks us (libsc-a3xx.so on the Samsung Galaxy S4).
860 * As libc's signal (bsd_signal/sysv_signal, really) calls sigaction
861 * under the hood, instead of calling the signal system call directly,
862 * we only need to hook sigaction. This is true for both bionic and
866 /* libc's sigaction */
868 sigaction(int signum
, const struct sigaction
*act
,
869 struct sigaction
*oldact
);
871 /* Simple reimplementation of sigaction. This is roughly equivalent
872 * to the assembly that comes in bionic, but not quite equivalent to
873 * glibc's implementation, so we only use this on Android. */
875 sys_sigaction(int signum
, const struct sigaction
*act
,
876 struct sigaction
*oldact
)
878 return syscall(__NR_sigaction
, signum
, act
, oldact
);
881 /* Replace the first instructions of the given function with a jump
882 * to the given new function. */
883 template <typename T
>
885 Divert(T func
, T new_func
)
887 void *ptr
= FunctionPtr(func
);
888 uintptr_t addr
= reinterpret_cast<uintptr_t>(ptr
);
890 #if defined(__i386__)
891 // A 32-bit jump is a 5 bytes instruction.
892 EnsureWritable
w(ptr
, 5);
893 *reinterpret_cast<unsigned char *>(addr
) = 0xe9; // jmp
894 *reinterpret_cast<intptr_t *>(addr
+ 1) =
895 reinterpret_cast<uintptr_t>(new_func
) - addr
- 5; // target displacement
897 #elif defined(__arm__)
898 const unsigned char trampoline
[] = {
904 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4]
907 const unsigned char *start
;
909 /* Function is thumb, the actual address of the code is without the
910 * least significant bit. */
912 /* The arm part of the trampoline needs to be 32-bit aligned */
916 start
= trampoline
+ 2;
918 /* Function is arm, we only need the arm part of the trampoline */
919 start
= trampoline
+ 6;
922 size_t len
= sizeof(trampoline
) - (start
- trampoline
);
923 EnsureWritable
w(reinterpret_cast<void *>(addr
), len
+ sizeof(void *));
924 memcpy(reinterpret_cast<void *>(addr
), start
, len
);
925 *reinterpret_cast<void **>(addr
+ len
) = FunctionPtr(new_func
);
926 cacheflush(addr
, addr
+ len
+ sizeof(void *), 0);
933 #define sys_sigaction sigaction
934 template <typename T
>
936 Divert(T func
, T new_func
)
944 /* Clock that only accounts for time spent in the current process. */
945 static uint64_t ProcessTimeStamp_Now()
948 int rv
= clock_gettime(CLOCK_PROCESS_CPUTIME_ID
, &ts
);
954 uint64_t baseNs
= (uint64_t)ts
.tv_sec
* 1000000000;
955 return baseNs
+ (uint64_t)ts
.tv_nsec
;
960 /* Data structure used to pass data to the temporary signal handler,
961 * as well as triggering a test crash. */
963 volatile int crash_int
;
964 volatile uint64_t crash_timestamp
;
967 SEGVHandler::SEGVHandler()
968 : initialized(false), registeredHandler(false), signalHandlingBroken(true)
969 , signalHandlingSlow(true)
971 /* Initialize oldStack.ss_flags to an invalid value when used to set
972 * an alternative stack, meaning we haven't got information about the
973 * original alternative stack and thus don't mean to restore it in
975 oldStack
.ss_flags
= SS_ONSTACK
;
977 /* Get the current segfault signal handler. */
978 struct sigaction old_action
;
979 sys_sigaction(SIGSEGV
, nullptr, &old_action
);
981 /* Some devices don't provide useful information to their SIGSEGV handlers,
982 * making it impossible for on-demand decompression to work. To check if
983 * we're on such a device, setup a temporary handler and deliberately
984 * trigger a segfault. The handler will set signalHandlingBroken if the
985 * provided information is bogus.
986 * Some other devices have a kernel option enabled that makes SIGSEGV handler
987 * have an overhead so high that it affects how on-demand decompression
988 * performs. The handler will also set signalHandlingSlow if the triggered
989 * SIGSEGV took too much time. */
990 struct sigaction action
;
991 action
.sa_sigaction
= &SEGVHandler::test_handler
;
992 sigemptyset(&action
.sa_mask
);
993 action
.sa_flags
= SA_SIGINFO
| SA_NODEFER
;
994 action
.sa_restorer
= nullptr;
995 stackPtr
.Assign(MemoryRange::mmap(nullptr, PageSize(),
996 PROT_READ
| PROT_WRITE
,
997 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0));
998 if (stackPtr
.get() == MAP_FAILED
)
1000 if (sys_sigaction(SIGSEGV
, &action
, nullptr))
1003 TmpData
*data
= reinterpret_cast<TmpData
*>(stackPtr
.get());
1004 data
->crash_timestamp
= ProcessTimeStamp_Now();
1005 mprotect(stackPtr
, stackPtr
.GetLength(), PROT_NONE
);
1006 data
->crash_int
= 123;
1007 /* Restore the original segfault signal handler. */
1008 sys_sigaction(SIGSEGV
, &old_action
, nullptr);
1009 stackPtr
.Assign(MAP_FAILED
, 0);
1013 SEGVHandler::FinishInitialization()
1015 /* Ideally, we'd need some locking here, but in practice, we're not
1016 * going to race with another thread. */
1019 if (signalHandlingBroken
|| signalHandlingSlow
)
1022 typedef int (*sigaction_func
)(int, const struct sigaction
*,
1023 struct sigaction
*);
1025 sigaction_func libc_sigaction
;
1027 #if defined(ANDROID)
1028 /* Android > 4.4 comes with a sigaction wrapper in a LD_PRELOADed library
1029 * (libsigchain) for ART. That wrapper kind of does the same trick as we
1030 * do, so we need extra care in handling it.
1031 * - Divert the libc's sigaction, assuming the LD_PRELOADed library uses
1032 * it under the hood (which is more or less true according to the source
1033 * of that library, since it's doing a lookup in RTLD_NEXT)
1034 * - With the LD_PRELOADed library in place, all calls to sigaction from
1035 * from system libraries will go to the LD_PRELOADed library.
1036 * - The LD_PRELOADed library calls to sigaction go to our __wrap_sigaction.
1037 * - The calls to sigaction from libraries faulty.lib loads are sent to
1038 * the LD_PRELOADed library.
1039 * In practice, for signal handling, this means:
1040 * - The signal handler registered to the kernel is ours.
1041 * - Our handler redispatches to the LD_PRELOADed library's if there's a
1042 * segfault we don't handle.
1043 * - The LD_PRELOADed library redispatches according to whatever system
1044 * library or faulty.lib-loaded library set with sigaction.
1046 * When there is no sigaction wrapper in place:
1047 * - Divert the libc's sigaction.
1048 * - Calls to sigaction from system library and faulty.lib-loaded libraries
1049 * all go to the libc's sigaction, which end up in our __wrap_sigaction.
1050 * - The signal handler registered to the kernel is ours.
1051 * - Our handler redispatches according to whatever system library or
1052 * faulty.lib-loaded library set with sigaction.
1054 void *libc
= dlopen("libc.so", RTLD_GLOBAL
| RTLD_LAZY
);
1057 reinterpret_cast<sigaction_func
>(dlsym(libc
, "sigaction"));
1061 libc_sigaction
= sigaction
;
1064 if (!Divert(libc_sigaction
, __wrap_sigaction
))
1067 /* Setup an alternative stack if the already existing one is not big
1068 * enough, or if there is none. */
1069 if (sigaltstack(nullptr, &oldStack
) == 0) {
1070 if (oldStack
.ss_flags
== SS_ONSTACK
)
1071 oldStack
.ss_flags
= 0;
1072 if (!oldStack
.ss_sp
|| oldStack
.ss_size
< stackSize
) {
1073 stackPtr
.Assign(MemoryRange::mmap(nullptr, stackSize
,
1074 PROT_READ
| PROT_WRITE
,
1075 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0));
1076 if (stackPtr
.get() == MAP_FAILED
)
1079 stack
.ss_sp
= stackPtr
;
1080 stack
.ss_size
= stackSize
;
1082 if (sigaltstack(&stack
, nullptr) != 0)
1086 /* Register our own handler, and store the already registered one in
1087 * SEGVHandler's struct sigaction member */
1088 action
.sa_sigaction
= &SEGVHandler::handler
;
1089 action
.sa_flags
= SA_SIGINFO
| SA_NODEFER
| SA_ONSTACK
;
1090 registeredHandler
= !sys_sigaction(SIGSEGV
, &action
, &this->action
);
1093 SEGVHandler::~SEGVHandler()
1095 /* Restore alternative stack for signals */
1096 if (oldStack
.ss_flags
!= SS_ONSTACK
)
1097 sigaltstack(&oldStack
, nullptr);
1098 /* Restore original signal handler */
1099 if (registeredHandler
)
1100 sys_sigaction(SIGSEGV
, &this->action
, nullptr);
1103 /* Test handler for a deliberately triggered SIGSEGV that determines whether
1104 * useful information is provided to signal handlers, particularly whether
1105 * si_addr is filled in properly, and whether the segfault handler is called
1106 * quickly enough. */
1107 void SEGVHandler::test_handler(int signum
, siginfo_t
*info
, void *context
)
1109 SEGVHandler
&that
= ElfLoader::Singleton
;
1110 if (signum
== SIGSEGV
&& info
&&
1111 info
->si_addr
== that
.stackPtr
.get())
1112 that
.signalHandlingBroken
= false;
1113 mprotect(that
.stackPtr
, that
.stackPtr
.GetLength(), PROT_READ
| PROT_WRITE
);
1114 TmpData
*data
= reinterpret_cast<TmpData
*>(that
.stackPtr
.get());
1115 uint64_t latency
= ProcessTimeStamp_Now() - data
->crash_timestamp
;
1116 DEBUG_LOG("SEGVHandler latency: %" PRIu64
, latency
);
1117 /* See bug 886736 for timings on different devices, 150 µs is reasonably above
1118 * the latency on "working" devices and seems to be short enough to not incur
1119 * a huge overhead to on-demand decompression. */
1120 if (latency
<= 150000)
1121 that
.signalHandlingSlow
= false;
1124 /* TODO: "properly" handle signal masks and flags */
1125 void SEGVHandler::handler(int signum
, siginfo_t
*info
, void *context
)
1127 //ASSERT(signum == SIGSEGV);
1128 DEBUG_LOG("Caught segmentation fault @%p", info
->si_addr
);
1130 /* Check whether we segfaulted in the address space of a CustomElf. We're
1131 * only expecting that to happen as an access error. */
1132 if (info
->si_code
== SEGV_ACCERR
) {
1133 mozilla::RefPtr
<LibHandle
> handle
=
1134 ElfLoader::Singleton
.GetHandleByPtr(info
->si_addr
);
1135 if (handle
&& !handle
->IsSystemElf()) {
1136 DEBUG_LOG("Within the address space of a CustomElf");
1137 CustomElf
*elf
= static_cast<CustomElf
*>(static_cast<LibHandle
*>(handle
));
1138 if (elf
->mappable
->ensure(info
->si_addr
))
1143 /* Redispatch to the registered handler */
1144 SEGVHandler
&that
= ElfLoader::Singleton
;
1145 if (that
.action
.sa_flags
& SA_SIGINFO
) {
1146 DEBUG_LOG("Redispatching to registered handler @%p",
1147 FunctionPtr(that
.action
.sa_sigaction
));
1148 that
.action
.sa_sigaction(signum
, info
, context
);
1149 } else if (that
.action
.sa_handler
== SIG_DFL
) {
1150 DEBUG_LOG("Redispatching to default handler");
1151 /* Reset the handler to the default one, and trigger it. */
1152 sys_sigaction(signum
, &that
.action
, nullptr);
1154 } else if (that
.action
.sa_handler
!= SIG_IGN
) {
1155 DEBUG_LOG("Redispatching to registered handler @%p",
1156 FunctionPtr(that
.action
.sa_handler
));
1157 that
.action
.sa_handler(signum
);
1159 DEBUG_LOG("Ignoring");
1164 SEGVHandler::__wrap_sigaction(int signum
, const struct sigaction
*act
,
1165 struct sigaction
*oldact
)
1167 SEGVHandler
&that
= ElfLoader::Singleton
;
1169 /* Use system sigaction() function for all but SIGSEGV signals. */
1170 if (!that
.registeredHandler
|| (signum
!= SIGSEGV
))
1171 return sys_sigaction(signum
, act
, oldact
);
1174 *oldact
= that
.action
;
1180 Logging
Logging::Singleton
;