binfmt: Remove PCODE dependency on apps/pcode.h

This commit is contained in:
Gregory Nutt
2016-06-30 11:25:59 -06:00
parent 7f296f9226
commit 378b22ec07
5 changed files with 170 additions and 82 deletions
+7 -7
View File
@@ -69,10 +69,10 @@ if BUILTIN
source binfmt/libbuiltin/Kconfig source binfmt/libbuiltin/Kconfig
endif endif
config PCODE config BINFMT_PCODE
bool "Support P-Code Applications" bool "Support P-Code Applications"
default n default n
depends on INTERPRETERS_PCODE && SYSTEM_PRUN && ((!BUILD_PROTECTED && !BUILD_KERNEL) || EXPERIMENTAL) depends on INTERPRETERS_PCODE && ((!BUILD_PROTECTED && !BUILD_KERNEL) || EXPERIMENTAL)
---help--- ---help---
Enable support for interpreted P-Code binaries. P-Code binaries are Enable support for interpreted P-Code binaries. P-Code binaries are
generated by the NuttX Pascal compiler. generated by the NuttX Pascal compiler.
@@ -84,12 +84,12 @@ config PCODE
Pascal package directory for more details. The correct installation Pascal package directory for more details. The correct installation
directory is: apps/interpreters. directory is: apps/interpreters.
ISSUES: This feature is highly coupled with logic in the apps/subdirectory ISSUES: This feature is highly coupled with logic in the apps/
and, as a consequence, cannot be used in environments that do not directory and, as a consequence, cannot be used in environments that
include the standard NuttX apps/ nor in build configurations using do not include the standard NuttX apps/ directory nor in build
UILD_PROTECTED or BUILD_KERNEL.. configurations using BUILD_PROTECTED or BUILD_KERNEL.
if PCODE if BINFMT_PCODE
source binfmt/libpcode/Kconfig source binfmt/libpcode/Kconfig
endif endif
+21 -18
View File
@@ -3,65 +3,68 @@
# see the file kconfig-language.txt in the NuttX tools repository. # see the file kconfig-language.txt in the NuttX tools repository.
# #
config PCODE_STACKSIZE config BINFMT_PCODE_STACKSIZE
int "P-code interpreter stack size" int "P-code interpreter stack size"
default 2048 default 2048
---help--- ---help---
This is the stack size that will be used when starting P-code interpreter. This is the stack size that will be used when starting P-code interpreter.
config PCODE_PRIORITY config BINFMT_PCODE_PRIORITY
int "P-code interpreter priority" int "P-code interpreter priority"
default 100 default 100
---help--- ---help---
This is the task_priority that will be used when starting P-code interpreter. This is the task_priority that will be used when starting P-code interpreter.
config PCODE_VARSTACKSIZE config BINFMT_PCODE_VARSTACKSIZE
int "P-code variable stack size" int "P-code variable stack size"
default 1024 default 1024
---help--- ---help---
This size of the P-Code variable storage area to be allocated by the This size of the P-Code variable storage area to be allocated by the
P-Code runtime. P-Code runtime.
config PCODE_STRSTACKSIZE config BINFMT_PCODE_STRSTACKSIZE
int "P-code string stack size" int "P-code string stack size"
default 128 default 128
---help--- ---help---
This size of the P-Code string stack area to be allocated by the This size of the P-Code string stack area to be allocated by the
P-Code runtime. P-Code runtime.
config PCODE_TEST_FS config BINFMT_PCODE_TEST_FS
bool "Mount a test file system" bool "Mount a test file system"
depends on FS_ROMFS && !DISABLE_MOUNTPOINT depends on FS_ROMFS && !DISABLE_MOUNTPOINT
---help--- ---help---
Mount a test file system. This test file system was used to verify the P-Code binary format. Mount a test file system. This test file system was used to verify
the P-Code binary format.
if PCODE_TEST_FS if BINFMT_PCODE_TEST_FS
config PCODE_TEST_DEVMINOR config BINFMT_PCODE_TEST_DEVMINOR
int "Test file system minor device number" int "Test file system minor device number"
default 0 default 0
---help--- ---help---
The minor device number of the ROMFS block. For example, the N in /dev/ramN. The minor device number of the ROMFS block. For example, the N in
Used for registering the RAM block driver that will hold the ROMFS file system /dev/ramN. Used for registering the RAM block driver that will hold
containing the P-code files to be tested. Default: 0 the ROMFS file system containing the P-code files to be tested.
Default: 0
config PCODE_TEST_DEVPATH config BINFMT_PCODE_TEST_DEVPATH
string "Test file system device Path" string "Test file system device Path"
default "/dev/ram0" default "/dev/ram0"
---help--- ---help---
The path to the ROMFS block driver device. This must match PCODE_TEST_DEVMINOR. The path to the ROMFS block driver device. This must match
Used for registering the RAM block driver that will hold the ROMFS file system BINFMT_PCODE_TEST_DEVMINOR. Used for registering the RAM block
containing the P-code files to be tested. Default: "/dev/ram0" driver that will hold the ROMFS file system containing the P-code
files to be tested. Default: "/dev/ram0"
config PCODE_TEST_MOUNTPOINT config BINFMT_PCODE_TEST_MOUNTPOINT
string "Test file system mount point" string "Test file system mount point"
default "/bin" default "/bin"
---help--- ---help---
Location where the test file system will be mounted Location where the test file system will be mounted
endif # PCODE_TEST_FS endif # BINFMT_PCODE_TEST_FS
config PCODE_DUMPBUFFER config BINFMT_PCODE_DUMPBUFFER
bool "Dump P-code buffers" bool "Dump P-code buffers"
default n default n
depends on DEBUG_INFO depends on DEBUG_INFO
+11 -3
View File
@@ -1,7 +1,7 @@
############################################################################ ############################################################################
# binfmt/libpcode/Make.defs # binfmt/libpcode/Make.defs
# #
# Copyright (C) 2014 Gregory Nutt. All rights reserved. # Copyright (C) 2014, 2016 Gregory Nutt. All rights reserved.
# Author: Gregory Nutt <gnutt@nuttx.org> # Author: Gregory Nutt <gnutt@nuttx.org>
# #
# Redistribution and use in source and binary forms, with or without # Redistribution and use in source and binary forms, with or without
@@ -33,7 +33,7 @@
# #
############################################################################ ############################################################################
ifeq ($(CONFIG_PCODE),y) ifeq ($(CONFIG_BINFMT_PCODE),y)
# P-code application interfaces # P-code application interfaces
@@ -46,7 +46,15 @@ BINFMT_CSRCS += pcode.c
# Add an include path so that P-Code related header files may reside in # Add an include path so that P-Code related header files may reside in
# the libpcode sub-directory # the libpcode sub-directory
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" "$(TOPDIR)$(DELIM)binfmt$(DELIM)libpcode"} CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \
"$(TOPDIR)$(DELIM)binfmt$(DELIM)libpcode"}
# FIXME: This also depends upon header files installed at
# apps/interpreters/pcode
PCODE_DIR = $(TOPDIR)$(DELIM)$(CONFIG_APPS_DIR)$(DELIM)interpreters$(DELIM)pcode
CFLAGS += ${shell $(INCDIR) $(INCDIROPT) "$(CC)" \
"$(PCODE_DIR)$(DELIM)include" "$(PCODE_DIR)$(DELIM)insn$(DELIM)include"}
# Hook the libpcode subdirectory into the build # Hook the libpcode subdirectory into the build
+18 -17
View File
@@ -14,7 +14,7 @@ Other required configuration settings:
CONFIG_NFILE_DESCRIPTORS > 3 CONFIG_NFILE_DESCRIPTORS > 3
CONFIG_BINFMT_DISABLE=n CONFIG_BINFMT_DISABLE=n
CONFIG_PCODE=y CONFIG_BINFMT_PCODE=y
Directory Contents Directory Contents
------------------ ------------------
@@ -83,16 +83,16 @@ Here is a simple test configuration using the NuttX simulator:
This enables building the PCODE binary format This enables building the PCODE binary format
CONFIG_PCODE=y CONFIG_BINFMT_PCODE=y
CONFIG_PCODE_PRIORITY=100 CONFIG_BINFMT_PCODE_PRIORITY=100
CONFIG_PCODE_STACKSIZE=2048 CONFIG_BINFMT_PCODE_STACKSIZE=2048
This enables building and mount a test filesystem: This enables building and mount a test filesystem:
CONFIG_PCODE_TEST_FS=y CONFIG_BINFMT_PCODE_TEST_FS=y
CONFIG_PCODE_TEST_DEVMINOR=3 CONFIG_BINFMT_PCODE_TEST_DEVMINOR=3
CONFIG_PCODE_TEST_DEVPATH="/dev/ram3" CONFIG_BINFMT_PCODE_TEST_DEVPATH="/dev/ram3"
CONFIG_PCODE_TEST_MOUNTPOINT="/bin" CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT="/bin"
Debug options can also be enabled with: Debug options can also be enabled with:
@@ -127,23 +127,24 @@ Here is a simple test configuration using the NuttX simulator:
Issues Issues
------ ------
1. As implemented now, there is a tight coupling between the nuttx/directory 1. As implemented now, there is a tight coupling between the nuttx/binfmt
and the apps/ directory. That should not be the case; the nuttx/ logic directory and the apps/interpreters/pcode directory. That should not
should be completely independent of apps/ logic (but not vice versa). be the case; the nuttx/ logic should be completely independent of apps/
logic (but not vice versa).
2. The current implementation will not work in the CONFIG_BUILD_PROTECTED or 2. The current implementation will not work in the CONFIG_BUILD_PROTECTED or
CONFIG_BUILD_KERNEL configurations. That is because of the little proxy CONFIG_BUILD_KERNEL configurations. That is because of the little proxy
logic (function pcode_proxy() in the file pcode.c). (a) That logic would logic (function pcode_proxy() and prun() in the file pcode.c). (a) That
attempt to link with P-code logic that resides in user space. That will logic would attempt to link with P-code logic that resides in user space.
not work. And (2) that proxy would be started in user mode but in the That will not work. And (2) that proxy would be started in user mode but
kernel address space which will certainly crash immediately. in the kernel address space which will certainly crash immediately.
The general idea to fix both of these problems is as follows: The general idea to fix both of these problems is as follows:
1. Eliminate the pcode_proxy. Instead start a P-Code execution program that 1. Eliminate the pcode_proxy. Instead start a P-Code execution program that
resides in the file system. That P-Code execution program already resides in the file system. That P-Code execution program already
exists. It is in apps/system/prun. This program should be built as, exists. This program should be built as, say, an ELF binary and
say, an ELF binary and installed in a file system. installed in a file system.
2. Add a configuration setting that gives the full path to where the pexec 2. Add a configuration setting that gives the full path to where the pexec
program is stored in the filesystem. program is stored in the filesystem.
+113 -37
View File
@@ -1,7 +1,7 @@
/**************************************************************************** /****************************************************************************
* binfmt/pcode.c * binfmt/pcode.c
* *
* Copyright (C) 2014-2015 Gregory Nutt. All rights reserved. * Copyright (C) 2014-2016 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org> * Author: Gregory Nutt <gnutt@nuttx.org>
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
@@ -47,15 +47,16 @@
#include <errno.h> #include <errno.h>
#include <debug.h> #include <debug.h>
#include <apps/prun.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/poff.h> #include <nuttx/poff.h>
#include <nuttx/fs/ramdisk.h> #include <nuttx/fs/ramdisk.h>
#include <nuttx/binfmt/binfmt.h> #include <nuttx/binfmt/binfmt.h>
#include <nuttx/binfmt/pcode.h> #include <nuttx/binfmt/pcode.h>
#ifdef CONFIG_PCODE #include "pexec.h"
#include "pedefs.h"
#ifdef CONFIG_BINFMT_PCODE
/**************************************************************************** /****************************************************************************
* Pre-processor Definitions * Pre-processor Definitions
@@ -72,23 +73,19 @@
# error The binary loader is disabled (CONFIG_BINFMT_DISABLE)! # error The binary loader is disabled (CONFIG_BINFMT_DISABLE)!
#endif #endif
#ifndef CONFIG_PCODE
# error You must select CONFIG_PCODE in your configuration file
#endif
#ifndef CONFIG_SCHED_ONEXIT #ifndef CONFIG_SCHED_ONEXIT
# error CONFIG_SCHED_ONEXIT is required # error CONFIG_SCHED_ONEXIT is required
#endif #endif
#ifndef CONFIG_PCODE_VARSTACKSIZE #ifndef CONFIG_BINFMT_PCODE_VARSTACKSIZE
# define CONFIG_PCODE_VARSTACKSIZE 1024 # define CONFIG_BINFMT_PCODE_VARSTACKSIZE 1024
#endif #endif
#ifndef CONFIG_PCODE_STRSTACKSIZE #ifndef CONFIG_BINFMT_PCODE_STRSTACKSIZE
# define CONFIG_PCODE_STRSTACKSIZE 128 # define CONFIG_BINFMT_PCODE_STRSTACKSIZE 128
#endif #endif
#ifdef CONFIG_PCODE_TEST_FS #ifdef CONFIG_BINFMT_PCODE_TEST_FS
# ifndef CONFIG_FS_ROMFS # ifndef CONFIG_FS_ROMFS
# error You must select CONFIG_FS_ROMFS in your configuration file # error You must select CONFIG_FS_ROMFS in your configuration file
# endif # endif
@@ -97,16 +94,16 @@
# error You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file # error You must not disable mountpoints via CONFIG_DISABLE_MOUNTPOINT in your configuration file
# endif # endif
# ifndef CONFIG_PCODE_TEST_DEVMINOR # ifndef CONFIG_BINFMT_PCODE_TEST_DEVMINOR
# define CONFIG_PCODE_TEST_DEVMINOR 0 # define CONFIG_BINFMT_PCODE_TEST_DEVMINOR 0
# endif # endif
# ifndef CONFIG_PCODE_TEST_DEVPATH # ifndef CONFIG_BINFMT_PCODE_TEST_DEVPATH
# define CONFIG_PCODE_TEST_DEVPATH "/dev/ram0" # define CONFIG_BINFMT_PCODE_TEST_DEVPATH "/dev/ram0"
# endif # endif
# ifndef CONFIG_PCODE_TEST_MOUNTPOINT # ifndef CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT
# define CONFIG_PCODE_TEST_MOUNTPOINT "/bin" # define CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT "/bin"
# endif # endif
#endif #endif
@@ -130,6 +127,16 @@ struct binfmt_handoff_s
* Private Function Prototypes * Private Function Prototypes
****************************************************************************/ ****************************************************************************/
static int pcode_run(FAR char *exepath, size_t varsize, size_t strsize);
#ifdef CONFIG_BINFMT_PCODE_TEST_FS
static int pcode_mount_testfs(void);
#endif
#if !defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_BUILD_KERNEL)
static void pcode_onexit(int exitcode, FAR void *arg);
#endif
#if !defined(CONFIG_BUILD_PROTECTED) && !defined(CONFIG_BUILD_KERNEL)
static int pcode_proxy(int argc, char **argv);
#endif
static int pcode_load(FAR struct binary_s *binp); static int pcode_load(FAR struct binary_s *binp);
static int pcode_unload(FAR struct binary_s *binp); static int pcode_unload(FAR struct binary_s *binp);
@@ -146,7 +153,7 @@ static struct binfmt_s g_pcode_binfmt =
struct binfmt_handoff_s g_pcode_handoff; struct binfmt_handoff_s g_pcode_handoff;
#ifdef CONFIG_PCODE_TEST_FS #ifdef CONFIG_BINFMT_PCODE_TEST_FS
# include "romfs.h" # include "romfs.h"
#endif #endif
@@ -154,6 +161,69 @@ struct binfmt_handoff_s g_pcode_handoff;
* Private Functions * Private Functions
****************************************************************************/ ****************************************************************************/
/****************************************************************************
* Name: pcode_run
*
* Description:
* Execute/interpret a P-Code file. This function does not return until
* the P-code program terminates or until a fatal error occurs.
*
* Input Parameters:
* exepath - The full path to the P-Code binary.
* varsize - Size of the P-Code variable stack
* strsize - the size of the P-Code string stack.
*
* Returned Value:
* OK if the P-Code program successfully terminated; A negated errno value
* is returned on the event of any failure.
*
****************************************************************************/
static int pcode_run(FAR char *exepath, size_t varsize, size_t strsize)
{
FAR struct pexec_s *st;
int errcode;
int ret = OK;
/* Load the POFF file into memory */
st = pload(exepath, varsize, varsize);
if (!st)
{
berr("ERROR: Could not load %s\n", exepath);
return -ENOEXEC;
}
binfo("Loaded %s\n", exepath);
/* Execute the P-Code program until a stopping condition occurs */
for (;;)
{
/* Execute the instruction; Check for exceptional conditions */
errcode = pexec(st);
if (errcode != eNOERROR)
{
break;
}
}
if (errcode != eEXIT)
{
/* REVISIT: Select a more appropriated return errocode */
berr("ERROR: Runtime error 0x%02x -- Execution Stopped\n", errcode);
ret = -ENOEXEC;
}
/* Clean up resources used by the interpreter */
binfo("Execution terminated\n");
pexec_release(st);
return ret;
}
/**************************************************************************** /****************************************************************************
* Name: pcode_mount_testfs * Name: pcode_mount_testfs
* *
@@ -162,15 +232,15 @@ struct binfmt_handoff_s g_pcode_handoff;
* *
****************************************************************************/ ****************************************************************************/
#ifdef CONFIG_PCODE_TEST_FS #ifdef CONFIG_BINFMT_PCODE_TEST_FS
static int pcode_mount_testfs(void) static int pcode_mount_testfs(void)
{ {
int ret; int ret;
/* Create a ROM disk for the ROMFS filesystem */ /* Create a ROM disk for the ROMFS filesystem */
binfo("Registering romdisk at /dev/ram%d\n", CONFIG_PCODE_TEST_DEVMINOR); binfo("Registering romdisk at /dev/ram%d\n", CONFIG_BINFMT_PCODE_TEST_DEVMINOR);
ret = romdisk_register(CONFIG_PCODE_TEST_DEVMINOR, (FAR uint8_t *)romfs_img, ret = romdisk_register(CONFIG_BINFMT_PCODE_TEST_DEVMINOR, (FAR uint8_t *)romfs_img,
NSECTORS(ROMFS_IMG_LEN), SECTORSIZE); NSECTORS(ROMFS_IMG_LEN), SECTORSIZE);
if (ret < 0) if (ret < 0)
{ {
@@ -181,9 +251,11 @@ static int pcode_mount_testfs(void)
/* Mount the test file system */ /* Mount the test file system */
binfo("Mounting ROMFS filesystem at target=%s with source=%s\n", binfo("Mounting ROMFS filesystem at target=%s with source=%s\n",
CONFIG_PCODE_TEST_MOUNTPOINT, CONFIG_PCODE_TEST_DEVPATH); CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT,
CONFIG_BINFMT_PCODE_TEST_DEVPATH);
ret = mount(CONFIG_PCODE_TEST_DEVPATH, CONFIG_PCODE_TEST_MOUNTPOINT, ret = mount(CONFIG_BINFMT_PCODE_TEST_DEVPATH,
CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT,
"romfs", MS_RDONLY, NULL); "romfs", MS_RDONLY, NULL);
if (ret < 0) if (ret < 0)
{ {
@@ -191,7 +263,9 @@ static int pcode_mount_testfs(void)
DEBUGASSERT(errval > 0); DEBUGASSERT(errval > 0);
berr("ERROR: mount(%s,%s,romfs) failed: %d\n", berr("ERROR: mount(%s,%s,romfs) failed: %d\n",
CONFIG_PCODE_TEST_DEVPATH, CONFIG_PCODE_TEST_MOUNTPOINT, errval); CONFIG_BINFMT_PCODE_TEST_DEVPATH,
CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, errval);
return -errval; return -errval;
} }
@@ -201,7 +275,7 @@ static int pcode_mount_testfs(void)
*/ */
#if defined(CONFIG_BINFMT_EXEPATH) && !defined(CONFIG_PATH_INITIAL) #if defined(CONFIG_BINFMT_EXEPATH) && !defined(CONFIG_PATH_INITIAL)
(void)setenv("PATH", CONFIG_PCODE_TEST_MOUNTPOINT, 1); (void)setenv("PATH", CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, 1);
#endif #endif
return OK; return OK;
@@ -273,7 +347,8 @@ static int pcode_proxy(int argc, char **argv)
/* Load the P-code file and execute it */ /* Load the P-code file and execute it */
ret = prun(fullpath, CONFIG_PCODE_VARSTACKSIZE, CONFIG_PCODE_STRSTACKSIZE); ret = pcode_run(fullpath, CONFIG_BINFMT_PCODE_VARSTACKSIZE,
CONFIG_BINFMT_PCODE_STRSTACKSIZE);
/* We no longer need the fullpath */ /* We no longer need the fullpath */
@@ -324,8 +399,8 @@ static int pcode_load(struct binary_s *binp)
/* Read the POFF file header */ /* Read the POFF file header */
for (remaining = sizeof(struct poff_fileheader_s), ptr = (FAR uint8_t *)&hdr; for (remaining = sizeof(struct poff_fileheader_s),
remaining > 0; ) ptr = (FAR uint8_t *)&hdr; remaining > 0; )
{ {
/* Read the next GULP */ /* Read the next GULP */
@@ -358,7 +433,7 @@ static int pcode_load(struct binary_s *binp)
} }
} }
#ifdef CONFIG_PCODE_DUMPBUFFER #ifdef CONFIG_BINFMT_PCODE_DUMPBUFFER
lib_dumpbuffer("POFF File Header", &hdr, sizeof(poff_fileheader_s)); lib_dumpbuffer("POFF File Header", &hdr, sizeof(poff_fileheader_s));
#endif #endif
@@ -377,8 +452,8 @@ static int pcode_load(struct binary_s *binp)
*/ */
binp->entrypt = pcode_proxy; binp->entrypt = pcode_proxy;
binp->stacksize = CONFIG_PCODE_STACKSIZE; binp->stacksize = CONFIG_BINFMT_PCODE_STACKSIZE;
binp->priority = CONFIG_PCODE_PRIORITY; binp->priority = CONFIG_BINFMT_PCODE_PRIORITY;
/* Get exclusive access to the p-code handoff structure */ /* Get exclusive access to the p-code handoff structure */
@@ -517,14 +592,15 @@ void pcode_uninitialize(void)
UNUSED(errval); UNUSED(errval);
} }
#ifdef CONFIG_PCODE_TEST_FS #ifdef CONFIG_BINFMT_PCODE_TEST_FS
ret = umount(CONFIG_PCODE_TEST_MOUNTPOINT); ret = umount(CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT);
if (ret < 0) if (ret < 0)
{ {
int errval = get_errno(); int errval = get_errno();
DEBUGASSERT(errval > 0); DEBUGASSERT(errval > 0);
berr("ERROR: umount(%s) failed: %d\n", CONFIG_PCODE_TEST_MOUNTPOINT, errval); berr("ERROR: umount(%s) failed: %d\n",
CONFIG_BINFMT_PCODE_TEST_MOUNTPOINT, errval);
UNUSED(errval); UNUSED(errval);
} }
#endif #endif
@@ -534,4 +610,4 @@ void pcode_uninitialize(void)
sem_destroy(&g_pcode_handoff.exclsem); sem_destroy(&g_pcode_handoff.exclsem);
} }
#endif /* CONFIG_PCODE */ #endif /* CONFIG_BINFMT_PCODE */