Changed the way the syscall infos are generated. We no longer include the

preprocessed <syscalls.h> header in sources compiled for the build platform.
Instead we're generating macros for the return type and parameter type sizes
via the CreateAsmStructOffsetsHeader rule (no template magic anymore) and
thus get a clear separation of host and target code, resulting in better
portability (although surprisingly enough the build already worked on 64 bit
hosts).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@34323 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Ingo Weinhold
2009-11-27 21:00:37 +00:00
parent aeb728e132
commit 59d6284b7b
10 changed files with 214 additions and 191 deletions
+71 -74
View File
@@ -1,17 +1,41 @@
SubDir HAIKU_TOP src tools gensyscalls ;
SubDirHdrs [ FDirName $(SUBDIR) arch $(TARGET_ARCH) ] ;
# What want to do here is analyze the <syscalls.h> 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 <syscalls.h> 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>syscalls.S.inc: Used to define the syscall functions in libroot.
# - <syscalls>syscall_dispatcher.h: Big "switch" statement for the syscall
# dispatcher in the kernel.
# - <syscalls>syscall_numbers.h: Macro definitions assigning indices to the
# syscalls.
# - <syscalls>syscall_table.h: An array with syscall information in the
# kernel. Used for dispatching syscalls e.g. for x86.
# - <syscalls>strace_syscalls.h: Syscall information needed by strace.
# preprocess the syscalls header
rule PreprocessSyscalls
{
# PreprocessSyscalls <preprocessedHeader> : <header> : <parsable> ;
#
local parsable = $(3) ;
local parsableDefine ;
if $(parsable) {
parsableDefine = GEN_SYSCALL_INFOS_PROCESSING ;
}
# PreprocessSyscalls <preprocessedHeader> : <header> ;
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 <syscalls>syscall_numbers.h : [ FDirName $(dir) system kernel ] ;
MakeLocate <syscalls>syscall_table.h : [ FDirName $(dir) system kernel ] ;
MakeLocate <syscalls>strace_syscalls.h : [ FDirName $(dir) bin 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>syscalls.S.inc ;
GenSyscallsDispatcher <syscalls>syscall_dispatcher.h ;
GenSyscallsNumbers <syscalls>syscall_numbers.h ;
GenSyscallsTable <syscalls>syscall_table.h ;
GenSyscallsSTrace <syscalls>strace_syscalls.h ;
GenSyscallsFile <syscalls>syscalls.S.inc : -c ;
GenSyscallsFile <syscalls>syscall_dispatcher.h : -d ;
GenSyscallsFile <syscalls>syscall_numbers.h : -n ;
GenSyscallsFile <syscalls>syscall_table.h : -t ;
GenSyscallsFile <syscalls>strace_syscalls.h : -s ;
@@ -1 +1,2 @@
#include "arch/generic/generic_gensyscalls.h"
#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int
#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int
@@ -1,51 +0,0 @@
// 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);
}
};
@@ -1 +1,2 @@
#include "arch/generic/generic_gensyscalls.h"
#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int
#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int
@@ -1 +1,2 @@
#include "arch/generic/generic_gensyscalls.h"
#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int
#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int
@@ -1 +1,2 @@
#include "arch/generic/generic_gensyscalls.h"
#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int
#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int
@@ -1 +1,2 @@
#include "arch/generic/generic_gensyscalls.h"
#define SYSCALL_RETURN_TYPE_ALIGNMENT_TYPE int
#define SYSCALL_PARAMETER_ALIGNMENT_TYPE int
+88 -13
View File
@@ -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 <header> <syscall infos>\n"
"Usage: gensyscallinfos <header> <syscall infos> <syscall types sizes>\n"
"\n"
"Given the (preprocessed) header file that defines the syscall prototypes "
"the\n"
@@ -30,7 +38,11 @@ const char* kUsage =
" syscall prototypes.\n"
" <syscall infos> - Output: The syscall infos source file needed "
"to\n"
" build gensyscalls.";
" build gensyscalls.\n"
" <syscall types sizes> - Output: A source file that will by another "
"build\n"
" step turned into a header file included by\n"
" <syscall infos>.\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>("returnType");
file << "\tsyscall->SetReturnType<" << returnType.type
<< ">(\"" << returnType.type << "\");" << endl;
// syscall->SetReturnType<(SYSCALL_RETURN_TYPE_SIZE_<i>,
// "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<ParameterType>("parameterTypeName",
// "parameterName");
file << "\tsyscall->AddParameter<"
<< param.type << ">(\""
<< param.type << "\", \""
<< param.name << "\");" << endl;
// syscall->AddParameter(SYSCALL_PARAMETER_SIZE_<i>_<k>,
// "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 <computed_asm_macros.h>" << endl;
file << "#include <syscalls.h>" << 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
+32 -5
View File
@@ -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 <cstdio>
@@ -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
+13 -43
View File
@@ -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: <syscalls.h> is pre-processed with the cross-compiler, but the
// pre-processed header is compiled with the native compiler. Unfortunately
// <stdarg.h> 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 <stdarg.h> 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<typename T> void SetReturnType(const char* name);
template<typename T> 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<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