diff --git a/src/tools/gensyscalls/Jamfile b/src/tools/gensyscalls/Jamfile index 51e3197f9b..02dbeb495b 100644 --- a/src/tools/gensyscalls/Jamfile +++ b/src/tools/gensyscalls/Jamfile @@ -1,17 +1,41 @@ SubDir HAIKU_TOP src tools gensyscalls ; +SubDirHdrs [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ; + + +# What want to do here is analyze the header and generate headers +# and sources containing information about the syscalls (like what parameters +# of what sizes and types they take, etc.) which will be used in other places +# (e.g. the kernel code or the strace tool). +# +# The strategy to achieve this is: +# * Preprocess the header, so that it is easier to parse. +# * Feed the preprocessed header to the gensyscallinfos tool. It will generate +# a source file, gensyscalls_infos.cpp, which implements a function that +# builds a table with all the syscall info information we need. The source +# file needs specific infos about sizes of types, which aren't easily +# available. That's why gensyscallinfos also generates a source file which +# via the CreateAsmStructOffsetsHeader rule is turned into a header with +# macro definitions for those type size. The header is included by +# gensyscalls_infos.cpp. +# * gensyscalls.cpp and the generated gensyscalls_infos.cpp are compiled into +# the gensyscalls tool. +# * gensyscalls has options to generate the various output files: +# - syscalls.S.inc: Used to define the syscall functions in libroot. +# - syscall_dispatcher.h: Big "switch" statement for the syscall +# dispatcher in the kernel. +# - syscall_numbers.h: Macro definitions assigning indices to the +# syscalls. +# - syscall_table.h: An array with syscall information in the +# kernel. Used for dispatching syscalls e.g. for x86. +# - strace_syscalls.h: Syscall information needed by strace. + + # preprocess the syscalls header rule PreprocessSyscalls { - # PreprocessSyscalls :
: ; - # - local parsable = $(3) ; - local parsableDefine ; - - if $(parsable) { - parsableDefine = GEN_SYSCALL_INFOS_PROCESSING ; - } + # PreprocessSyscalls :
; Depends $(<) : $(>) ; @@ -30,7 +54,7 @@ rule PreprocessSyscalls HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ; HDRGRIST on $(>) = $(HDRGRIST) ; - DEFINES on $(<) += $(HAIKU_DEFINES) $(parsableDefine) ; + DEFINES on $(<) += $(HAIKU_DEFINES) GEN_SYSCALL_INFOS_PROCESSING ; CCFLAGS on $(<) += $(HAIKU_CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ; CCHDRS on $(<) = [ FIncludes $(headers) : $(HAIKU_LOCAL_INCLUDES_OPTION) ] @@ -47,15 +71,11 @@ actions PreprocessSyscalls local syscallsHeader = [ FGristFiles syscalls.h ] ; SEARCH on $(syscallsHeader) = [ FDirName $(HAIKU_TOP) headers private system ] ; -# We generate two preprocessed headers. One for parsing by gensyscallinfos -# (it contains #pragmas) and one for inclusion by the generated -# gensyscalls_infos.cpp. +# Generate the preprocessed syscalls.h header. It will be parsed by +# gensyscallinfos (it contains marker #pragmas). local syscallsHeaderPPParsable = [ FGristFiles syscalls.h.pp.parsable ] ; -local syscallsHeaderPP = [ FGristFiles syscalls.h.pp ] ; -MakeLocateArch $(syscallsHeaderPPParsable) $(syscallsHeaderPP) ; - -PreprocessSyscalls $(syscallsHeaderPPParsable) : $(syscallsHeader) : true ; -PreprocessSyscalls $(syscallsHeaderPP) : $(syscallsHeader) ; +MakeLocateArch $(syscallsHeaderPPParsable) ; +PreprocessSyscalls $(syscallsHeaderPPParsable) : $(syscallsHeader) ; # build gensyscallinfos @@ -66,35 +86,45 @@ BuildPlatformMain gensyscallinfos ; -# generate the syscall infos source file +# generate the syscall infos source file and the source for the header it +# includes local syscallInfos = [ FGristFiles gensyscalls_infos.cpp ] ; -MakeLocateArch $(syscallInfos) ; +local syscallTypesSizesSource = [ FGristFiles syscall_types_sizes.h.cpp ] ; +local syscallTypesSizes = [ FGristFiles syscall_types_sizes.h ] ; +MakeLocateArch $(syscallInfos) $(syscallTypesSizesSource) $(syscallTypesSizes) ; -rule GenSyscallInfos { +rule GenSyscallInfos +{ Depends $(1) : gensyscallinfos $(2) ; GenSyscallInfos1 $(1) : gensyscallinfos $(2) ; } -actions GenSyscallInfos1 { +actions GenSyscallInfos1 +{ $(2[1]) $(2[2]) $(1) } -GenSyscallInfos $(syscallInfos) : $(syscallsHeaderPPParsable) ; +GenSyscallInfos $(syscallInfos) $(syscallTypesSizesSource) + : $(syscallsHeaderPPParsable) ; -SubDirHdrs [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ; +TARGET_HDRS on $(syscallTypesSizes) + = [ on $(syscallTypesSizes) return $(TARGET_HDRS) ] + $(TARGET_PRIVATE_SYSTEM_HEADERS) ; +CreateAsmStructOffsetsHeader $(syscallTypesSizes) : $(syscallTypesSizesSource) ; + +#Includes $(syscallInfos) : $(syscallTypesSizes) ; + # explicitly tell jam about the inclusion of the generated header +Depends $(syscallInfos:S=$(SUFOBJ)) : $(syscallTypesSizes) ; + # NOTE: Jam messes up the "Includes" declaration, so we have to declare + # the dependency more directly. # build gensyscalls -ObjectDefines $(syscallInfos) : HAIKU_BUILD_COMPATIBILITY_H ; - # Prevent the inclusion of HaikuBuildCompatibility.h. TODO: Very hacky! BuildPlatformMain gensyscalls : gensyscalls.cpp $(syscallInfos) ; LinkAgainst gensyscalls : $(HOST_LIBSTDC++) $(HOST_LIBSUPC++) ; -# Explicitly tell jam that gensyscalls.cpp includes the generated header. -Includes [ FGristFiles gensyscalls.cpp ] : $(syscallsHeaderPP) ; - # generate the output files @@ -106,53 +136,20 @@ MakeLocate syscall_numbers.h : [ FDirName $(dir) system kernel ] ; MakeLocate syscall_table.h : [ FDirName $(dir) system kernel ] ; MakeLocate strace_syscalls.h : [ FDirName $(dir) bin debug strace ] ; -rule GenSyscallsFile { - Depends $(1) : gensyscalls ; - GenSyscallsFile1 $(1) : gensyscalls ; +rule GenSyscallsFile file : option +{ + GENSYSCALLS_FILE_OPTION on $(file) = $(option) ; + Depends $(file) : gensyscalls ; + GenSyscallsFile1 $(file) : gensyscalls ; } -actions GenSyscallsFile1 { - $(2[1]) -c $(1) +actions GenSyscallsFile1 +{ + $(2[1]) $(GENSYSCALLS_FILE_OPTION) $(1) } -rule GenSyscallsDispatcher { - Depends $(1) : gensyscalls ; - GenSyscallsDispatcher1 $(1) : gensyscalls ; -} - -actions GenSyscallsDispatcher1 { - $(2[1]) -d $(1) -} - -rule GenSyscallsNumbers { - Depends $(1) : gensyscalls ; - GenSyscallsNumbers1 $(1) : gensyscalls ; -} - -actions GenSyscallsNumbers1 { - $(2[1]) -n $(1) -} - -rule GenSyscallsTable { - Depends $(1) : gensyscalls ; - GenSyscallsTable1 $(1) : gensyscalls ; -} - -actions GenSyscallsTable1 { - $(2[1]) -t $(1) -} - -rule GenSyscallsSTrace { - Depends $(1) : gensyscalls ; - GenSyscallsSTrace1 $(1) : gensyscalls ; -} - -actions GenSyscallsSTrace1 { - $(2[1]) -s $(1) -} - -GenSyscallsFile syscalls.S.inc ; -GenSyscallsDispatcher syscall_dispatcher.h ; -GenSyscallsNumbers syscall_numbers.h ; -GenSyscallsTable syscall_table.h ; -GenSyscallsSTrace strace_syscalls.h ; +GenSyscallsFile syscalls.S.inc : -c ; +GenSyscallsFile syscall_dispatcher.h : -d ; +GenSyscallsFile syscall_numbers.h : -n ; +GenSyscallsFile syscall_table.h : -t ; +GenSyscallsFile strace_syscalls.h : -s ; diff --git a/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h b/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h index c12ea3f356..d67d074574 100644 --- a/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/arm/arch_gensyscalls.h @@ -1 +1,2 @@ -#include "arch/generic/generic_gensyscalls.h" +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int diff --git a/src/tools/gensyscalls/arch/generic/generic_gensyscalls.h b/src/tools/gensyscalls/arch/generic/generic_gensyscalls.h deleted file mode 100644 index 28f51bea95..0000000000 --- a/src/tools/gensyscalls/arch/generic/generic_gensyscalls.h +++ /dev/null @@ -1,51 +0,0 @@ -// 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/m68k/arch_gensyscalls.h b/src/tools/gensyscalls/arch/m68k/arch_gensyscalls.h index c12ea3f356..d67d074574 100644 --- a/src/tools/gensyscalls/arch/m68k/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/m68k/arch_gensyscalls.h @@ -1 +1,2 @@ -#include "arch/generic/generic_gensyscalls.h" +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int diff --git a/src/tools/gensyscalls/arch/mipsel/arch_gensyscalls.h b/src/tools/gensyscalls/arch/mipsel/arch_gensyscalls.h index c12ea3f356..d67d074574 100644 --- a/src/tools/gensyscalls/arch/mipsel/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/mipsel/arch_gensyscalls.h @@ -1 +1,2 @@ -#include "arch/generic/generic_gensyscalls.h" +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int diff --git a/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h b/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h index c12ea3f356..d67d074574 100644 --- a/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h @@ -1 +1,2 @@ -#include "arch/generic/generic_gensyscalls.h" +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int diff --git a/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h b/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h index c12ea3f356..d67d074574 100644 --- a/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h +++ b/src/tools/gensyscalls/arch/x86/arch_gensyscalls.h @@ -1 +1,2 @@ -#include "arch/generic/generic_gensyscalls.h" +#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int +#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int diff --git a/src/tools/gensyscalls/gensyscallinfos.cpp b/src/tools/gensyscalls/gensyscallinfos.cpp index 7fade0c407..cf82831459 100644 --- a/src/tools/gensyscalls/gensyscallinfos.cpp +++ b/src/tools/gensyscalls/gensyscallinfos.cpp @@ -15,9 +15,17 @@ #include "gensyscalls_common.h" +#include "arch_gensyscalls.h" + // for the alignment type macros (only for the type names) + + +// macro trickery to create a string literal +#define MAKE_STRING(x) #x +#define EVAL_MACRO(macro, x) macro(x) + const char* kUsage = - "Usage: gensyscallinfos
\n" + "Usage: gensyscallinfos
\n" "\n" "Given the (preprocessed) header file that defines the syscall prototypes " "the\n" @@ -30,7 +38,11 @@ const char* kUsage = " syscall prototypes.\n" " - Output: The syscall infos source file needed " "to\n" - " build gensyscalls."; + " build gensyscalls.\n" + " - Output: A source file that will by another " + "build\n" + " step turned into a header file included by\n" + " .\n"; static void @@ -285,12 +297,13 @@ public: print_usage(false); return 0; } - if (argc != 3) { + if (argc != 4) { print_usage(true); return 1; } _ParseSyscalls(argv[1]); _WriteSyscallInfoFile(argv[2]); + _WriteSyscallTypeSizes(argv[3]); return 0; } @@ -335,7 +348,19 @@ private: // write preamble file << "#include \"gensyscalls.h\"" << endl; - file << "#include \"syscalls.h.pp\"" << endl; + file << "#include \"syscall_types_sizes.h\"" << endl; + file << endl; + + file << "const char* const kReturnTypeAlignmentType = \"" + EVAL_MACRO(MAKE_STRING, SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE) + << "\";" << endl; + file << "const char* const kParameterAlignmentType = \"" + EVAL_MACRO(MAKE_STRING, SYSCALL_PARAMETER_ALIGNMENT_TYPE) + << "\";" << endl; + file << "const int kReturnTypeAlignmentSize = " + "SYSCALL_RETURN_TYPE_ALIGNMENT_SIZE;" << endl; + file << "const int kParameterAlignmentSize = " + "SYSCALL_PARAMETER_ALIGNMENT_SIZE;" << endl; file << endl; file << "SyscallVector* create_syscall_vector() {" << endl; @@ -355,20 +380,22 @@ private: const Type& returnType = syscall.GetReturnType(); - // syscall->SetReturnType("returnType"); - file << "\tsyscall->SetReturnType<" << returnType.type - << ">(\"" << returnType.type << "\");" << endl; + // syscall->SetReturnType<(SYSCALL_RETURN_TYPE_SIZE_, + // "returnType"); + file << "\tsyscall->SetReturnType(" + << "SYSCALL_RETURN_TYPE_SIZE_" << i << ", \"" + << returnType.type << "\");" << endl; // parameters int paramCount = syscall.CountParameters(); for (int k = 0; k < paramCount; k++) { const NamedType& param = syscall.ParameterAt(k); - // syscall->AddParameter("parameterTypeName", - // "parameterName"); - file << "\tsyscall->AddParameter<" - << param.type << ">(\"" - << param.type << "\", \"" - << param.name << "\");" << endl; + // syscall->AddParameter(SYSCALL_PARAMETER_SIZE__, + // "parameterTypeName", "parameterName"); + file << "\tsyscall->AddParameter(" + << "SYSCALL_PARAMETER_SIZE_" << i << "_" << k + << ", \"" << param.type << "\", \"" << param.name << "\");" + << endl; } file << endl; } @@ -378,6 +405,54 @@ private: file << "}" << endl; } + void _WriteSyscallTypeSizes(const char* filename) + { + // open the syscall info file + ofstream file(filename, ofstream::out | ofstream::trunc); + if (!file.is_open()) + throw new IOException(string("Failed to open `") + filename + "'."); + + // write preamble + file << "#include " << endl; + file << "#include " << endl; + file << endl; + file << "#include \"arch_gensyscalls.h\"" << endl; + file << endl; + file << "void dummy() {" << endl; + + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_RETURN_TYPE_ALIGNMENT_SIZE, " + "sizeof(SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE));" << endl; + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_PARAMETER_ALIGNMENT_SIZE, " + "sizeof(SYSCALL_PARAMETER_ALIGNMENT_TYPE));" << endl; + file << endl; + + // syscalls + for (int i = 0; i < (int)fSyscalls.size(); i++) { + const Syscall& syscall = fSyscalls[i]; + const Type& returnType = syscall.GetReturnType(); + + if (returnType.type == "void") { + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_RETURN_TYPE_SIZE_" + << i << ", 0);" << endl; + } else { + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_RETURN_TYPE_SIZE_" + << i << ", sizeof(" << returnType.type << "));" << endl; + } + + // parameters + int paramCount = syscall.CountParameters(); + for (int k = 0; k < paramCount; k++) { + const NamedType& param = syscall.ParameterAt(k); + file << "DEFINE_COMPUTED_ASM_MACRO(SYSCALL_PARAMETER_SIZE_" << i + << "_" << k << ", sizeof(" << param.type << "));" << endl; + } + file << endl; + } + + // postamble + file << "}" << endl; + } + void _ParseSyscall(Tokenizer& tokenizer, Syscall& syscall) { // get return type and function name diff --git a/src/tools/gensyscalls/gensyscalls.cpp b/src/tools/gensyscalls/gensyscalls.cpp index 29968090fd..0a11045a10 100644 --- a/src/tools/gensyscalls/gensyscalls.cpp +++ b/src/tools/gensyscalls/gensyscalls.cpp @@ -1,13 +1,9 @@ /* - * Copyright 2004-2008, Ingo Weinhold, ingo_weinhold@gmx.de. + * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de. * Distributed under the terms of the MIT License. */ -// Don't include arch_gensyscalls.h. It's only needed when creating the -// syscall vector. -#define DONT_INCLUDE_ARCH_GENSYSCALLS_H 1 - #include "gensyscalls.h" #include @@ -130,6 +126,19 @@ Syscall::LastParameter() const } +void +Syscall::SetReturnType(int size, const char* name) +{ + int usedSize = (size + kReturnTypeAlignmentSize - 1) + / kReturnTypeAlignmentSize * kReturnTypeAlignmentSize; + const char* alignmentType + = size != usedSize && size < kReturnTypeAlignmentSize + ? kReturnTypeAlignmentType : 0; + + SetReturnType(name, size, usedSize, alignmentType); +} + + Type* Syscall::SetReturnType(const char* name, int size, int usedSize, const char* alignmentTypeName) @@ -149,6 +158,24 @@ Syscall::AddParameter(const char* typeName, const char* parameterName, return parameter; } +void +Syscall::AddParameter(int size, const char* typeName, const char* parameterName) +{ + // compute offset + int offset = 0; + if (Parameter* previous = LastParameter()) + offset = previous->Offset() + previous->UsedSize(); + + int usedSize = (size + kParameterAlignmentSize - 1) + / kParameterAlignmentSize * kParameterAlignmentSize; + const char* alignmentType + = size != usedSize && size < kParameterAlignmentSize + ? kParameterAlignmentType : 0; + + AddParameter(typeName, parameterName, size, usedSize, offset, + alignmentType); +} + // #pragma mark - SyscallVector diff --git a/src/tools/gensyscalls/gensyscalls.h b/src/tools/gensyscalls/gensyscalls.h index 25630efd1e..fe8a19542d 100644 --- a/src/tools/gensyscalls/gensyscalls.h +++ b/src/tools/gensyscalls/gensyscalls.h @@ -1,15 +1,16 @@ +/* + * Copyright 2004-2009, Ingo Weinhold, ingo_weinhold@gmx.de. + * Distributed under the terms of the MIT License. + */ #ifndef GENSYSCALLS_H #define GENSYSCALLS_H -// TODO: is pre-processed with the cross-compiler, but the -// pre-processed header is compiled with the native compiler. Unfortunately -// is included indirectly, which results in a missing typedef when -// the host compiler is gcc 2 and the native compiler gcc 4. The type is never -// really used, so this doesn't really matter what it is defined to. The better -// solution would be to remove the dependency, though. -#if __GNUC__ == 2 -typedef void *__builtin_va_list; -#endif + +extern const char* const kReturnTypeAlignmentType; +extern const char* const kParameterAlignmentType; +extern const int kReturnTypeAlignmentSize; +extern const int kParameterAlignmentSize; + // Type class Type { @@ -64,13 +65,12 @@ public: Parameter* ParameterAt(int index) const; Parameter* LastParameter() const; - template void SetReturnType(const char* name); - template void AddParameter(const char* typeName, - const char* parameterName); - + void SetReturnType(int size, const char* name); Type* SetReturnType(const char* name, int size, int usedSize, const char* alignmentTypeName); + void AddParameter(int size, const char* typeName, + const char* parameterName); Parameter* AddParameter(const char* typeName, const char* parameterName, int size, int usedSize, int offset, @@ -108,34 +108,4 @@ private: 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