libc: Add munmap support to plugin interface
With this patch, libc plugins become able to handle munmap for regions attached by the plugin.
This commit is contained in:
parent
3546b17827
commit
4914032800
|
@ -58,6 +58,7 @@ namespace Libc {
|
||||||
virtual bool supports_socket(int domain, int type, int protocol);
|
virtual bool supports_socket(int domain, int type, int protocol);
|
||||||
virtual bool supports_stat(const char *path);
|
virtual bool supports_stat(const char *path);
|
||||||
virtual bool supports_unlink(const char *path);
|
virtual bool supports_unlink(const char *path);
|
||||||
|
virtual bool supports_mmap();
|
||||||
|
|
||||||
virtual File_descriptor *accept(File_descriptor *,
|
virtual File_descriptor *accept(File_descriptor *,
|
||||||
struct ::sockaddr *addr,
|
struct ::sockaddr *addr,
|
||||||
|
@ -98,6 +99,7 @@ namespace Libc {
|
||||||
virtual int mkdir(const char *pathname, mode_t mode);
|
virtual int mkdir(const char *pathname, mode_t mode);
|
||||||
virtual void *mmap(void *addr, ::size_t length, int prot, int flags,
|
virtual void *mmap(void *addr, ::size_t length, int prot, int flags,
|
||||||
File_descriptor *, ::off_t offset);
|
File_descriptor *, ::off_t offset);
|
||||||
|
virtual int munmap(void *addr, ::size_t length);
|
||||||
virtual File_descriptor *open(const char *pathname, int flags);
|
virtual File_descriptor *open(const char *pathname, int flags);
|
||||||
virtual int pipe(File_descriptor *pipefd[2]);
|
virtual int pipe(File_descriptor *pipefd[2]);
|
||||||
virtual ssize_t read(File_descriptor *, void *buf, ::size_t count);
|
virtual ssize_t read(File_descriptor *, void *buf, ::size_t count);
|
||||||
|
|
|
@ -10,7 +10,7 @@ LIBS += timed_semaphore cxx
|
||||||
#
|
#
|
||||||
# Back end
|
# Back end
|
||||||
#
|
#
|
||||||
SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc readlink.cc munmap.cc \
|
SRC_CC = atexit.cc dummies.cc rlimit.cc sysctl.cc readlink.cc \
|
||||||
issetugid.cc errno.cc gai_strerror.cc clock_gettime.cc \
|
issetugid.cc errno.cc gai_strerror.cc clock_gettime.cc \
|
||||||
gettimeofday.cc malloc.cc progname.cc fd_alloc.cc file_operations.cc \
|
gettimeofday.cc malloc.cc progname.cc fd_alloc.cc file_operations.cc \
|
||||||
plugin.cc plugin_registry.cc select.cc exit.cc environ.cc nanosleep.cc \
|
plugin.cc plugin_registry.cc select.cc exit.cc environ.cc nanosleep.cc \
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
|
|
||||||
/* libc-internal includes */
|
/* libc-internal includes */
|
||||||
#include "libc_mem_alloc.h"
|
#include "libc_mem_alloc.h"
|
||||||
|
#include "libc_mmap_registry.h"
|
||||||
|
|
||||||
using namespace Libc;
|
using namespace Libc;
|
||||||
|
|
||||||
|
@ -43,6 +44,13 @@ using namespace Libc;
|
||||||
enum { INVALID_FD = -1 };
|
enum { INVALID_FD = -1 };
|
||||||
|
|
||||||
|
|
||||||
|
Libc::Mmap_registry *Libc::mmap_registry()
|
||||||
|
{
|
||||||
|
static Libc::Mmap_registry registry;
|
||||||
|
return ®istry;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
** Utilities **
|
** Utilities **
|
||||||
***************/
|
***************/
|
||||||
|
@ -295,17 +303,48 @@ extern "C" void *mmap(void *addr, ::size_t length, int prot, int flags,
|
||||||
int libc_fd, ::off_t offset)
|
int libc_fd, ::off_t offset)
|
||||||
{
|
{
|
||||||
/* handle requests for anonymous memory */
|
/* handle requests for anonymous memory */
|
||||||
if (!addr && libc_fd == -1)
|
if (!addr && libc_fd == -1) {
|
||||||
return Libc::mem_alloc()->alloc(length, PAGE_SHIFT);
|
PDBG("call Libc::mem_alloc()->alloc(%zd)", length);
|
||||||
|
void *start = Libc::mem_alloc()->alloc(length, PAGE_SHIFT);
|
||||||
|
mmap_registry()->insert(start, length, 0);
|
||||||
|
PDBG("return addr %p", start);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
/* lookup plugin responsible for file descriptor */
|
/* lookup plugin responsible for file descriptor */
|
||||||
File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap");
|
File_descriptor *fd = libc_fd_to_fd(libc_fd, "mmap");
|
||||||
if (!fd || !fd->plugin) {
|
if (!fd || !fd->plugin || !fd->plugin->supports_mmap()) {
|
||||||
PWRN("mmap not supported for file descriptor %d", libc_fd);
|
PWRN("mmap not supported for file descriptor %d", libc_fd);
|
||||||
return (void *)INVALID_FD;
|
return (void *)INVALID_FD;
|
||||||
}
|
}
|
||||||
|
|
||||||
return fd->plugin->mmap(addr, length, prot, flags, fd, offset);
|
void *start = fd->plugin->mmap(addr, length, prot, flags, fd, offset);
|
||||||
|
mmap_registry()->insert(start, length, fd->plugin);
|
||||||
|
return start;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" int munmap(void *start, size_t length)
|
||||||
|
{
|
||||||
|
if (!mmap_registry()->is_registered(start)) {
|
||||||
|
PWRN("munmap: could not lookup plugin for address %p", start);
|
||||||
|
errno = EINVAL;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Lookup plugin that was used for mmap
|
||||||
|
*
|
||||||
|
* If the pointer is NULL, 'start' refers to an anonymous mmap.
|
||||||
|
*/
|
||||||
|
Plugin *plugin = mmap_registry()->lookup_plugin_by_addr(start);
|
||||||
|
|
||||||
|
if (!plugin) {
|
||||||
|
Libc::mem_alloc()->free(start);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin->munmap(start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
/*
|
||||||
|
* \brief Registry for keeping track of mmapped regions
|
||||||
|
* \author Norman Feske
|
||||||
|
* \date 2012-08-16
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _LIBC_MMAP_REGISTRY_H_
|
||||||
|
#define _LIBC_MMAP_REGISTRY_H_
|
||||||
|
|
||||||
|
/* Genode includes */
|
||||||
|
#include <base/lock.h>
|
||||||
|
#include <base/env.h>
|
||||||
|
#include <base/printf.h>
|
||||||
|
|
||||||
|
/* libc-internal includes */
|
||||||
|
#include <libc-plugin/plugin.h>
|
||||||
|
|
||||||
|
/* libc includes */
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
namespace Libc {
|
||||||
|
|
||||||
|
class Mmap_registry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return singleton instance of mmap registry
|
||||||
|
*/
|
||||||
|
Mmap_registry *mmap_registry();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Libc::Mmap_registry
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
struct Entry : Genode::List<Entry>::Element
|
||||||
|
{
|
||||||
|
void * const start;
|
||||||
|
Plugin * const plugin;
|
||||||
|
|
||||||
|
Entry(void *start, Plugin *plugin)
|
||||||
|
: start(start), plugin(plugin) { }
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
Genode::List<Mmap_registry::Entry> _list;
|
||||||
|
|
||||||
|
Genode::Lock mutable _lock;
|
||||||
|
|
||||||
|
Entry *_lookup_by_addr_unsynchronized(void * const start) const
|
||||||
|
{
|
||||||
|
Entry *curr = _list.first();
|
||||||
|
|
||||||
|
for (; curr; curr = curr->next())
|
||||||
|
if (curr->start == start)
|
||||||
|
return curr;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
void insert(void *start, Genode::size_t len, Plugin *plugin)
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
|
||||||
|
if (_lookup_by_addr_unsynchronized(start)) {
|
||||||
|
PINF("mmap region at %p is already registered", start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_list.insert(new (Genode::env()->heap()) Entry(start, plugin));
|
||||||
|
}
|
||||||
|
|
||||||
|
Plugin *lookup_plugin_by_addr(void *start) const
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
|
||||||
|
Entry * const e = _lookup_by_addr_unsynchronized(start);
|
||||||
|
return e ? e->plugin : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool is_registered(void *start) const
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
|
||||||
|
return _lookup_by_addr_unsynchronized(start) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(void *start)
|
||||||
|
{
|
||||||
|
Genode::Lock::Guard guard(_lock);
|
||||||
|
|
||||||
|
Entry *e = _lookup_by_addr_unsynchronized(start);
|
||||||
|
|
||||||
|
if (!e) {
|
||||||
|
PWRN("lookup for address %p in in mmap registry failed", start);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_list.remove(e);
|
||||||
|
destroy(Genode::env()->heap(), e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* _LIBC_MMAP_REGISTRY_H_ */
|
|
@ -1,22 +0,0 @@
|
||||||
/*
|
|
||||||
* \brief C-library back end
|
|
||||||
* \author Norman Feske
|
|
||||||
* \date 2008-11-11
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Copyright (C) 2008-2012 Genode Labs GmbH
|
|
||||||
*
|
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
|
||||||
* under the terms of the GNU General Public License version 2.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <sys/mman.h>
|
|
||||||
|
|
||||||
#include "libc_debug.h"
|
|
||||||
|
|
||||||
extern "C" int munmap(void *start, size_t length)
|
|
||||||
{
|
|
||||||
raw_write_str("munmap called, not yet implemented!\n");
|
|
||||||
return 0;
|
|
||||||
}
|
|
|
@ -110,6 +110,13 @@ bool Plugin::supports_unlink(const char*)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Plugin::supports_mmap()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default implementations
|
* Default implementations
|
||||||
*/
|
*/
|
||||||
|
@ -181,6 +188,7 @@ DUMMY(int, -1, getaddrinfo, (const char *, const char *, const struct ::addrinf
|
||||||
DUMMY(int, -1, mkdir, (const char*, mode_t));
|
DUMMY(int, -1, mkdir, (const char*, mode_t));
|
||||||
DUMMY(void *, (void *)(-1), mmap, (void *addr, ::size_t length, int prot, int flags,
|
DUMMY(void *, (void *)(-1), mmap, (void *addr, ::size_t length, int prot, int flags,
|
||||||
File_descriptor *, ::off_t offset));
|
File_descriptor *, ::off_t offset));
|
||||||
|
DUMMY(int, -1, munmap, (void *, ::size_t));
|
||||||
DUMMY(int, -1, pipe, (File_descriptor*[2]));
|
DUMMY(int, -1, pipe, (File_descriptor*[2]));
|
||||||
DUMMY(int, -1, rename, (const char *, const char *));
|
DUMMY(int, -1, rename, (const char *, const char *));
|
||||||
DUMMY(int, -1, select, (int, fd_set *, fd_set *, fd_set *, struct timeval *));
|
DUMMY(int, -1, select, (int, fd_set *, fd_set *, fd_set *, struct timeval *));
|
||||||
|
|
Loading…
Reference in New Issue