From 2ae568931fcac7deb9f1e6ff4e47213fbfe4029b Mon Sep 17 00:00:00 2001 From: Ingo Weinhold Date: Mon, 28 Nov 2005 12:53:55 +0000 Subject: [PATCH] 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 --- src/tools/gensyscalls/Jamfile | 126 ++++---- .../gensyscalls/arch/ppc/arch_gensyscalls.h | 51 ++++ .../gensyscalls/arch/x86/arch_gensyscalls.h | 51 ++++ src/tools/gensyscalls/gensyscallinfos.cpp | 113 +++---- src/tools/gensyscalls/gensyscalls.cpp | 278 +++++++++++++----- src/tools/gensyscalls/gensyscalls.h | 145 +++++++-- 6 files changed, 538 insertions(+), 226 deletions(-) create mode 100644 src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h create mode 100644 src/tools/gensyscalls/arch/x86/arch_gensyscalls.h diff --git a/src/tools/gensyscalls/Jamfile b/src/tools/gensyscalls/Jamfile index 59e0ca9db5..8c392b5076 100644 --- a/src/tools/gensyscalls/Jamfile +++ b/src/tools/gensyscalls/Jamfile @@ -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 :
: ; + # + 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.S.inc : [ FDirName $(dir) system libroot os ] ; MakeLocate syscall_dispatcher.h : [ FDirName $(dir) system kernel ] ; @@ -47,7 +104,6 @@ MakeLocate syscall_numbers.h : [ FDirName $(dir) system kernel ] ; MakeLocate syscall_table.h : [ FDirName $(dir) system kernel ] ; MakeLocate strace_syscalls.h : [ FDirName $(dir) bin strace ] ; - rule GenSyscallsFile { Depends $(1) : gensyscalls ; GenSyscallsFile1 $(1) : gensyscalls ; @@ -98,49 +154,3 @@ GenSyscallsDispatcher syscall_dispatcher.h ; GenSyscallsNumbers syscall_numbers.h ; GenSyscallsTable syscall_table.h ; GenSyscallsSTrace 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 ; diff --git a/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h b/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h new file mode 100644 index 0000000000..cd6707b8a2 --- /dev/null +++ b/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h @@ -0,0 +1,51 @@ +// Included by gensyscalls. + +typedef int AlignmentType; +static const char* kAlignmentType = "int"; +static const int kAlignment = sizeof(AlignmentType); + +// ReturnTypeCreator +template +class ReturnTypeCreator { +public: + static void Create(Syscall* syscall, const char* name) + { + int size = sizeof(T); + int usedSize = align_to_type(size); + const char* alignmentType + = (size != usedSize && size < kAlignment ? kAlignmentType : 0); + + syscall->SetReturnType(name, size, usedSize, alignmentType); + } +}; + +template<> +class ReturnTypeCreator { +public: + static void Create(Syscall* syscall, const char* name) + { + syscall->SetReturnType(name, 0, 0, 0); + } +}; + +// ParameterCreator +template +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(size); + const char* alignmentType + = (size != usedSize && size < kAlignment ? kAlignmentType : 0); + + syscall->AddParameter(typeName, parameterName, size, usedSize, offset, + alignmentType); + } +}; diff --git a/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h b/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h new file mode 100644 index 0000000000..cd6707b8a2 --- /dev/null +++ b/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h @@ -0,0 +1,51 @@ +// Included by gensyscalls. + +typedef int AlignmentType; +static const char* kAlignmentType = "int"; +static const int kAlignment = sizeof(AlignmentType); + +// ReturnTypeCreator +template +class ReturnTypeCreator { +public: + static void Create(Syscall* syscall, const char* name) + { + int size = sizeof(T); + int usedSize = align_to_type(size); + const char* alignmentType + = (size != usedSize && size < kAlignment ? kAlignmentType : 0); + + syscall->SetReturnType(name, size, usedSize, alignmentType); + } +}; + +template<> +class ReturnTypeCreator { +public: + static void Create(Syscall* syscall, const char* name) + { + syscall->SetReturnType(name, 0, 0, 0); + } +}; + +// ParameterCreator +template +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(size); + const char* alignmentType + = (size != usedSize && size < kAlignment ? kAlignmentType : 0); + + syscall->AddParameter(typeName, parameterName, size, usedSize, offset, + alignmentType); + } +}; diff --git a/src/tools/gensyscalls/gensyscallinfos.cpp b/src/tools/gensyscalls/gensyscallinfos.cpp index 912fa89417..4a4f23b944 100644 --- a/src/tools/gensyscalls/gensyscallinfos.cpp +++ b/src/tools/gensyscalls/gensyscallinfos.cpp @@ -15,7 +15,7 @@ // usage const char *kUsage = -"Usage: gensyscallinfos
\n" +"Usage: gensyscallinfos
\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"); + 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 ¶m = syscall.ParameterAt(k); - file << "\t{ \"" << param.type << "\", \"" << param.name - << "\", 0, " << "sizeof(" << syscall.ParameterAt(k).type - << "), 0 }," << endl; + // syscall->AddParameter("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; } diff --git a/src/tools/gensyscalls/gensyscalls.cpp b/src/tools/gensyscalls/gensyscalls.cpp index a81ede7df0..9ec64bd5f1 100644 --- a/src/tools/gensyscalls/gensyscalls.cpp +++ b/src/tools/gensyscalls/gensyscalls.cpp @@ -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 #include #include #include - -#include "arch_config.h" +#include #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 { }; +// 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 { +}; + + +// 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 ¶meter - = 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,30 +475,9 @@ 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; - int fSyscallCount; + SyscallVector* fSyscallVector; + int fSyscallCount; }; // main diff --git a/src/tools/gensyscalls/gensyscalls.h b/src/tools/gensyscalls/gensyscalls.h index 8628480810..0c7ec2dcc8 100644 --- a/src/tools/gensyscalls/gensyscalls.h +++ b/src/tools/gensyscalls/gensyscalls.h @@ -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 void SetReturnType(const char* name); + template 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 +int +align_to_type(int size) +{ + return (size + sizeof(T) - 1) / sizeof(T) * sizeof(T); +} + +#include "arch_gensyscalls.h" + +// SetReturnType +template +void +Syscall::SetReturnType(const char* name) +{ + ReturnTypeCreator::Create(this, name); +} + +// AddParameter +template +void +Syscall::AddParameter(const char* typeName, const char* parameterName) +{ + ParameterCreator::Create(this, typeName, parameterName); +} + +#endif // !DONT_INCLUDE_ARCH_GENSYSCALLS_H + +#endif // GENSYSCALLS_H