Ejemplo n.º 1
0
// buf: buffer returned by mmap_file()
// size: same size as supplied to the mmap_file()
void unmap(void* buf, size_t size)
{
  assert(buf);
  uintptr_t end = page_ceil((uintptr_t)buf + size);
  uintptr_t start = page_floor((uintptr_t)buf);
  assert(end > (uintptr_t)buf);
  size_t len = end - start;
  if (munmap((void*)start, len) < 0)
      err(1, "munmap failed");
}
Ejemplo n.º 2
0
// mmap file content at given offset
// use unmap to release the mapping
void* mmap_file(int fd, off_t offset, size_t size)
{
    off_t offset_end = offset + size;
    assert(offset >= 0);
    assert(offset_end >= offset); // No overflow
    
    uintptr_t end = page_ceil(offset_end);
    uintptr_t start = page_floor(offset);

    uintptr_t len = end - start;
    void* buf = mmap(NULL, len, PROT_READ, MAP_SHARED, fd, start);
    
    if (buf == MAP_FAILED)
        err(1, "mmap failed");

    return ((void *)((uintptr_t)buf + (offset - start)));
}
Ejemplo n.º 3
0
void elflink_parse_load( elfinfo_t *elf, Elf32_Phdr *hdr )
{
	Elf32_Addr rstart, rend;
	Elf32_Addr fstart, fend, frend;
	Elf32_Addr caddr, cend, cmaddr;
	physaddr_t cphys, pstart, fphys, cdstart, cfstart, csz, psz;
	int flags;

	/* Determine base address */
	if ( elf->base == 0xFFFFFFFF ) {
		elf->base = page_floor( hdr->p_vaddr );
		elf->mbase = platldr_start_image( elf->id );
	}

	/* Setup page flags */
	flags = PAGE_FLAG_GLOBAL;
	
	if ( hdr->p_flags & PF_R )
		flags |= PAGE_PERM_R;
	if ( hdr->p_flags & PF_W )
		flags |= PAGE_PERM_W;
	if ( hdr->p_flags & PF_X )
		flags |= PAGE_PERM_X;

	//Note: Assume page size power of 2
	/* Calculate the page boundaries of the LOAD */
	rstart = page_floor( hdr->p_vaddr );
	rend = page_ceil( hdr->p_vaddr + hdr->p_memsz );
	
	fstart = hdr->p_vaddr;
	fend = hdr->p_vaddr + hdr->p_filesz;

	/* pstart contains the physical offset of the segment data */
	pstart = (physaddr_t) elf->pstart;
	pstart += page_floor(hdr->p_offset);

	/* Calculate the page boundary of the last filled page */
	frend = page_ceil(fend);
	
	/* Determine image end address */
	if ( rend > elf->end )
		elf->end = rend;

	/* Map all pages containing file data */
	for ( caddr = rstart; caddr < frend; caddr = cend ) {
		cend = caddr + ARCH_PAGE_SIZE;
		cmaddr = (caddr - elf->base) + elf->mbase;
		cphys = fphys = caddr - rstart + pstart;
		if ( caddr < fstart ) {
			/* This page does not fully contain the file */

			/* Allocate a fresh frame for this page */
			cphys = physmm_alloc_frame();

			/* Calculate the padding size */
			psz = fstart - caddr;

			/* Clear the padded start */
			memset( (void *) cphys, 0, psz );

			/* Calculate the offsets */
			cdstart = cphys + psz;
			cfstart = fphys	+ psz;
			csz = cend - fstart;

//			printf("Copy over: 0x%x to 0x%x\n", cfstart, cdstart );

			/* Copy in the data */
			memcpy( (void *) cdstart, (void *) cfstart, csz );
   
		} else if ( cend > fend ) {
			/* This page does not fully contain the file */

			/* Allocate a fresh frame for this page */
			cphys = physmm_alloc_frame();
			
			/* Calculate the padding size */
			psz = cend - fend;
		
			/* Calculate the data size and padding start */
			csz = fend - caddr;
			cdstart = cphys + csz;
	
			/* Clear the padded end */
			memset( (void *) cdstart, 0, psz );
//			printf("Copy over: 0x%x to 0x%x %x bytes\n", fphys, cphys,
//				csz);	
			/* Copy in the data */
			memcpy( (void *) cphys, (void *) fphys, csz );

		} /* If the page fully contains the file, map it */
//			else printf("Nocopy\n");
		platldr_map( elf->id, cmaddr, cphys, flags ); 

	}

	/* Map all pages which should not contain file data */
	for ( caddr = frend; caddr < rend; caddr = cend ) {
		cend = caddr + ARCH_PAGE_SIZE;
		cphys = physmm_alloc_frame();
		cmaddr = (caddr - elf->base) + elf->mbase;
		memset( (void *) cphys, 0, ARCH_PAGE_SIZE );
		platldr_map( elf->id, cmaddr, cphys, flags );
	}
	
	
}