Reworked the way how the gensyscalls stuff finds out about
the sizes and alignments of syscall parameters. It no longer generates and compiles functions with the same signature as the syscalls. This simply doesn't generally work for cross-compilation. Instead we provide a bit of architecture-specific code that knows how things work for the target architecture. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@15196 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
968748e669
commit
2ae568931f
@ -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 <preprocessedHeader> : <header> : <parsable> ;
|
||||
#
|
||||
local parsable = $(3) ;
|
||||
local parsableDefine ;
|
||||
|
||||
if $(parsable) {
|
||||
parsableDefine = GEN_SYSCALL_INFOS_PROCESSING ;
|
||||
}
|
||||
|
||||
# generate the syscall infos source file
|
||||
Depends $(<) : $(>) ;
|
||||
|
||||
local headers = [ on $(1) return $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
|
||||
local sysHeaders =
|
||||
[ PrivateHeaders kernel ]
|
||||
[ ArchHeaders $(TARGET_ARCH) ]
|
||||
[ on $(1) return $(SUBDIRSYSHDRS) $(SYSHDRS) ]
|
||||
$(HAIKU_HDRS) ;
|
||||
|
||||
HDRS on $(<) = $(headers) ;
|
||||
SYSHDRS on $(<) = $(sysHeaders) ;
|
||||
|
||||
HDRRULE on $(>) = HdrRule ;
|
||||
HDRSCAN on $(>) = $(HDRPATTERN) ;
|
||||
HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ;
|
||||
HDRGRIST on $(>) = $(HDRGRIST) ;
|
||||
|
||||
DEFINES on $(<) += $(HAIKU_DEFINES) $(parsableDefine) ;
|
||||
|
||||
CCFLAGS on $(<) += $(HAIKU_CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ;
|
||||
CCHDRS on $(<) = [ FIncludes $(headers) : $(HAIKU_LOCAL_INCLUDES_OPTION) ]
|
||||
$(HAIKU_INCLUDES_SEPARATOR)
|
||||
[ FSysIncludes $(sysHeaders) : $(HAIKU_SYSTEM_INCLUDES_OPTION) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions PreprocessSyscalls
|
||||
{
|
||||
$(HAIKU_C++) -xc++ -E "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
|
||||
}
|
||||
|
||||
local syscallsHeader = [ FGristFiles syscalls.h ] ;
|
||||
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>syscalls.S.inc : [ FDirName $(dir) system libroot os ] ;
|
||||
MakeLocate <syscalls>syscall_dispatcher.h : [ FDirName $(dir) system kernel ] ;
|
||||
@ -47,7 +104,6 @@ MakeLocate <syscalls>syscall_numbers.h : [ FDirName $(dir) system kernel ] ;
|
||||
MakeLocate <syscalls>syscall_table.h : [ FDirName $(dir) system kernel ] ;
|
||||
MakeLocate <syscalls>strace_syscalls.h : [ FDirName $(dir) bin strace ] ;
|
||||
|
||||
|
||||
rule GenSyscallsFile {
|
||||
Depends $(1) : gensyscalls ;
|
||||
GenSyscallsFile1 $(1) : gensyscalls ;
|
||||
@ -98,49 +154,3 @@ GenSyscallsDispatcher <syscalls>syscall_dispatcher.h ;
|
||||
GenSyscallsNumbers <syscalls>syscall_numbers.h ;
|
||||
GenSyscallsTable <syscalls>syscall_table.h ;
|
||||
GenSyscallsSTrace <syscalls>strace_syscalls.h ;
|
||||
|
||||
|
||||
# preprocess the syscalls header
|
||||
|
||||
UsePrivateHeaders kernel ;
|
||||
UseArchHeaders $(TARGET_ARCH) ;
|
||||
|
||||
rule PreprocessSyscalls
|
||||
{
|
||||
Depends $(<) : $(>) ;
|
||||
|
||||
local headers = [ on $(1) return $(SEARCH_SOURCE) $(SUBDIRHDRS) $(HDRS) ] ;
|
||||
local sysHeaders = [ on $(1) return $(SUBDIRSYSHDRS) $(SYSHDRS) ]
|
||||
$(HAIKU_HDRS) ;
|
||||
|
||||
HDRS on $(<) = $(headers) ;
|
||||
SYSHDRS on $(<) = $(sysHeaders) ;
|
||||
|
||||
HDRRULE on $(>) = HdrRule ;
|
||||
HDRSCAN on $(>) = $(HDRPATTERN) ;
|
||||
HDRSEARCH on $(>) = $(headers) $(sysHeaders) $(STDHDRS) ;
|
||||
HDRGRIST on $(>) = $(HDRGRIST) ;
|
||||
|
||||
DEFINES on $(<) += $(HAIKU_DEFINES) GEN_SYSCALL_INFOS_PROCESSING ;
|
||||
|
||||
CCFLAGS on $(<) += $(HAIKU_CCFLAGS) $(SUBDIRCCFLAGS) $(OPTIM) ;
|
||||
CCHDRS on $(<) = [ FIncludes $(headers) : $(HAIKU_LOCAL_INCLUDES_OPTION) ]
|
||||
$(HAIKU_INCLUDES_SEPARATOR)
|
||||
[ FSysIncludes $(sysHeaders) : $(HAIKU_SYSTEM_INCLUDES_OPTION) ] ;
|
||||
CCDEFS on $(<) = [ on $(<) FDefines $(DEFINES) ] ;
|
||||
}
|
||||
|
||||
actions PreprocessSyscalls
|
||||
{
|
||||
$(HAIKU_C++) -xc++ -E "$(2)" $(CCFLAGS) $(CCDEFS) $(CCHDRS) -o "$(1)" ;
|
||||
}
|
||||
|
||||
PreprocessSyscalls $(syscallsHeaderPP) : $(syscallsHeader) ;
|
||||
|
||||
|
||||
# compile the syscall infos source file
|
||||
|
||||
# TODO: Clean this mess up!
|
||||
SYSHDRS on $(syscallInfos:S=$(SUFOBJ)) = $(HAIKU_HDRS) ;
|
||||
Object $(syscallInfos:S=$(SUFOBJ)) : $(syscallInfos) ;
|
||||
CCFLAGS on $(syscallInfos:S=$(SUFOBJ)) += -nostdinc ;
|
||||
|
51
src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h
Normal file
51
src/tools/gensyscalls/arch/ppc/arch_gensyscalls.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Included by gensyscalls.
|
||||
|
||||
typedef int AlignmentType;
|
||||
static const char* kAlignmentType = "int";
|
||||
static const int kAlignment = sizeof(AlignmentType);
|
||||
|
||||
// ReturnTypeCreator
|
||||
template<typename T>
|
||||
class ReturnTypeCreator {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* name)
|
||||
{
|
||||
int size = sizeof(T);
|
||||
int usedSize = align_to_type<AlignmentType>(size);
|
||||
const char* alignmentType
|
||||
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
|
||||
|
||||
syscall->SetReturnType(name, size, usedSize, alignmentType);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class ReturnTypeCreator<void> {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* name)
|
||||
{
|
||||
syscall->SetReturnType(name, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// ParameterCreator
|
||||
template<typename T>
|
||||
class ParameterCreator {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* typeName,
|
||||
const char* parameterName)
|
||||
{
|
||||
// compute offset
|
||||
int offset = 0;
|
||||
if (Parameter* previous = syscall->LastParameter())
|
||||
offset = previous->Offset() + previous->UsedSize();
|
||||
|
||||
int size = sizeof(T);
|
||||
int usedSize = align_to_type<AlignmentType>(size);
|
||||
const char* alignmentType
|
||||
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
|
||||
|
||||
syscall->AddParameter(typeName, parameterName, size, usedSize, offset,
|
||||
alignmentType);
|
||||
}
|
||||
};
|
51
src/tools/gensyscalls/arch/x86/arch_gensyscalls.h
Normal file
51
src/tools/gensyscalls/arch/x86/arch_gensyscalls.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Included by gensyscalls.
|
||||
|
||||
typedef int AlignmentType;
|
||||
static const char* kAlignmentType = "int";
|
||||
static const int kAlignment = sizeof(AlignmentType);
|
||||
|
||||
// ReturnTypeCreator
|
||||
template<typename T>
|
||||
class ReturnTypeCreator {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* name)
|
||||
{
|
||||
int size = sizeof(T);
|
||||
int usedSize = align_to_type<AlignmentType>(size);
|
||||
const char* alignmentType
|
||||
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
|
||||
|
||||
syscall->SetReturnType(name, size, usedSize, alignmentType);
|
||||
}
|
||||
};
|
||||
|
||||
template<>
|
||||
class ReturnTypeCreator<void> {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* name)
|
||||
{
|
||||
syscall->SetReturnType(name, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
|
||||
// ParameterCreator
|
||||
template<typename T>
|
||||
class ParameterCreator {
|
||||
public:
|
||||
static void Create(Syscall* syscall, const char* typeName,
|
||||
const char* parameterName)
|
||||
{
|
||||
// compute offset
|
||||
int offset = 0;
|
||||
if (Parameter* previous = syscall->LastParameter())
|
||||
offset = previous->Offset() + previous->UsedSize();
|
||||
|
||||
int size = sizeof(T);
|
||||
int usedSize = align_to_type<AlignmentType>(size);
|
||||
const char* alignmentType
|
||||
= (size != usedSize && size < kAlignment ? kAlignmentType : 0);
|
||||
|
||||
syscall->AddParameter(typeName, parameterName, size, usedSize, offset,
|
||||
alignmentType);
|
||||
}
|
||||
};
|
@ -15,7 +15,7 @@
|
||||
|
||||
// usage
|
||||
const char *kUsage =
|
||||
"Usage: gensyscallinfos <header> <calls> <dispatcher>\n"
|
||||
"Usage: gensyscallinfos <header> <syscall infos>\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>("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<ParameterType>("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;
|
||||
}
|
||||
|
||||
|
@ -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 <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "arch_config.h"
|
||||
#include <vector>
|
||||
|
||||
#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<Parameter*> {
|
||||
};
|
||||
|
||||
// constructor
|
||||
Syscall::Syscall(const char* name, const char* kernelName)
|
||||
: fName(name),
|
||||
fKernelName(kernelName),
|
||||
fReturnType(NULL),
|
||||
fParameters(new ParameterVector)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
Syscall::~Syscall()
|
||||
{
|
||||
delete fReturnType;
|
||||
|
||||
int count = CountParameters();
|
||||
for (int i = 0; i < count; i++)
|
||||
delete ParameterAt(i);
|
||||
delete fParameters;
|
||||
}
|
||||
|
||||
// ParameterAt
|
||||
int
|
||||
Syscall::CountParameters() const
|
||||
{
|
||||
return fParameters->size();
|
||||
}
|
||||
|
||||
// ParameterAt
|
||||
Parameter*
|
||||
Syscall::ParameterAt(int index) const
|
||||
{
|
||||
if (index < 0 || index >= CountParameters())
|
||||
return NULL;
|
||||
|
||||
return (*fParameters)[index];
|
||||
}
|
||||
|
||||
// LastParameter
|
||||
Parameter*
|
||||
Syscall::LastParameter() const
|
||||
{
|
||||
return ParameterAt(CountParameters() - 1);
|
||||
}
|
||||
|
||||
// SetReturnType
|
||||
Type*
|
||||
Syscall::SetReturnType(const char* name, int size, int usedSize,
|
||||
const char* alignmentTypeName)
|
||||
{
|
||||
delete fReturnType;
|
||||
return fReturnType = new Type(name, size, usedSize, alignmentTypeName);
|
||||
}
|
||||
|
||||
// AddParameter
|
||||
Parameter*
|
||||
Syscall::AddParameter(const char* typeName, const char* parameterName,
|
||||
int size, int usedSize, int offset, const char* alignmentTypeName)
|
||||
{
|
||||
Parameter* parameter = new Parameter(typeName, parameterName, size,
|
||||
usedSize, offset, alignmentTypeName);
|
||||
fParameters->push_back(parameter);
|
||||
return parameter;
|
||||
}
|
||||
|
||||
|
||||
// SyscallVector
|
||||
|
||||
struct SyscallVector::_SyscallVector : public vector<Syscall*> {
|
||||
};
|
||||
|
||||
|
||||
// constructor
|
||||
SyscallVector::SyscallVector()
|
||||
: fSyscalls(new _SyscallVector)
|
||||
{
|
||||
}
|
||||
|
||||
// destructor
|
||||
SyscallVector::~SyscallVector()
|
||||
{
|
||||
int count = CountSyscalls();
|
||||
for (int i = 0; i < count; i++)
|
||||
delete SyscallAt(i);
|
||||
delete fSyscalls;
|
||||
}
|
||||
|
||||
// Create
|
||||
SyscallVector*
|
||||
SyscallVector::Create()
|
||||
{
|
||||
return new SyscallVector;
|
||||
}
|
||||
|
||||
// CountSyscalls
|
||||
int
|
||||
SyscallVector::CountSyscalls() const
|
||||
{
|
||||
return fSyscalls->size();
|
||||
}
|
||||
|
||||
// SyscallAt
|
||||
Syscall*
|
||||
SyscallVector::SyscallAt(int index) const
|
||||
{
|
||||
if (index < 0 || index >= CountSyscalls())
|
||||
return NULL;
|
||||
|
||||
return (*fSyscalls)[index];
|
||||
}
|
||||
|
||||
// CreateSyscall
|
||||
Syscall*
|
||||
SyscallVector::CreateSyscall(const char* name, const char* kernelName)
|
||||
{
|
||||
Syscall* syscall = new Syscall(name, kernelName);
|
||||
fSyscalls->push_back(syscall);
|
||||
return syscall;
|
||||
}
|
||||
|
||||
|
||||
// #pragma mark -
|
||||
|
||||
// Main
|
||||
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,29 +475,8 @@ 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;
|
||||
SyscallVector* fSyscallVector;
|
||||
int fSyscallCount;
|
||||
};
|
||||
|
||||
|
@ -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<typename T> void SetReturnType(const char* name);
|
||||
template<typename T> void AddParameter(const char* typeName,
|
||||
const char* parameterName);
|
||||
|
||||
Type* SetReturnType(const char* name, int size,
|
||||
int usedSize,
|
||||
const char* alignmentTypeName);
|
||||
Parameter* AddParameter(const char* typeName,
|
||||
const char* parameterName, int size,
|
||||
int usedSize, int offset,
|
||||
const char* alignmentTypeName);
|
||||
|
||||
private:
|
||||
struct ParameterVector;
|
||||
|
||||
const char* fName;
|
||||
const char* fKernelName;
|
||||
Type* fReturnType;
|
||||
ParameterVector* fParameters;
|
||||
};
|
||||
|
||||
// SyscallVector
|
||||
class SyscallVector {
|
||||
public:
|
||||
SyscallVector();
|
||||
~SyscallVector();
|
||||
|
||||
static SyscallVector* Create();
|
||||
|
||||
int CountSyscalls() const;
|
||||
Syscall* SyscallAt(int index) const;
|
||||
|
||||
Syscall* CreateSyscall(const char* name,
|
||||
const char* kernelName);
|
||||
|
||||
private:
|
||||
struct _SyscallVector;
|
||||
|
||||
_SyscallVector* fSyscalls;
|
||||
};
|
||||
|
||||
extern SyscallVector* create_syscall_vector();
|
||||
|
||||
|
||||
#ifndef DONT_INCLUDE_ARCH_GENSYSCALLS_H
|
||||
|
||||
// align_to_type
|
||||
template<typename T>
|
||||
int
|
||||
align_to_type(int size)
|
||||
{
|
||||
return (size + sizeof(T) - 1) / sizeof(T) * sizeof(T);
|
||||
}
|
||||
|
||||
#include "arch_gensyscalls.h"
|
||||
|
||||
// SetReturnType
|
||||
template<typename T>
|
||||
void
|
||||
Syscall::SetReturnType(const char* name)
|
||||
{
|
||||
ReturnTypeCreator<T>::Create(this, name);
|
||||
}
|
||||
|
||||
// AddParameter
|
||||
template<typename T>
|
||||
void
|
||||
Syscall::AddParameter(const char* typeName, const char* parameterName)
|
||||
{
|
||||
ParameterCreator<T>::Create(this, typeName, parameterName);
|
||||
}
|
||||
|
||||
#endif // !DONT_INCLUDE_ARCH_GENSYSCALLS_H
|
||||
|
||||
#endif // GENSYSCALLS_H
|
||||
|
Loading…
Reference in New Issue
Block a user