summaryrefslogtreecommitdiff
path: root/sysdeps/nacl/dl-map-segments.h
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/nacl/dl-map-segments.h')
-rw-r--r--sysdeps/nacl/dl-map-segments.h30
1 files changed, 28 insertions, 2 deletions
diff --git a/sysdeps/nacl/dl-map-segments.h b/sysdeps/nacl/dl-map-segments.h
index f305da304a..ec3eff8a60 100644
--- a/sysdeps/nacl/dl-map-segments.h
+++ b/sysdeps/nacl/dl-map-segments.h
@@ -1,5 +1,5 @@
/* Map in a shared object's segments. NaCl version.
- Copyright (C) 2015 Free Software Foundation, Inc.
+ Copyright (C) 2015-2016 Free Software Foundation, Inc.
This file is part of the GNU C Library.
The GNU C Library is free software; you can redistribute it and/or
@@ -53,7 +53,7 @@ _dl_map_segments (struct link_map *l, int fd,
const size_t maplength, bool has_holes,
struct link_map *loader)
{
- if (__builtin_expect (type, ET_DYN) == ET_DYN)
+ if (__glibc_likely (type == ET_DYN))
{
/* This is a position-independent shared object. Let the system
choose where to place it.
@@ -165,6 +165,32 @@ _dl_map_segments (struct link_map *l, int fd,
errno = error;
return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
}
+ if (__glibc_unlikely (type != ET_DYN))
+ {
+ /* A successful PROT_EXEC mmap would have implicitly
+ updated the bookkeeping so that a future
+ allocate_code_data call would know that this range
+ of the address space is already occupied. That
+ doesn't happen implicitly with dyncode_create, so
+ it's necessary to do an explicit call to update the
+ bookkeeping. */
+ uintptr_t allocated_address;
+ error = __nacl_irt_code_data_alloc.allocate_code_data
+ (l->l_addr + c->mapstart, len, 0, 0, &allocated_address);
+ if (__glibc_unlikely (error))
+ {
+ errno = error;
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+ }
+ if (__glibc_unlikely
+ (allocated_address != l->l_addr + c->mapstart))
+ {
+ /* This is not a very helpful error for this case,
+ but there isn't really anything better to use. */
+ errno = ENOMEM;
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+ }
+ }
}
else
{