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