Reworked the way how the gensyscalls stuff finds out about

the sizes and alignments of syscall parameters. It no longer
generates and compiles functions with the same signature as the
syscalls. This simply doesn't generally work for cross-compilation.
Instead we provide a bit of architecture-specific code that knows
how things work for the target architecture.



git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15196 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold 2005-11-28 12:53:55 +00:00
parent 968748e669
commit 2ae568931f
6 changed files with 538 additions and 226 deletions

View File

@ -1,20 +1,74 @@
SubDir HAIKU_TOP src tools gensyscalls ;
# build gensyscallinfos
# preprocess the syscalls header
BuildPlatformMain gensyscallinfos : gensyscallinfos.cpp ;
LinkAgainst gensyscallinfos : $(HOST_LIBSTDC++) ;
rule PreprocessSyscalls
{
# PreprocessSyscalls <preprocessedHeader> : <header> : <parsable> ;
#
local parsable = $(3) ;
local parsableDefine ;
if $(parsable) {
parsableDefine = GEN_SYSCALL_INFOS_PROCESSING ;
}
# generate the syscall infos source file
Depends $(<) : $(>) ;
local headers = [ on $(1) return $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
local sysHeaders =
[ PrivateHeaders kernel ]
[ ArchHeaders $(TARGET_ARCH) ]
[ on $(1) return $(SUBDIRSYSHDRS) $(SYSHDRS) ]
$(HAIKU_HDRS) ;
HDRS on $(<) = $(headers) ;
SYSHDRS on $(<) = $(sysHeaders) ;
HDRRULE on $(>) = HdrRule ;
HDRSCAN on $(>) = $(HDRPATTERN) ;
HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ;
HDRGRIST on $(>) = $(HDRGRIST) ;
DEFINES on $(<) += $(HAIKU_DEFINES) $(parsableDefine) ;
CCFLAGS on $(<) += $(HAIKU_CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ;
CCHDRS on $(<) = [ FIncludes $(headers) : $(HAIKU_LOCAL_INCLUDES_OPTION) ]
$(HAIKU_INCLUDES_SEPARATOR)
[ FSysIncludes $(sysHeaders) : $(HAIKU_SYSTEM_INCLUDES_OPTION) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions PreprocessSyscalls
{
$(HAIKU_C++) -xc++ -E "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
}
local syscallsHeader = [ FGristFiles syscalls.h ] ;
SEARCH on $(syscallsHeader) = [ FDirName $(HAIKU_TOP) headers private kernel ] ;
# We generate two preprocessed headers. One for parsing by gensyscallinfos
# (it contains #pragmas) and one for inclusion by the generated
# gensyscalls_infos.cpp.
local syscallsHeaderPPParsable = [ FGristFiles syscalls.h.pp.parsable ] ;
local syscallsHeaderPP = [ FGristFiles syscalls.h.pp ] ;
MakeLocateArch $(syscallsHeaderPP) ;
MakeLocateArch $(syscallsHeaderPPParsable) $(syscallsHeaderPP) ;
local syscallInfos = [ FGristFiles gensyscalls_infos.c ] ;
PreprocessSyscalls $(syscallsHeaderPPParsable) : $(syscallsHeader) : true ;
PreprocessSyscalls $(syscallsHeaderPP) : $(syscallsHeader) ;
# build gensyscallinfos
BuildPlatformMain gensyscallinfos
: gensyscallinfos.cpp
: $(HOST_LIBSTDC++)
;
# generate the syscall infos source file
local syscallInfos = [ FGristFiles gensyscalls_infos.cpp ] ;
MakeLocateArch $(syscallInfos) ;
rule GenSyscallInfos {
@ -26,20 +80,23 @@ actions GenSyscallInfos1 {
$(2[1]) $(2[2]) $(1)
}
GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPP) ;
GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPPParsable) ;
SubDirHdrs [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
# build gensyscalls
BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos:S=$(SUFOBJ)) ;
BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos) ;
LinkAgainst gensyscalls : $(HOST_LIBSTDC++) ;
UsePrivateObjectHeaders gensyscalls.cpp : kernel ;
UseArchObjectHeaders gensyscalls.cpp : $(TARGET_ARCH) ;
# Explicitly tell jam that gensyscalls.cpp includes the generated header.
Includes [ FGristFiles gensyscalls.cpp ] : $(syscallsHeaderPP) ;
# generate the output files
# place them where there are needed
# place them where they are needed
local dir = $(HAIKU_COMMON_DEBUG_OBJECT_DIR) ;
MakeLocate <syscalls>syscalls.S.inc : [ FDirName $(dir) system libroot os ] ;
MakeLocate <syscalls>syscall_dispatcher.h : [ FDirName $(dir) system kernel ] ;
@ -47,7 +104,6 @@ MakeLocate <syscalls>syscall_numbers.h : [ FDirName $(dir) system kernel ] ;
MakeLocate <syscalls>syscall_table.h : [ FDirName $(dir) system kernel ] ;
MakeLocate <syscalls>strace_syscalls.h : [ FDirName $(dir) bin strace ] ;
rule GenSyscallsFile {
Depends $(1) : gensyscalls ;
GenSyscallsFile1 $(1) : gensyscalls ;
@ -98,49 +154,3 @@ GenSyscallsDispatcher <syscalls>syscall_dispatcher.h ;
GenSyscallsNumbers <syscalls>syscall_numbers.h ;
GenSyscallsTable <syscalls>syscall_table.h ;
GenSyscallsSTrace <syscalls>strace_syscalls.h ;
# preprocess the syscalls header
UsePrivateHeaders kernel ;
UseArchHeaders $(TARGET_ARCH) ;
rule PreprocessSyscalls
{
Depends $(<) : $(>) ;
local headers = [ on $(1) return $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
local sysHeaders = [ on $(1) return $(SUBDIRSYSHDRS) $(SYSHDRS) ]
$(HAIKU_HDRS) ;
HDRS on $(<) = $(headers) ;
SYSHDRS on $(<) = $(sysHeaders) ;
HDRRULE on $(>) = HdrRule ;
HDRSCAN on $(>) = $(HDRPATTERN) ;
HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ;
HDRGRIST on $(>) = $(HDRGRIST) ;
DEFINES on $(<) += $(HAIKU_DEFINES) GEN_SYSCALL_INFOS_PROCESSING ;
CCFLAGS on $(<) += $(HAIKU_CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ;
CCHDRS on $(<) = [ FIncludes $(headers) : $(HAIKU_LOCAL_INCLUDES_OPTION) ]
$(HAIKU_INCLUDES_SEPARATOR)
[ FSysIncludes $(sysHeaders) : $(HAIKU_SYSTEM_INCLUDES_OPTION) ] ;
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
}
actions PreprocessSyscalls
{
$(HAIKU_C++) -xc++ -E "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
}
PreprocessSyscalls $(syscallsHeaderPP) : $(syscallsHeader) ;
# compile the syscall infos source file
# TODO: Clean this mess up!
SYSHDRS on $(syscallInfos:S=$(SUFOBJ)) = $(HAIKU_HDRS) ;
Object $(syscallInfos:S=$(SUFOBJ)) : $(syscallInfos) ;
CCFLAGS on $(syscallInfos:S=$(SUFOBJ)) += -nostdinc ;

View File

@ -0,0 +1,51 @@
// Included by gensyscalls.
typedef int AlignmentType;
static const char* kAlignmentType = "int";
static const int kAlignment = sizeof(AlignmentType);
// ReturnTypeCreator
template<typename T>
class ReturnTypeCreator {
public:
static void Create(Syscall* syscall, const char* name)
{
int size = sizeof(T);
int usedSize = align_to_type<AlignmentType>(size);
const char* alignmentType
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
syscall->SetReturnType(name, size, usedSize, alignmentType);
}
};
template<>
class ReturnTypeCreator<void> {
public:
static void Create(Syscall* syscall, const char* name)
{
syscall->SetReturnType(name, 0, 0, 0);
}
};
// ParameterCreator
template<typename T>
class ParameterCreator {
public:
static void Create(Syscall* syscall, const char* typeName,
const char* parameterName)
{
// compute offset
int offset = 0;
if (Parameter* previous = syscall->LastParameter())
offset = previous->Offset() + previous->UsedSize();
int size = sizeof(T);
int usedSize = align_to_type<AlignmentType>(size);
const char* alignmentType
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
syscall->AddParameter(typeName, parameterName, size, usedSize, offset,
alignmentType);
}
};

View File

@ -0,0 +1,51 @@
// Included by gensyscalls.
typedef int AlignmentType;
static const char* kAlignmentType = "int";
static const int kAlignment = sizeof(AlignmentType);
// ReturnTypeCreator
template<typename T>
class ReturnTypeCreator {
public:
static void Create(Syscall* syscall, const char* name)
{
int size = sizeof(T);
int usedSize = align_to_type<AlignmentType>(size);
const char* alignmentType
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
syscall->SetReturnType(name, size, usedSize, alignmentType);
}
};
template<>
class ReturnTypeCreator<void> {
public:
static void Create(Syscall* syscall, const char* name)
{
syscall->SetReturnType(name, 0, 0, 0);
}
};
// ParameterCreator
template<typename T>
class ParameterCreator {
public:
static void Create(Syscall* syscall, const char* typeName,
const char* parameterName)
{
// compute offset
int offset = 0;
if (Parameter* previous = syscall->LastParameter())
offset = previous->Offset() + previous->UsedSize();
int size = sizeof(T);
int usedSize = align_to_type<AlignmentType>(size);
const char* alignmentType
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
syscall->AddParameter(typeName, parameterName, size, usedSize, offset,
alignmentType);
}
};

View File

@ -15,7 +15,7 @@
// usage
const char *kUsage =
"Usage: gensyscallinfos <header> <calls> <dispatcher>\n"
"Usage: gensyscallinfos <header> <syscall infos>\n"
"\n"
"Given the (preprocessed) header file that defines the syscall prototypes the\n"
"command generates a source file consisting of syscall infos, which is needed\n"
@ -322,16 +322,6 @@ private:
tokenizer.ExpectNextToken("pragma");
tokenizer.ExpectNextToken("syscalls");
tokenizer.ExpectNextToken("end");
// for (int i = 0; i < (int)fSyscalls.size(); i++) {
// const Syscall &syscall = fSyscalls[i];
// printf("syscall: `%s'\n", syscall.GetName().c_str());
// for (int k = 0; k < (int)syscall.CountParameters(); k++)
// printf(" arg: `%s'\n", syscall.ParameterAt(k).type.c_str());
// printf(" return type: `%s'\n",
// syscall.GetReturnType().type.c_str());
// }
// printf("Found %lu syscalls.\n", fSyscalls.size());
}
void _WriteSyscallInfoFile(const char *filename)
@ -340,86 +330,49 @@ private:
ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open())
throw new IOException(string("Failed to open `") + filename + "'.");
// write preamble
file << "#include \"gensyscalls.h\"" << endl;
file << "#include \"syscalls.h\"" << endl;
file << "#include \"syscalls.h.pp\"" << endl;
file << endl;
// output the case statements
file << "SyscallVector* create_syscall_vector() {" << endl;
file << "\tSyscallVector* syscallVector = SyscallVector::Create();"
<< endl;
file << "\tSyscall* syscall;" << endl;
// syscalls
for (int i = 0; i < (int)fSyscalls.size(); i++) {
const Syscall &syscall = fSyscalls[i];
string name = string("gensyscall_") + syscall.GetName();
string paramInfoName = name + "_parameter_info";
// syscall = syscallVector->CreateSyscall("syscallName",
// "syscallKernelName");
file << "\tsyscall = syscallVector->CreateSyscall(\""
<< syscall.GetName() << "\", \""
<< syscall.GetKernelName() << "\");" << endl;
const Type &returnType = syscall.GetReturnType();
// syscall->SetReturnType<ReturnType>("returnType");
file << "\tsyscall->SetReturnType<" << returnType.type
<< ">(\"" << returnType.type << "\");" << endl;
// parameters
int paramCount = syscall.CountParameters();
// write the parameter infos
file << "static gensyscall_parameter_info " << paramInfoName
<< "[] = {" << endl;
for (int k = 0; k < paramCount; k++) {
const NamedType &param = syscall.ParameterAt(k);
file << "\t{ \"" << param.type << "\", \"" << param.name
<< "\", 0, " << "sizeof(" << syscall.ParameterAt(k).type
<< "), 0 }," << endl;
// syscall->AddParameter<ParameterType>("parameterTypeName",
// "parameterName");
file << "\tsyscall->AddParameter<"
<< param.type << ">(\""
<< param.type << "\", \""
<< param.name << "\");" << endl;
}
file << "};" << endl;
file << endl;
// write the initialization function
file << "static void " << name << "(";
for (int k = 0; k < paramCount; k++) {
if (k > 0)
file << ", ";
string type = syscall.ParameterAt(k).type;
string::size_type pos = type.find(")");
if (pos == string::npos) {
file << type << " arg" << k;
} else {
// function pointer
file << string(type, 0, pos) << " arg" << k
<< string(type, pos, type.length() - pos);
}
}
if (paramCount > 0)
file << ", ";
file << "int arg" << paramCount << ") {" << endl;
for (int k = 0; k < paramCount; k++) {
file << "\t" << paramInfoName << "[" << k << "].offset = "
<< "(char*)&arg" << k << " - (char*)&arg0;" << endl;
file << "\t" << paramInfoName << "[" << k << "].actual_size = "
<< "(char*)&arg" << (k + 1) << " - (char*)&arg" << k << ";"
<< endl;
}
file << "}" << endl;
file << endl;
}
// write the syscall infos
file << "static gensyscall_syscall_info "
"gensyscall_syscall_infos[] = {" << endl;
for (int i = 0; i < (int)fSyscalls.size(); i++) {
const Syscall &syscall = fSyscalls[i];
string name = string("gensyscall_") + syscall.GetName();
string paramInfoName = name + "_parameter_info";
file << "\t{ \"" << syscall.GetName() << "\", "
<< "\"" << syscall.GetKernelName() << "\", "
<< "\"" << syscall.GetReturnType().type << "\", "
<< syscall.CountParameters() << ", "
<< paramInfoName << " }," << endl;
}
file << "};" << endl;
file << endl;
// write the initialization function
file << "gensyscall_syscall_info *gensyscall_get_infos(int *count);";
file << "gensyscall_syscall_info *gensyscall_get_infos(int *count) {"
<< endl;
for (int i = 0; i < (int)fSyscalls.size(); i++) {
const Syscall &syscall = fSyscalls[i];
string name = string("gensyscall_") + syscall.GetName();
file << "\t" << name << "(";
int paramCount = syscall.CountParameters();
// write the dummy parameters
for (int k = 0; k < paramCount; k++)
file << "(" << syscall.ParameterAt(k).type << ")0, ";
file << "0);" << endl;
}
file << "\t*count = " << fSyscalls.size() << ";" << endl;
file << "\treturn gensyscall_syscall_infos;" << endl;
// postamble
file << "\treturn syscallVector;" << endl;
file << "}" << endl;
}

View File

@ -1,16 +1,19 @@
// gensyscalls.cpp
// Don't include arch_gensyscalls.h. It's only needed when creating the
// syscall vector.
#define DONT_INCLUDE_ARCH_GENSYSCALLS_H 1
#include <cstdio>
#include <cstdlib>
#include <fstream>
#include <string>
#include "arch_config.h"
#include <vector>
#include "gensyscalls.h"
#include "gensyscalls_common.h"
extern "C" gensyscall_syscall_info *gensyscall_get_infos(int *count);
using std::vector;
// usage
const char *kUsage =
@ -38,10 +41,160 @@ print_usage(bool error)
fprintf((error ? stderr : stdout), kUsage);
}
enum {
PARAMETER_ALIGNMENT = sizeof(FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE)
// Type
// constructor
Type::Type(const char* name, int size, int usedSize,
const char* alignmentTypeName)
: fName(name),
fSize(size),
fUsedSize(usedSize),
fAlignmentType(alignmentTypeName)
{
}
// Parameter
// constructor
Parameter::Parameter(const char* typeName, const char* parameterName,
int size, int usedSize, int offset, const char* alignmentTypeName)
: Type(typeName, size, usedSize, alignmentTypeName),
fParameterName(parameterName),
fOffset(offset)
{
}
// Syscall
// ParameterVector
struct Syscall::ParameterVector : public vector<Parameter*> {
};
// constructor
Syscall::Syscall(const char* name, const char* kernelName)
: fName(name),
fKernelName(kernelName),
fReturnType(NULL),
fParameters(new ParameterVector)
{
}
// destructor
Syscall::~Syscall()
{
delete fReturnType;
int count = CountParameters();
for (int i = 0; i < count; i++)
delete ParameterAt(i);
delete fParameters;
}
// ParameterAt
int
Syscall::CountParameters() const
{
return fParameters->size();
}
// ParameterAt
Parameter*
Syscall::ParameterAt(int index) const
{
if (index < 0 || index >= CountParameters())
return NULL;
return (*fParameters)[index];
}
// LastParameter
Parameter*
Syscall::LastParameter() const
{
return ParameterAt(CountParameters() - 1);
}
// SetReturnType
Type*
Syscall::SetReturnType(const char* name, int size, int usedSize,
const char* alignmentTypeName)
{
delete fReturnType;
return fReturnType = new Type(name, size, usedSize, alignmentTypeName);
}
// AddParameter
Parameter*
Syscall::AddParameter(const char* typeName, const char* parameterName,
int size, int usedSize, int offset, const char* alignmentTypeName)
{
Parameter* parameter = new Parameter(typeName, parameterName, size,
usedSize, offset, alignmentTypeName);
fParameters->push_back(parameter);
return parameter;
}
// SyscallVector
struct SyscallVector::_SyscallVector : public vector<Syscall*> {
};
// constructor
SyscallVector::SyscallVector()
: fSyscalls(new _SyscallVector)
{
}
// destructor
SyscallVector::~SyscallVector()
{
int count = CountSyscalls();
for (int i = 0; i < count; i++)
delete SyscallAt(i);
delete fSyscalls;
}
// Create
SyscallVector*
SyscallVector::Create()
{
return new SyscallVector;
}
// CountSyscalls
int
SyscallVector::CountSyscalls() const
{
return fSyscalls->size();
}
// SyscallAt
Syscall*
SyscallVector::SyscallAt(int index) const
{
if (index < 0 || index >= CountSyscalls())
return NULL;
return (*fSyscalls)[index];
}
// CreateSyscall
Syscall*
SyscallVector::CreateSyscall(const char* name, const char* kernelName)
{
Syscall* syscall = new Syscall(name, kernelName);
fSyscalls->push_back(syscall);
return syscall;
}
// #pragma mark -
// Main
class Main {
public:
@ -94,8 +247,8 @@ public:
return 1;
}
}
fSyscallInfos = gensyscall_get_infos(&fSyscallCount);
_UpdateSyscallInfos();
fSyscallVector = create_syscall_vector();
fSyscallCount = fSyscallVector->CountSyscalls();
if (!syscallsFile && !dispatcherFile && !numbersFile && !tableFile
&& !straceFile) {
printf("Found %d syscalls.\n", fSyscallCount);
@ -121,20 +274,21 @@ public:
ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'.");
// output the syscalls definitions
for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
int paramCount = syscall.parameter_count;
const Syscall* syscall = fSyscallVector->SyscallAt(i);
int paramCount = syscall->CountParameters();
int paramSize = 0;
gensyscall_parameter_info* parameters = syscall.parameters;
// XXX: Currently the SYSCALL macros support 4 byte aligned
// parameters only. This has to change, of course.
for (int k = 0; k < paramCount; k++) {
int size = parameters[k].actual_size;
const Parameter* parameter = syscall->ParameterAt(k);
int size = parameter->UsedSize();
paramSize += (size + 3) / 4 * 4;
}
file << "SYSCALL" << (paramSize / 4) << "("
<< syscall.name << ", " << i << ")" << endl;
<< syscall->Name() << ", " << i << ")" << endl;
}
}
@ -144,34 +298,36 @@ public:
ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'.");
// output the case statements
for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
const Syscall* syscall = fSyscallVector->SyscallAt(i);
file << "case " << i << ":" << endl;
file << "\t";
if (string(syscall.return_type) != "void")
if (string(syscall->ReturnType()->TypeName()) != "void")
file << "*call_ret = ";
file << syscall.kernel_name << "(";
int paramCount = syscall.parameter_count;
file << syscall->KernelName() << "(";
int paramCount = syscall->CountParameters();
if (paramCount > 0) {
gensyscall_parameter_info* parameters = syscall.parameters;
if (parameters[0].size < PARAMETER_ALIGNMENT) {
file << "(" << parameters[0].type << ")*("
<< "FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE"
Parameter* parameter = syscall->ParameterAt(0);
if (parameter->AlignmentTypeName()) {
file << "(" << parameter->TypeName() << ")*("
<< parameter->AlignmentTypeName()
<< "*)args";
} else {
file << "*(" << _GetPointerType(parameters[0].type)
file << "*(" << _GetPointerType(parameter->TypeName())
<< ")args";
}
for (int k = 1; k < paramCount; k++) {
if (parameters[k].size < PARAMETER_ALIGNMENT) {
file << ", (" << parameters[k].type << ")*("
<< "FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE"
<< "*)((char*)args + " << parameters[k].offset
parameter = syscall->ParameterAt(k);
if (parameter->AlignmentTypeName()) {
file << ", (" << parameter->TypeName() << ")*("
<< parameter->AlignmentTypeName()
<< "*)((char*)args + " << parameter->Offset()
<< ")";
} else {
file << ", *(" << _GetPointerType(parameters[k].type)
<< ")((char*)args + " << parameters[k].offset
file << ", *(" << _GetPointerType(parameter->TypeName())
<< ")((char*)args + " << parameter->Offset()
<< ")";
}
}
@ -187,16 +343,19 @@ public:
ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'.");
// output the defines
const char *prefix = "_user_";
size_t prefixLen = strlen(prefix);
for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
string name(syscall.kernel_name);
const Syscall* syscall = fSyscallVector->SyscallAt(i);
string name(syscall->KernelName());
// drop the leading "_user_" prefix
if (name.find(prefix) != 0)
throw Exception(string("Bad kernel name: `") + name + "'.");
name = string(name, prefixLen);
// convert to upper case (is there no function for that?)
string defineName;
for (int k = 0; k < (int)name.length(); k++)
@ -221,18 +380,15 @@ public:
// the syscall infos
for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
const Syscall* syscall = fSyscallVector->SyscallAt(i);
// get the parameter size
int paramSize = 0;
if (syscall.parameter_count > 0) {
const gensyscall_parameter_info &lastParam
= syscall.parameters[syscall.parameter_count - 1];
paramSize = lastParam.offset + lastParam.actual_size;
}
if (Parameter* parameter = syscall->LastParameter())
paramSize = parameter->Offset() + parameter->UsedSize();
// output the info for the syscall
file << "\t{ " << syscall.kernel_name << ", "
file << "\t{ " << syscall->KernelName() << ", "
<< paramSize << " }," << endl;
}
@ -260,7 +416,7 @@ public:
// iterate through the syscalls
for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i];
const Syscall* syscall = fSyscallVector->SyscallAt(i);
if (i % chunkSize == 0) {
// chunk end
@ -273,29 +429,32 @@ public:
// spacing, comment
file << endl;
file << "\t// " << syscall.name << endl;
file << "\t// " << syscall->Name() << endl;
// create the return type handler
file << "\thandler = TypeHandlerFactory<" << syscall.return_type
const char* returnType = syscall->ReturnType()->TypeName();
file << "\thandler = TypeHandlerFactory<"
<< returnType
<< ">::Create();" << endl;
// create the syscall
file << "\tsyscall = new Syscall(\"" << syscall.name << "\", "
<< "\"" << syscall.return_type << "\", "<< "handler);" << endl;
file << "\tsyscall = new Syscall(\"" << syscall->Name() << "\", "
<< "\"" << returnType << "\", "<< "handler);" << endl;
file << "\tsyscalls.push_back(syscall);" << endl;
// add the parameters
for (int k = 0; k < syscall.parameter_count; k++) {
const gensyscall_parameter_info &parameter
= syscall.parameters[k];
int paramCount = syscall->CountParameters();
for (int k = 0; k < paramCount; k++) {
const Parameter* parameter = syscall->ParameterAt(k);
// create the parameter type handler
file << "\thandler = TypeHandlerFactory<"
<< parameter.type << ">::Create();" << endl;
<< parameter->TypeName() << ">::Create();" << endl;
// add the parameter
file << "\tsyscall->AddParameter(\"" << parameter.name << "\", "
<< parameter.offset << ", \"" << parameter.type
file << "\tsyscall->AddParameter(\""
<< parameter->ParameterName() << "\", "
<< parameter->Offset() << ", \"" << parameter->TypeName()
<< "\", handler);" << endl;
}
}
@ -316,29 +475,8 @@ public:
return string(type, parenthesis - type) + "*" + parenthesis;
}
void _UpdateSyscallInfos()
{
// Since getting the parameter offsets and actual sizes doesn't work
// as it is now, we overwrite them with values computed using the
// parameter alignment type.
for (int i = 0; i < fSyscallCount; i++) {
gensyscall_syscall_info &syscall = fSyscallInfos[i];
int paramCount = syscall.parameter_count;
gensyscall_parameter_info* parameters = syscall.parameters;
int offset = 0;
for (int k = 0; k < paramCount; k++) {
if (parameters[k].size < PARAMETER_ALIGNMENT)
parameters[k].actual_size = PARAMETER_ALIGNMENT;
else
parameters[k].actual_size = parameters[k].size;
parameters[k].offset = offset;
offset += parameters[k].actual_size;
}
}
}
private:
gensyscall_syscall_info *fSyscallInfos;
SyscallVector* fSyscallVector;
int fSyscallCount;
};

