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
+68 -58
View File
@@ -1,20 +1,74 @@
SubDir HAIKU_TOP src tools gensyscalls ; SubDir HAIKU_TOP src tools gensyscalls ;
# build gensyscallinfos # preprocess the syscalls header
BuildPlatformMain gensyscallinfos : gensyscallinfos.cpp ; rule PreprocessSyscalls
LinkAgainst gensyscallinfos : $(HOST_LIBSTDC++) ; {
# 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 ] ; local syscallsHeader = [ FGristFiles syscalls.h ] ;
SEARCH on $(syscallsHeader) = [ FDirName $(HAIKU_TOP) headers private kernel ] ; 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 ] ; 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) ; MakeLocateArch $(syscallInfos) ;
rule GenSyscallInfos { rule GenSyscallInfos {
@@ -26,20 +80,23 @@ actions GenSyscallInfos1 {
$(2[1]) $(2[2]) $(1) $(2[1]) $(2[2]) $(1)
} }
GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPP) ; GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPPParsable) ;
SubDirHdrs [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
# build gensyscalls # build gensyscalls
BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos:S=$(SUFOBJ)) ; BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos) ;
LinkAgainst gensyscalls : $(HOST_LIBSTDC++) ; 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 # generate the output files
# place them where there are needed # place them where they are needed
local dir = $(HAIKU_COMMON_DEBUG_OBJECT_DIR) ; local dir = $(HAIKU_COMMON_DEBUG_OBJECT_DIR) ;
MakeLocate <syscalls>syscalls.S.inc : [ FDirName $(dir) system libroot os ] ; MakeLocate <syscalls>syscalls.S.inc : [ FDirName $(dir) system libroot os ] ;
MakeLocate <syscalls>syscall_dispatcher.h : [ FDirName $(dir) system kernel ] ; 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>syscall_table.h : [ FDirName $(dir) system kernel ] ;
MakeLocate <syscalls>strace_syscalls.h : [ FDirName $(dir) bin strace ] ; MakeLocate <syscalls>strace_syscalls.h : [ FDirName $(dir) bin strace ] ;
rule GenSyscallsFile { rule GenSyscallsFile {
Depends $(1) : gensyscalls ; Depends $(1) : gensyscalls ;
GenSyscallsFile1 $(1) : gensyscalls ; GenSyscallsFile1 $(1) : gensyscalls ;
@@ -98,49 +154,3 @@ GenSyscallsDispatcher <syscalls>syscall_dispatcher.h ;
GenSyscallsNumbers <syscalls>syscall_numbers.h ; GenSyscallsNumbers <syscalls>syscall_numbers.h ;
GenSyscallsTable <syscalls>syscall_table.h ; GenSyscallsTable <syscalls>syscall_table.h ;
GenSyscallsSTrace <syscalls>strace_syscalls.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 ;
@@ -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);
}
};
@@ -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);
}
};
+33 -80
View File
@@ -15,7 +15,7 @@
// usage // usage
const char *kUsage = const char *kUsage =
"Usage: gensyscallinfos <header> <calls> <dispatcher>\n" "Usage: gensyscallinfos <header> <syscall infos>\n"
"\n" "\n"
"Given the (preprocessed) header file that defines the syscall prototypes the\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" "command generates a source file consisting of syscall infos, which is needed\n"
@@ -322,16 +322,6 @@ private:
tokenizer.ExpectNextToken("pragma"); tokenizer.ExpectNextToken("pragma");
tokenizer.ExpectNextToken("syscalls"); tokenizer.ExpectNextToken("syscalls");
tokenizer.ExpectNextToken("end"); 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) void _WriteSyscallInfoFile(const char *filename)
@@ -340,86 +330,49 @@ private:
ofstream file(filename, ofstream::out | ofstream::trunc); ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open()) if (!file.is_open())
throw new IOException(string("Failed to open `") + filename + "'."); throw new IOException(string("Failed to open `") + filename + "'.");
// write preamble // write preamble
file << "#include \"gensyscalls.h\"" << endl; file << "#include \"gensyscalls.h\"" << endl;
file << "#include \"syscalls.h\"" << endl; file << "#include \"syscalls.h.pp\"" << endl;
file << 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++) { for (int i = 0; i < (int)fSyscalls.size(); i++) {
const Syscall &syscall = fSyscalls[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(); int paramCount = syscall.CountParameters();
// write the parameter infos
file << "static gensyscall_parameter_info " << paramInfoName
<< "[] = {" << endl;
for (int k = 0; k < paramCount; k++) { for (int k = 0; k < paramCount; k++) {
const NamedType &param = syscall.ParameterAt(k); const NamedType &param = syscall.ParameterAt(k);
file << "\t{ \"" << param.type << "\", \"" << param.name // syscall->AddParameter<ParameterType>("parameterTypeName",
<< "\", 0, " << "sizeof(" << syscall.ParameterAt(k).type // "parameterName");
<< "), 0 }," << endl; 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; file << endl;
} }
// write the syscall infos
file << "static gensyscall_syscall_info " // postamble
"gensyscall_syscall_infos[] = {" << endl; file << "\treturn syscallVector;" << 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;
file << "}" << endl; file << "}" << endl;
} }
+207 -69
View File
@@ -1,16 +1,19 @@
// gensyscalls.cpp // 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 <cstdio>
#include <cstdlib> #include <cstdlib>
#include <fstream> #include <fstream>
#include <string> #include <string>
#include <vector>
#include "arch_config.h"
#include "gensyscalls.h" #include "gensyscalls.h"
#include "gensyscalls_common.h" #include "gensyscalls_common.h"
extern "C" gensyscall_syscall_info *gensyscall_get_infos(int *count); using std::vector;
// usage // usage
const char *kUsage = const char *kUsage =
@@ -38,10 +41,160 @@ print_usage(bool error)
fprintf((error ? stderr : stdout), kUsage); 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 // Main
class Main { class Main {
public: public:
@@ -94,8 +247,8 @@ public:
return 1; return 1;
} }
} }
fSyscallInfos = gensyscall_get_infos(&fSyscallCount); fSyscallVector = create_syscall_vector();
_UpdateSyscallInfos(); fSyscallCount = fSyscallVector->CountSyscalls();
if (!syscallsFile && !dispatcherFile && !numbersFile && !tableFile if (!syscallsFile && !dispatcherFile && !numbersFile && !tableFile
&& !straceFile) { && !straceFile) {
printf("Found %d syscalls.\n", fSyscallCount); printf("Found %d syscalls.\n", fSyscallCount);
@@ -121,20 +274,21 @@ public:
ofstream file(filename, ofstream::out | ofstream::trunc); ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open()) if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'."); throw IOException(string("Failed to open `") + filename + "'.");
// output the syscalls definitions // output the syscalls definitions
for (int i = 0; i < fSyscallCount; i++) { for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i]; const Syscall* syscall = fSyscallVector->SyscallAt(i);
int paramCount = syscall.parameter_count; int paramCount = syscall->CountParameters();
int paramSize = 0; int paramSize = 0;
gensyscall_parameter_info* parameters = syscall.parameters;
// XXX: Currently the SYSCALL macros support 4 byte aligned // XXX: Currently the SYSCALL macros support 4 byte aligned
// parameters only. This has to change, of course. // parameters only. This has to change, of course.
for (int k = 0; k < paramCount; k++) { 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; paramSize += (size + 3) / 4 * 4;
} }
file << "SYSCALL" << (paramSize / 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); ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open()) if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'."); throw IOException(string("Failed to open `") + filename + "'.");
// output the case statements // output the case statements
for (int i = 0; i < fSyscallCount; i++) { 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 << "case " << i << ":" << endl;
file << "\t"; file << "\t";
if (string(syscall.return_type) != "void") if (string(syscall->ReturnType()->TypeName()) != "void")
file << "*call_ret = "; file << "*call_ret = ";
file << syscall.kernel_name << "("; file << syscall->KernelName() << "(";
int paramCount = syscall.parameter_count; int paramCount = syscall->CountParameters();
if (paramCount > 0) { if (paramCount > 0) {
gensyscall_parameter_info* parameters = syscall.parameters; Parameter* parameter = syscall->ParameterAt(0);
if (parameters[0].size < PARAMETER_ALIGNMENT) { if (parameter->AlignmentTypeName()) {
file << "(" << parameters[0].type << ")*(" file << "(" << parameter->TypeName() << ")*("
<< "FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE" << parameter->AlignmentTypeName()
<< "*)args"; << "*)args";
} else { } else {
file << "*(" << _GetPointerType(parameters[0].type) file << "*(" << _GetPointerType(parameter->TypeName())
<< ")args"; << ")args";
} }
for (int k = 1; k < paramCount; k++) { for (int k = 1; k < paramCount; k++) {
if (parameters[k].size < PARAMETER_ALIGNMENT) { parameter = syscall->ParameterAt(k);
file << ", (" << parameters[k].type << ")*(" if (parameter->AlignmentTypeName()) {
<< "FUNCTION_CALL_PARAMETER_ALIGNMENT_TYPE" file << ", (" << parameter->TypeName() << ")*("
<< "*)((char*)args + " << parameters[k].offset << parameter->AlignmentTypeName()
<< "*)((char*)args + " << parameter->Offset()
<< ")"; << ")";
} else { } else {
file << ", *(" << _GetPointerType(parameters[k].type) file << ", *(" << _GetPointerType(parameter->TypeName())
<< ")((char*)args + " << parameters[k].offset << ")((char*)args + " << parameter->Offset()
<< ")"; << ")";
} }
} }
@@ -187,16 +343,19 @@ public:
ofstream file(filename, ofstream::out | ofstream::trunc); ofstream file(filename, ofstream::out | ofstream::trunc);
if (!file.is_open()) if (!file.is_open())
throw IOException(string("Failed to open `") + filename + "'."); throw IOException(string("Failed to open `") + filename + "'.");
// output the defines // output the defines
const char *prefix = "_user_"; const char *prefix = "_user_";
size_t prefixLen = strlen(prefix); size_t prefixLen = strlen(prefix);
for (int i = 0; i < fSyscallCount; i++) { for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i]; const Syscall* syscall = fSyscallVector->SyscallAt(i);
string name(syscall.kernel_name); string name(syscall->KernelName());
// drop the leading "_user_" prefix // drop the leading "_user_" prefix
if (name.find(prefix) != 0) if (name.find(prefix) != 0)
throw Exception(string("Bad kernel name: `") + name + "'."); throw Exception(string("Bad kernel name: `") + name + "'.");
name = string(name, prefixLen); name = string(name, prefixLen);
// convert to upper case (is there no function for that?) // convert to upper case (is there no function for that?)
string defineName; string defineName;
for (int k = 0; k < (int)name.length(); k++) for (int k = 0; k < (int)name.length(); k++)
@@ -221,18 +380,15 @@ public:
// the syscall infos // the syscall infos
for (int i = 0; i < fSyscallCount; i++) { for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i]; const Syscall* syscall = fSyscallVector->SyscallAt(i);
// get the parameter size // get the parameter size
int paramSize = 0; int paramSize = 0;
if (syscall.parameter_count > 0) { if (Parameter* parameter = syscall->LastParameter())
const gensyscall_parameter_info &lastParam paramSize = parameter->Offset() + parameter->UsedSize();
= syscall.parameters[syscall.parameter_count - 1];
paramSize = lastParam.offset + lastParam.actual_size;
}
// output the info for the syscall // output the info for the syscall
file << "\t{ " << syscall.kernel_name << ", " file << "\t{ " << syscall->KernelName() << ", "
<< paramSize << " }," << endl; << paramSize << " }," << endl;
} }
@@ -260,7 +416,7 @@ public:
// iterate through the syscalls // iterate through the syscalls
for (int i = 0; i < fSyscallCount; i++) { for (int i = 0; i < fSyscallCount; i++) {
const gensyscall_syscall_info &syscall = fSyscallInfos[i]; const Syscall* syscall = fSyscallVector->SyscallAt(i);
if (i % chunkSize == 0) { if (i % chunkSize == 0) {
// chunk end // chunk end
@@ -273,29 +429,32 @@ public:
// spacing, comment // spacing, comment
file << endl; file << endl;
file << "\t// " << syscall.name << endl; file << "\t// " << syscall->Name() << endl;
// create the return type handler // create the return type handler
file << "\thandler = TypeHandlerFactory<" << syscall.return_type const char* returnType = syscall->ReturnType()->TypeName();
file << "\thandler = TypeHandlerFactory<"
<< returnType
<< ">::Create();" << endl; << ">::Create();" << endl;
// create the syscall // create the syscall
file << "\tsyscall = new Syscall(\"" << syscall.name << "\", " file << "\tsyscall = new Syscall(\"" << syscall->Name() << "\", "
<< "\"" << syscall.return_type << "\", "<< "handler);" << endl; << "\"" << returnType << "\", "<< "handler);" << endl;
file << "\tsyscalls.push_back(syscall);" << endl; file << "\tsyscalls.push_back(syscall);" << endl;
// add the parameters // add the parameters
for (int k = 0; k < syscall.parameter_count; k++) { int paramCount = syscall->CountParameters();
const gensyscall_parameter_info &parameter for (int k = 0; k < paramCount; k++) {
= syscall.parameters[k]; const Parameter* parameter = syscall->ParameterAt(k);
// create the parameter type handler // create the parameter type handler
file << "\thandler = TypeHandlerFactory<" file << "\thandler = TypeHandlerFactory<"
<< parameter.type << ">::Create();" << endl; << parameter->TypeName() << ">::Create();" << endl;
// add the parameter // add the parameter
file << "\tsyscall->AddParameter(\"" << parameter.name << "\", " file << "\tsyscall->AddParameter(\""
<< parameter.offset << ", \"" << parameter.type << parameter->ParameterName() << "\", "
<< parameter->Offset() << ", \"" << parameter->TypeName()
<< "\", handler);" << endl; << "\", handler);" << endl;
} }
} }
@@ -316,29 +475,8 @@ public:
return string(type, parenthesis - type) + "*" + parenthesis; 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: private:
gensyscall_syscall_info *fSyscallInfos; SyscallVector* fSyscallVector;
int fSyscallCount; int fSyscallCount;
}; };
+127 -18
View File
@@ -1,22 +1,131 @@
// gensyscalls.h #ifndef GENSYSCALLS_H
#define GENSYSCALLS_H
#ifndef _GEN_SYSCALLS_H // Type
#define _GEN_SYSCALLS_H class Type {
public:
Type(const char* name, int size,
int usedSize,
const char* alignmentTypeName);
~Type() {}
typedef struct gensyscall_parameter_info { const char* TypeName() const { return fName; }
const char *type; int Size() const { return fSize; }
const char *name; int UsedSize() const { return fUsedSize; }
int offset; const char* AlignmentTypeName() const
int size; { return fAlignmentType; }
int actual_size;
} gensyscall_parameter_info;
typedef struct gensyscall_syscall_info { private:
const char *name; const char* fName;
const char *kernel_name; int fSize;
const char *return_type; int fUsedSize;
int parameter_count; const char* fAlignmentType;
gensyscall_parameter_info *parameters; };
} gensyscall_syscall_info;
#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