Пример #1
0
/*
 * map_file_segment() -- map a [range of a] registered file segment.
 */
static int
map_file_segment(segment_t *segp)
{
    glctx_t *gcp = &glctx;

    char *memp;
    size_t size;
    int fd;
    int   flags = segp->seg_flags;

    if (!flags)
        flags = MAP_PRIVATE;	/* default */

    if ((fd = segp->seg_fd) == SEG_FD_NONE) {
        fprintf(stderr, "%s:  file %s not open\n",
                gcp->program_name, segp->seg_path);
        return SEG_ERR;
    }

    size = file_size(fd);

    /*
     * page align offset/length;  verify fit in file
     */
    segp->seg_offset = round_down_to_pagesize(segp->seg_offset);
    if (segp->seg_offset > size) {
        fprintf(stderr, "%s: offset 0x%lx beyond end of file %s\n",
                gcp->program_name, segp->seg_offset,
                segp->seg_path);
        return SEG_ERR;
    }

    if (segp->seg_length == 0)
        segp->seg_length = round_up_to_pagesize(size) -
                           segp->seg_offset;
    else
        segp->seg_length = round_up_to_pagesize(segp->seg_length);

    memp = (char *)mmap(0, segp->seg_length,
                        segp->seg_prot,
                        flags,
                        fd,
                        segp->seg_offset);

    if (memp == MAP_FAILED) {
        int err = errno;
        fprintf(stderr, "%s:  mmap of %s failed - %s\n",
                __FUNCTION__, segp->seg_path, strerror(err));
        return SEG_ERR;
    }

    vprint("%s:  mmap()ed file seg %s at 0x%lx-0x%lx\n",
           gcp->program_name, segp->seg_name,
           memp, memp+segp->seg_length-1);

    segp->seg_start = memp;

    return SEG_OK;
}
Пример #2
0
void *nacl_dyncode_alloc_fixed (void *dest, size_t code_size, size_t data_size,
                                size_t data_offset)
{
  /* TODO(eaeltsin): probably these alignment requirements are overly strict.
     If really so, support unaligned case.  */
  assert (dest == round_up_to_pagesize (dest));
  assert (data_offset == round_up_to_pagesize (data_offset));

  nacl_dyncode_alloc_init ();

  if (nacl_next_code > dest)
    {
      return NULL;
    }
  nacl_next_code = dest;

  code_size = round_up_to_pagesize (code_size);
  data_size = round_up_to_pagesize (data_size);

  if (data_size != 0)
    {
      size_t last_offset = nacl_next_data - nacl_next_code;
      if (data_offset > last_offset)
        {
          /* Leaves unused space in the data area. */
          nacl_next_data += data_offset - last_offset;
        }
      else if (data_offset < last_offset)
        {
          /* Cannot move code. */
          return NULL;
        }
      assert (nacl_next_code + data_offset == nacl_next_data);

      /* Check whether the data space is available and reserve it.
         MAP_FIXED cannot be used because it overwrites existing mappings.
         Instead, fail if returned value is different from address hint.  */
      void *mapped = __mmap (nacl_next_data, data_size, PROT_NONE,
                             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
      if (mapped == MAP_FAILED)
        {
          return NULL;
        }
      if (mapped != nacl_next_data)
        {
          __munmap (nacl_next_data, data_size);
          return NULL;
        }
    }

  nacl_next_data += data_size;
  nacl_next_code += code_size;
  return dest;
}
Пример #3
0
/* Allocate space for code and data simultaneously.
   This is a simple allocator that doesn't know how to deallocate.  */
void *nacl_dyncode_alloc (size_t code_size, size_t data_size,
                          size_t data_offset)
{
  assert (data_offset == round_up_to_pagesize (data_offset));

  nacl_dyncode_alloc_init ();

  code_size = round_up_to_pagesize (code_size);
  data_size = round_up_to_pagesize (data_size);

  if (data_size != 0)
    {
      size_t last_offset = nacl_next_data - nacl_next_code;
      if (data_offset > last_offset)
        {
          /* Leaves unused space in the data area. */
          nacl_next_data += data_offset - last_offset;
        }
      else if (data_offset < last_offset)
        {
          /* Leaves unused space in the code area. */
          nacl_next_code += last_offset - data_offset;
        }
      assert (nacl_next_code + data_offset == nacl_next_data);

      /* Check whether the data space is available and reserve it.
         MAP_FIXED cannot be used because it overwrites existing mappings.
         Instead, fail if returned value is different from address hint.
         TODO(mseaborn): Retry on failure or avoid failure by
         reserving a big chunk of address space at startup. */
      void *mapped = __mmap (nacl_next_data, data_size, PROT_NONE,
                             MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
      if (mapped == MAP_FAILED)
        {
          return NULL;
        }
      if (mapped != nacl_next_data)
        {
          __munmap (nacl_next_data, data_size);
          return NULL;
        }
    }

  void *code_addr = nacl_next_code;
  nacl_next_data += data_size;
  nacl_next_code += code_size;
  return code_addr;
}
Пример #4
0
/*
 * segment_mbind() - set memory policy for a range of specified segment
 *
 * NOTE:  offset is relative to start of mapping, not start of file
 */
int
segment_mbind(char *name, range_t * range, int policy,
	      nodemask_t * nodemask, int flags)
{
	glctx_t *gcp = &glctx;
	segment_t *segp;
	char *start;
	off_t offset;
	size_t length, maxlength;
	int ret;

	segp = segment_get(name);
	if (segp == NULL) {
		fprintf(stderr, "%s:  no such segment:  %s\n",
			gcp->program_name, name);
		return SEG_ERR;
	}

	if (segp->seg_start == MAP_FAILED) {
		fprintf(stderr, "%s:  segment %s not mapped\n",
			gcp->program_name, name);
		return SEG_ERR;
	}

	offset = round_down_to_pagesize(range->offset);
	if (offset >= segp->seg_length) {
		fprintf(stderr, "%s:  offset %ld is past end of segment %s\n",
			gcp->program_name, offset, name);
		return SEG_ERR;
	}

	start = segp->seg_start + offset;
	maxlength = segp->seg_length - offset;

	length = range->length;
	if (length)
		length = round_up_to_pagesize(length);

	/*
	 * note:  we silently truncate to max length [end of segment]
	 */
	if (length == 0 || length > maxlength)
		length = maxlength;

	ret = mbind(segp->seg_start + offset, length, policy, nodemask->n,
		    NUMA_NUM_NODES, flags);

	if (ret == -1) {
		int err = errno;
		fprintf(stderr, "%s:  mbind() of segment %s failed - %s\n",
			gcp->program_name, name, strerror(err));
		return SEG_ERR;
	}

	return SEG_OK;
}
Пример #5
0
/*
 * segment_register:  register an anon, file or shm segment based on args.
 *	for anon and shm, 'name' = segment name.
 *	for file, 'name' = path name; segment name = basename(path)
 *
 * returns: !0 on success; 0 on failure
 */
int
segment_register(seg_type_t type, char *name, range_t *range, int flags)
{
    glctx_t   *gcp = &glctx;
    segment_t *segp;
    char      *path;

    segp = segment_get(basename(name));	/* ensure unique name */
    if (segp != NULL) {
        fprintf(stderr, "%s:  segment %s already exists\n",
                gcp->program_name, segp->seg_name);
        return SEG_ERR;
    }

    segp = get_seg_slot();
    if (segp == NULL)
        return SEG_ERR;

    path = strdup(name);	/* save a copy */
    segp->seg_name   = strdup(basename(name));
    segp->seg_start  = MAP_FAILED;
    segp->seg_length = round_up_to_pagesize(range->length);
    segp->seg_offset = round_down_to_pagesize(range->offset);
    segp->seg_type   = type;
    segp->seg_flags  = flags;			/* possibly 0 */
    segp->seg_prot   = PROT_READ|PROT_WRITE;	/* default */
    segp->seg_fd     = SEG_FD_NONE;
    segp->seg_shmid  = SHM_ID_NONE;

    switch (type) {
    case SEGT_ANON:
        free(path);
        break;

    case SEGT_FILE:
        segp->seg_path = path;
        return open_file(segp);
        break;

    case SEGT_SHM:
        free(path);
        return get_shm_segment(segp);
        break;

    default:
        free(path);
    }
    return SEG_OK;
}
Пример #6
0
static void nacl_dyncode_alloc_init (void)
{
  extern char __etext[]; /* Defined by the linker script */

  if (nacl_next_code)
    {
      return;
    }

  /* Place data after whatever brk() heap has been allocated so far. This will
     mean the brk() heap cannot be extended any further.
     TODO(mseaborn): Ideally place ld.so and brk() heap at a high address so
     that library data can be mapped below and not get in the way of the brk()
     heap.  */
  nacl_next_code = __etext;
  nacl_next_data = (char *) round_up_to_pagesize((size_t) __sbrk(0));
}
Пример #7
0
/*
 * segment_touch() - "touch" [read or write] each page of specified range
 *                   -- from offset to offset+length -- to fault in or to
 *                   test protection.
 * NOTE:  offset is relative to start of mapping, not start of file!
 */
int
segment_touch(char *name, range_t *range, int rw)
{
    glctx_t       *gcp = &glctx;
    segment_t     *segp;
    off_t          offset;
    size_t         length, maxlength;
    unsigned long *memp;
    struct timeval t_start, t_end;

    segp = segment_get(name);
    if (segp == NULL) {
        fprintf(stderr, "%s:  no such segment:  %s\n",
                gcp->program_name, name);
        return SEG_ERR;
    }

    offset    = round_down_to_pagesize(range->offset);
    if (offset >= segp->seg_length) {
        fprintf(stderr, "%s:  offset %ld is past end of segment %s\n",
                gcp->program_name, offset, name);
        return SEG_ERR;
    }

    memp      = (unsigned long*)(segp->seg_start + offset);
    maxlength = segp->seg_length - offset;

    length = range->length;
    if (length)
        length = round_up_to_pagesize(length);

    /*
     * note:  we silently truncate to max length [end of segment]
     */
    if (length == 0 || length > maxlength)
        length = maxlength;

    gettimeofday(&t_start, NULL);
    touch_memory(rw, memp, length);
    gettimeofday(&t_end, NULL);
    printf("%s:  touched %d pages in %6.3f secs\n",
           gcp->program_name, length/gcp->pagesize,
           (float)(tv_diff_usec(&t_start, &t_end))/1000000.0);

    return SEG_OK;
}
Пример #8
0
int segment_location(char *name, range_t * range)
{
	glctx_t *gcp = &glctx;
	segment_t *segp;
	char *apage, *end;
	off_t offset;
	size_t length, maxlength;
	int pgid, i;
	bool need_nl;

	segp = segment_get(name);
	if (segp == NULL) {
		fprintf(stderr, "%s:  no such segment:  %s\n",
			gcp->program_name, name);
		return SEG_ERR;
	}

	if (segp->seg_start == MAP_FAILED) {
		fprintf(stderr, "%s:  segment %s not mapped\n",
			gcp->program_name, name);
		return SEG_ERR;
	}

	offset = round_down_to_pagesize(range->offset);
	if (offset >= segp->seg_length) {
		fprintf(stderr, "%s:  offset %ld is past end of segment %s\n",
			gcp->program_name, offset, name);
		return SEG_ERR;
	}

	apage = segp->seg_start + offset;
	maxlength = segp->seg_length - offset;

	length = range->length;
	if (length)
		length = round_up_to_pagesize(length);

	/*
	 * note:  we silently truncate to max length [end of segment]
	 */
	if (length == 0 || length > maxlength)
		length = maxlength;

	end = apage + length;
	pgid = offset / gcp->pagesize;

	show_one_segment(segp, false);	/* show mapping, no header */

	printf("page offset   ");
	for (i = 0; i < PG_PER_LINE; ++i)
		printf(" +%02d", i);
	printf("\n");
	if (pgid & PPL_MASK) {
		/*
		 * start partial line
		 */
		int pgid2 = pgid & ~PPL_MASK;
		printf("%12x: ", pgid2);
		while (pgid2 < pgid) {
			printf("    ");
			++pgid2;
		}
		need_nl = true;
	} else
		need_nl = false;

	for (; apage < end; apage += gcp->pagesize, ++pgid) {
		int node;

		node = get_node(apage);
		if (node < 0) {
			fprintf(stderr, "\n%s:  "
				"failed to get node for segment %s, offset 0x%x\n",
				gcp->program_name, name, SEG_OFFSET(segp,
								    apage));
			return SEG_ERR;
		}

		if ((pgid & PPL_MASK) == 0) {
			if (need_nl)
				printf("\n");
			printf("%12x: ", pgid);	/* start a new line */
			need_nl = true;
		}
		printf(" %3d", node);

		if (signalled(gcp)) {
			reset_signal();
			break;
		}
	}
	printf("\n");

	return SEG_OK;
}