View File

@ -1,22 +1,131 @@
// gensyscalls.h
#ifndef GENSYSCALLS_H
#define GENSYSCALLS_H
#ifndef _GEN_SYSCALLS_H
#define _GEN_SYSCALLS_H
// Type
class Type {
public:
Type(const char* name, int size,
int usedSize,
const char* alignmentTypeName);
~Type() {}
typedef struct gensyscall_parameter_info {
const char *type;
const char *name;
int offset;
int size;
int actual_size;
} gensyscall_parameter_info;
const char* TypeName() const { return fName; }
int Size() const { return fSize; }
int UsedSize() const { return fUsedSize; }
const char* AlignmentTypeName() const
{ return fAlignmentType; }
typedef struct gensyscall_syscall_info {
const char *name;
const char *kernel_name;
const char *return_type;
int parameter_count;
gensyscall_parameter_info *parameters;
} gensyscall_syscall_info;
private:
const char* fName;
int fSize;
int fUsedSize;
const char* fAlignmentType;
};
#endif // _GEN_SYSCALLS_H
// Parameter
class Parameter : public Type {
public:
Parameter(const char* typeName,
const char* parameterName, int size,
int usedSize, int offset,
const char* alignmentTypeName);
~Parameter() {}
const char* ParameterName() const { return fParameterName; }
int Offset() const { return fOffset; }
private:
const char* fParameterName;
int fOffset;
};
// Syscall
class Syscall {
public:
Syscall(const char* name,
const char* kernelName);
~Syscall();
const char* Name() const { return fName; }
const char* KernelName() const { return fKernelName; }
Type* ReturnType() const { return fReturnType; }
int CountParameters() const;
Parameter* ParameterAt(int index) const;
Parameter* LastParameter() const;
template<typename T> void SetReturnType(const char* name);
template<typename T> void AddParameter(const char* typeName,
const char* parameterName);
Type* SetReturnType(const char* name, int size,
int usedSize,
const char* alignmentTypeName);
Parameter* AddParameter(const char* typeName,
const char* parameterName, int size,
int usedSize, int offset,
const char* alignmentTypeName);
private:
struct ParameterVector;
const char* fName;
const char* fKernelName;
Type* fReturnType;
ParameterVector* fParameters;
};
// SyscallVector
class SyscallVector {
public:
SyscallVector();
~SyscallVector();
static SyscallVector* Create();
int CountSyscalls() const;
Syscall* SyscallAt(int index) const;
Syscall* CreateSyscall(const char* name,
const char* kernelName);
private:
struct _SyscallVector;
_SyscallVector* fSyscalls;
};
extern SyscallVector* create_syscall_vector();
#ifndef DONT_INCLUDE_ARCH_GENSYSCALLS_H
// align_to_type
template<typename T>
int
align_to_type(int size)
{
return (size + sizeof(T) - 1) / sizeof(T) * sizeof(T);
}
#include "arch_gensyscalls.h"
// SetReturnType
template<typename T>
void
Syscall::SetReturnType(const char* name)
{
ReturnTypeCreator<T>::Create(this, name);
}
// AddParameter
template<typename T>
void
Syscall::AddParameter(const char* typeName, const char* parameterName)
{
ParameterCreator<T>::Create(this, typeName, parameterName);
}
#endif // !DONT_INCLUDE_ARCH_GENSYSCALLS_H
#endif // GENSYSCALLS_H