blob: 9b8148b380b949070f636c8f88a46cfff94910ec [file] [log] [blame]
// NACL MOD TRACK "third_party/nacl-glibc/sysdeps/nacl/nacl_dyncode_map.c"
// NACL MOD BEGIN
// Copyright and #include lines.
// Copyright 2013 Google Inc. All Rights Reserved.
#include <sys/mman.h>
#include <irt_syscalls.h>
// Add declarations of __mmap, __munmap, and __nacl_dyncode_create.
void *__mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset);
int __munmap(void *addr, size_t length);
int __nacl_dyncode_create(void *dest, const void *src, size_t size);
// NACL MOD END
/* Dynamically load code from a file. One day NaCl might provide a
syscall that provides this functionality without needing to make a
copy of the code. offset and size do not need to be page-aligned. */
int nacl_dyncode_map (int fd, void *dest, size_t offset, size_t size)
{
size_t alignment_padding = offset & (getpagesize() - 1);
uint8_t *mapping;
if (alignment_padding == 0 && (size & (getpagesize() - 1)) == 0) {
/* First try mmap using PROT_EXEC directly. */
mapping = __mmap(dest, size, PROT_READ | PROT_EXEC,
MAP_PRIVATE | MAP_FIXED, fd, offset);
if (mapping == dest) {
return 0;
} else if (mapping != MAP_FAILED) {
/* Mapped to an unexpected location. Unmap and fall back. */
__munmap(mapping, size);
}
}
mapping = __mmap (NULL, size + alignment_padding,
PROT_READ, MAP_PRIVATE, fd,
offset - alignment_padding);
if (mapping == MAP_FAILED)
return -1;
// NACL MOD BEGIN
// |dest| is aligned for us, and debugging code.
int result = __nacl_dyncode_create((char *)dest + alignment_padding,
mapping + alignment_padding, size);
// We do not support valgrind for now.
// TODO(crbug.com/243244): Figure out if we can/should support this.
#if 0
/* Tell Valgrind about this mapping. */
__nacl_dyncode_map_for_valgrind(dest, size, offset, mapping);
#endif
// NACL MOD END
int munmap_result = __munmap (mapping, size);
if (result != 0 || munmap_result != 0)
return -1;
return 0;
}