This commit was generated by cvs2svn to compensate for changes in r2,

which included commits to RCS files with non-trunk default branches.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@3 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
bellard 2003-02-18 22:55:36 +00:00
parent e63c3dc74b
commit 31e31b8a24
16 changed files with 5791 additions and 0 deletions

504
COPYING.LIB Normal file
View File

@ -0,0 +1,504 @@
------------------------------------------------------------------------------
NOTE:
Some code of the Twin package was modified for DOSEMU by the DOSEMU-team.
The original is 'Copyright 1997 Willows Software, Inc.' and generously
was put under the GNU Library General Public License.
( for more information see http://www.willows.com/ )
We make use of section 3 of the GNU Library General Public License
('...opt to apply the terms of the ordinary GNU General Public License...'),
because the resulting product is an integrated part of DOSEMU and
can not be considered to be a 'library' in the terms of Library License.
Therefore, the below GNU LIBRARY GENERAL PUBLIC LICENSE applies only to the
_unchanged_ Twin package from Willows. For the DOSEMU-changed parts the normal
GNU GENERAL PUBLIC LICENSE applies. This GPL (file COPYING) can be found in
the root directory of the DOSEMU distribution.
The act of transformation to GPL was indicated to the maintainer of the Twin
package (Rob Penrose <rob@Canopy.Com>) and he acknowledge agreement.
Nov. 1 1997, The DOSEMU team.
------------------------------------------------------------------------------
GNU LIBRARY GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1991 Free Software Foundation, Inc.
675 Mass Ave, Cambridge, MA 02139, USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
[This is the first released version of the library GPL. It is
numbered 2 because it goes with version 2 of the ordinary GPL.]
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
Licenses are intended to guarantee your freedom to share and change
free software--to make sure the software is free for all its users.
This license, the Library General Public License, applies to some
specially designated Free Software Foundation software, and to any
other libraries whose authors decide to use it. You can use it for
your libraries, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if
you distribute copies of the library, or if you modify it.
For example, if you distribute copies of the library, whether gratis
or for a fee, you must give the recipients all the rights that we gave
you. You must make sure that they, too, receive or can get the source
code. If you link a program with the library, you must provide
complete object files to the recipients so that they can relink them
with the library, after making changes to the library and recompiling
it. And you must show them these terms so they know their rights.
Our method of protecting your rights has two steps: (1) copyright
the library, and (2) offer you this license which gives you legal
permission to copy, distribute and/or modify the library.
Also, for each distributor's protection, we want to make certain
that everyone understands that there is no warranty for this free
library. If the library is modified by someone else and passed on, we
want its recipients to know that what they have is not the original
version, so that any problems introduced by others will not reflect on
the original authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that companies distributing free
software will individually obtain patent licenses, thus in effect
transforming the program into proprietary software. To prevent this,
we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
Most GNU software, including some libraries, is covered by the ordinary
GNU General Public License, which was designed for utility programs. This
license, the GNU Library General Public License, applies to certain
designated libraries. This license is quite different from the ordinary
one; be sure to read it in full, and don't assume that anything in it is
the same as in the ordinary license.
The reason we have a separate public license for some libraries is that
they blur the distinction we usually make between modifying or adding to a
program and simply using it. Linking a program with a library, without
changing the library, is in some sense simply using the library, and is
analogous to running a utility program or application program. However, in
a textual and legal sense, the linked executable is a combined work, a
derivative of the original library, and the ordinary General Public License
treats it as such.
Because of this blurred distinction, using the ordinary General
Public License for libraries did not effectively promote software
sharing, because most developers did not use the libraries. We
concluded that weaker conditions might promote sharing better.
However, unrestricted linking of non-free programs would deprive the
users of those programs of all benefit from the free status of the
libraries themselves. This Library General Public License is intended to
permit developers of non-free programs to use free libraries, while
preserving your freedom as a user of such programs to change the free
libraries that are incorporated in them. (We have not seen how to achieve
this as regards changes in header files, but we have achieved it as regards
changes in the actual functions of the Library.) The hope is that this
will lead to faster development of free libraries.
The precise terms and conditions for copying, distribution and
modification follow. Pay close attention to the difference between a
"work based on the library" and a "work that uses the library". The
former contains code derived from the library, while the latter only
works together with the library.
Note that it is possible for a library to be covered by the ordinary
General Public License rather than by this special one.
GNU LIBRARY GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License Agreement applies to any software library which
contains a notice placed by the copyright holder or other authorized
party saying it may be distributed under the terms of this Library
General Public License (also called "this License"). Each licensee is
addressed as "you".
A "library" means a collection of software functions and/or data
prepared so as to be conveniently linked with application programs
(which use some of those functions and data) to form executables.
The "Library", below, refers to any such software library or work
which has been distributed under these terms. A "work based on the
Library" means either the Library or any derivative work under
copyright law: that is to say, a work containing the Library or a
portion of it, either verbatim or with modifications and/or translated
straightforwardly into another language. (Hereinafter, translation is
included without limitation in the term "modification".)
"Source code" for a work means the preferred form of the work for
making modifications to it. For a library, complete source code means
all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation
and installation of the library.
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running a program using the Library is not restricted, and output from
such a program is covered only if its contents constitute a work based
on the Library (independent of the use of the Library in a tool for
writing it). Whether that is true depends on what the Library does
and what the program that uses the Library does.
1. You may copy and distribute verbatim copies of the Library's
complete source code as you receive it, in any medium, provided that
you conspicuously and appropriately publish on each copy an
appropriate copyright notice and disclaimer of warranty; keep intact
all the notices that refer to this License and to the absence of any
warranty; and distribute a copy of this License along with the
Library.
You may charge a fee for the physical act of transferring a copy,
and you may at your option offer warranty protection in exchange for a
fee.
2. You may modify your copy or copies of the Library or any portion
of it, thus forming a work based on the Library, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) The modified work must itself be a software library.
b) You must cause the files modified to carry prominent notices
stating that you changed the files and the date of any change.
c) You must cause the whole of the work to be licensed at no
charge to all third parties under the terms of this License.
d) If a facility in the modified Library refers to a function or a
table of data to be supplied by an application program that uses
the facility, other than as an argument passed when the facility
is invoked, then you must make a good faith effort to ensure that,
in the event an application does not supply such function or
table, the facility still operates, and performs whatever part of
its purpose remains meaningful.
(For example, a function in a library to compute square roots has
a purpose that is entirely well-defined independent of the
application. Therefore, Subsection 2d requires that any
application-supplied function or table used by this function must
be optional: if the application does not supply it, the square
root function must still compute square roots.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Library,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Library, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote
it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Library.
In addition, mere aggregation of another work not based on the Library
with the Library (or with a work based on the Library) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may opt to apply the terms of the ordinary GNU General Public
License instead of this License to a given copy of the Library. To do
this, you must alter all the notices that refer to this License, so
that they refer to the ordinary GNU General Public License, version 2,
instead of to this License. (If a newer version than version 2 of the
ordinary GNU General Public License has appeared, then you can specify
that version instead if you wish.) Do not make any other change in
these notices.
Once this change is made in a given copy, it is irreversible for
that copy, so the ordinary GNU General Public License applies to all
subsequent copies and derivative works made from that copy.
This option is useful when you wish to copy part of the code of
the Library into a program that is not a library.
4. You may copy and distribute the Library (or a portion or
derivative of it, under Section 2) in object code or executable form
under the terms of Sections 1 and 2 above provided that you accompany
it with the complete corresponding machine-readable source code, which
must be distributed under the terms of Sections 1 and 2 above on a
medium customarily used for software interchange.
If distribution of object code is made by offering access to copy
from a designated place, then offering equivalent access to copy the
source code from the same place satisfies the requirement to
distribute the source code, even though third parties are not
compelled to copy the source along with the object code.
5. A program that contains no derivative of any portion of the
Library, but is designed to work with the Library by being compiled or
linked with it, is called a "work that uses the Library". Such a
work, in isolation, is not a derivative work of the Library, and
therefore falls outside the scope of this License.
However, linking a "work that uses the Library" with the Library
creates an executable that is a derivative of the Library (because it
contains portions of the Library), rather than a "work that uses the
library". The executable is therefore covered by this License.
Section 6 states terms for distribution of such executables.
When a "work that uses the Library" uses material from a header file
that is part of the Library, the object code for the work may be a
derivative work of the Library even though the source code is not.
Whether this is true is especially significant if the work can be
linked without the Library, or if the work is itself a library. The
threshold for this to be true is not precisely defined by law.
If such an object file uses only numerical parameters, data
structure layouts and accessors, and small macros and small inline
functions (ten lines or less in length), then the use of the object
file is unrestricted, regardless of whether it is legally a derivative
work. (Executables containing this object code plus portions of the
Library will still fall under Section 6.)
Otherwise, if the work is a derivative of the Library, you may
distribute the object code for the work under the terms of Section 6.
Any executables containing that work also fall under Section 6,
whether or not they are linked directly with the Library itself.
6. As an exception to the Sections above, you may also compile or
link a "work that uses the Library" with the Library to produce a
work containing portions of the Library, and distribute that work
under terms of your choice, provided that the terms permit
modification of the work for the customer's own use and reverse
engineering for debugging such modifications.
You must give prominent notice with each copy of the work that the
Library is used in it and that the Library and its use are covered by
this License. You must supply a copy of this License. If the work
during execution displays copyright notices, you must include the
copyright notice for the Library among them, as well as a reference
directing the user to the copy of this License. Also, you must do one
of these things:
a) Accompany the work with the complete corresponding
machine-readable source code for the Library including whatever
changes were used in the work (which must be distributed under
Sections 1 and 2 above); and, if the work is an executable linked
with the Library, with the complete machine-readable "work that
uses the Library", as object code and/or source code, so that the
user can modify the Library and then relink to produce a modified
executable containing the modified Library. (It is understood
that the user who changes the contents of definitions files in the
Library will not necessarily be able to recompile the application
to use the modified definitions.)
b) Accompany the work with a written offer, valid for at
least three years, to give the same user the materials
specified in Subsection 6a, above, for a charge no more
than the cost of performing this distribution.
c) If distribution of the work is made by offering access to copy
from a designated place, offer equivalent access to copy the above
specified materials from the same place.
d) Verify that the user has already received a copy of these
materials or that you have already sent this user a copy.
For an executable, the required form of the "work that uses the
Library" must include any data and utility programs needed for
reproducing the executable from it. However, as a special exception,
the source code distributed need not include anything that is normally
distributed (in either source or binary form) with the major
components (compiler, kernel, and so on) of the operating system on
which the executable runs, unless that component itself accompanies
the executable.
It may happen that this requirement contradicts the license
restrictions of other proprietary libraries that do not normally
accompany the operating system. Such a contradiction means you cannot
use both them and the Library together in an executable that you
distribute.
7. You may place library facilities that are a work based on the
Library side-by-side in a single library together with other library
facilities not covered by this License, and distribute such a combined
library, provided that the separate distribution of the work based on
the Library and of the other library facilities is otherwise
permitted, and provided that you do these two things:
a) Accompany the combined library with a copy of the same work
based on the Library, uncombined with any other library
facilities. This must be distributed under the terms of the
Sections above.
b) Give prominent notice with the combined library of the fact
that part of it is a work based on the Library, and explaining
where to find the accompanying uncombined form of the same work.
8. You may not copy, modify, sublicense, link with, or distribute
the Library except as expressly provided under this License. Any
attempt otherwise to copy, modify, sublicense, link with, or
distribute the Library is void, and will automatically terminate your
rights under this License. However, parties who have received copies,
or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
9. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Library or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Library (or any work based on the
Library), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Library or works based on it.
10. Each time you redistribute the Library (or any work based on the
Library), the recipient automatically receives a license from the
original licensor to copy, distribute, link with or modify the Library
subject to these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
11. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Library at all. For example, if a patent
license would not permit royalty-free redistribution of the Library by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Library.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply,
and the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
12. If the distribution and/or use of the Library is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Library under this License may add
an explicit geographical distribution limitation excluding those countries,
so that distribution is permitted only in or among countries not thus
excluded. In such case, this License incorporates the limitation as if
written in the body of this License.
13. The Free Software Foundation may publish revised and/or new
versions of the Library General Public License from time to time.
Such new versions will be similar in spirit to the present version,
but may differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the Library
specifies a version number of this License which applies to it and
"any later version", you have the option of following the terms and
conditions either of that version or of any later version published by
the Free Software Foundation. If the Library does not specify a
license version number, you may choose any version ever published by
the Free Software Foundation.
14. If you wish to incorporate parts of the Library into other free
programs whose distribution conditions are incompatible with these,
write to the author to ask for permission. For software which is
copyrighted by the Free Software Foundation, write to the Free
Software Foundation; we sometimes make exceptions for this. Our
decision will be guided by the two goals of preserving the free status
of all derivatives of our free software and of promoting the sharing
and reuse of software generally.
NO WARRANTY
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
DAMAGES.
END OF TERMS AND CONDITIONS
Appendix: How to Apply These Terms to Your New Libraries
If you develop a new library, and you want it to be of the greatest
possible use to the public, we recommend making it free software that
everyone can redistribute and change. You can do so by permitting
redistribution under these terms (or, alternatively, under the terms of the
ordinary General Public License).
To apply these terms, attach the following notices to the library. It is
safest to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least the
"copyright" line and a pointer to where the full notice is found.
<one line to give the library's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
Also add information on how to contact you by electronic and paper mail.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the library, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
<signature of Ty Coon>, 1 April 1990
Ty Coon, President of Vice
That's all there is to it!

37
Makefile Normal file
View File

@ -0,0 +1,37 @@
CFLAGS=-Wall -O2 -g
LDFLAGS=-g
DEFINES=-D_GNU_SOURCE -DGEMU -DDOSEMU #-DNO_TRACE_MSGS
OBJS= i386/fp87.o i386/interp_main.o i386/interp_modrm.o i386/interp_16_32.o \
i386/interp_32_16.o i386/interp_32_32.o i386/emu-utils.o \
i386/dis8086.o i386/emu-ldt.o
OBJS+= elfload.o main.o thunk.o syscall.o
SRCS = $(OBJS:.o=.c)
all: gemu
gemu: $(OBJS)
$(CC) -Wl,-T,i386.ld $(LDFLAGS) -o $@ $(OBJS)
depend: $(SRCS)
$(CC) -MM $(CFLAGS) $^ 1>.depend
%.o: %.c
$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
clean:
rm -f *.o *~ i386/*.o i386/*~ gemu hello test1 test2 TAGS
hello: hello.c
$(CC) -nostdlib $(CFLAGS) -static $(LDFLAGS) -o $@ $<
test1: test1.c
$(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $<
test2: test2.c
$(CC) $(CFLAGS) -static $(LDFLAGS) -o $@ $<
ifneq ($(wildcard .depend),)
include .depend
endif

2
TODO Normal file
View File

@ -0,0 +1,2 @@
- swap all elf paramters
- fix printf for doubles (fp87.c bug ?)

425
elf.h Normal file
View File

@ -0,0 +1,425 @@
/*
* ELF register definitions..
*/
#include <inttypes.h>
typedef uint32_t elf_greg_t;
#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
typedef elf_greg_t elf_gregset_t[ELF_NGREG];
typedef struct user_i387_struct elf_fpregset_t;
/*
* This is used to ensure we don't load something for the wrong architecture.
*/
#define elf_check_arch(x) ( ((x) == EM_386) || ((x) == EM_486) )
/*
* These are used to set parameters in the core dumps.
*/
#define ELF_CLASS ELFCLASS32
#define ELF_DATA ELFDATA2LSB;
#define ELF_ARCH EM_386
/* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
starts %edx contains a pointer to a function which might be
registered using `atexit'. This provides a mean for the
dynamic linker to call DT_FINI functions for shared libraries
that have been loaded before the code runs.
A value of 0 tells we have no such handler. */
#define ELF_PLAT_INIT(_r) _r->edx = 0
#define USE_ELF_CORE_DUMP
#define ELF_EXEC_PAGESIZE 4096
typedef uint32_t Elf32_Addr;
typedef uint16_t Elf32_Half;
typedef uint32_t Elf32_Off;
typedef int32_t Elf32_Sword;
typedef uint32_t Elf32_Word;
/* These constants are for the segment types stored in the image headers */
#define PT_NULL 0
#define PT_LOAD 1
#define PT_DYNAMIC 2
#define PT_INTERP 3
#define PT_NOTE 4
#define PT_SHLIB 5
#define PT_PHDR 6
#define PT_LOPROC 0x70000000
#define PT_HIPROC 0x7fffffff
/* These constants define the different elf file types */
#define ET_NONE 0
#define ET_REL 1
#define ET_EXEC 2
#define ET_DYN 3
#define ET_CORE 4
#define ET_LOPROC 5
#define ET_HIPROC 6
/* These constants define the various ELF target machines */
#define EM_NONE 0
#define EM_M32 1
#define EM_SPARC 2
#define EM_386 3
#define EM_68K 4
#define EM_88K 5
#define EM_486 6 /* Perhaps disused */
#define EM_860 7
#define EM_MIPS 8 /* MIPS R3000 (officially, big-endian only) */
#define EM_MIPS_RS4_BE 10 /* MIPS R4000 big-endian */
#define EM_SPARC64 11 /* SPARC v9 (not official) 64-bit */
#define EM_PARISC 15 /* HPPA */
#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */
#define EM_PPC 20 /* PowerPC */
/*
* This is an interim value that we will use until the committee comes
* up with a final number.
*/
#define EM_ALPHA 0x9026
/* This is the info that is needed to parse the dynamic section of the file */
#define DT_NULL 0
#define DT_NEEDED 1
#define DT_PLTRELSZ 2
#define DT_PLTGOT 3
#define DT_HASH 4
#define DT_STRTAB 5
#define DT_SYMTAB 6
#define DT_RELA 7
#define DT_RELASZ 8
#define DT_RELAENT 9
#define DT_STRSZ 10
#define DT_SYMENT 11
#define DT_INIT 12
#define DT_FINI 13
#define DT_SONAME 14
#define DT_RPATH 15
#define DT_SYMBOLIC 16
#define DT_REL 17
#define DT_RELSZ 18
#define DT_RELENT 19
#define DT_PLTREL 20
#define DT_DEBUG 21
#define DT_TEXTREL 22
#define DT_JMPREL 23
#define DT_LOPROC 0x70000000
#define DT_HIPROC 0x7fffffff
/* This info is needed when parsing the symbol table */
#define STB_LOCAL 0
#define STB_GLOBAL 1
#define STB_WEAK 2
#define STT_NOTYPE 0
#define STT_OBJECT 1
#define STT_FUNC 2
#define STT_SECTION 3
#define STT_FILE 4
#define ELF32_ST_BIND(x) ((x) >> 4)
#define ELF32_ST_TYPE(x) (((unsigned int) x) & 0xf)
/* Symbolic values for the entries in the auxiliary table
put on the initial stack */
#define AT_NULL 0 /* end of vector */
#define AT_IGNORE 1 /* entry should be ignored */
#define AT_EXECFD 2 /* file descriptor of program */
#define AT_PHDR 3 /* program headers for program */
#define AT_PHENT 4 /* size of program header entry */
#define AT_PHNUM 5 /* number of program headers */
#define AT_PAGESZ 6 /* system page size */
#define AT_BASE 7 /* base address of interpreter */
#define AT_FLAGS 8 /* flags */
#define AT_ENTRY 9 /* entry point of program */
#define AT_NOTELF 10 /* program is not ELF */
#define AT_UID 11 /* real uid */
#define AT_EUID 12 /* effective uid */
#define AT_GID 13 /* real gid */
#define AT_EGID 14 /* effective gid */
typedef struct dynamic{
Elf32_Sword d_tag;
union{
Elf32_Sword d_val;
Elf32_Addr d_ptr;
} d_un;
} Elf32_Dyn;
typedef struct {
unsigned long long d_tag; /* entry tag value */
union {
unsigned long long d_val;
unsigned long long d_ptr;
} d_un;
} Elf64_Dyn;
/* The following are used with relocations */
#define ELF32_R_SYM(x) ((x) >> 8)
#define ELF32_R_TYPE(x) ((x) & 0xff)
#define R_386_NONE 0
#define R_386_32 1
#define R_386_PC32 2
#define R_386_GOT32 3
#define R_386_PLT32 4
#define R_386_COPY 5
#define R_386_GLOB_DAT 6
#define R_386_JMP_SLOT 7
#define R_386_RELATIVE 8
#define R_386_GOTOFF 9
#define R_386_GOTPC 10
#define R_386_NUM 11
typedef struct elf32_rel {
Elf32_Addr r_offset;
Elf32_Word r_info;
} Elf32_Rel;
typedef struct elf64_rel {
unsigned long long r_offset; /* Location at which to apply the action */
unsigned long long r_info; /* index and type of relocation */
} Elf64_Rel;
typedef struct elf32_rela{
Elf32_Addr r_offset;
Elf32_Word r_info;
Elf32_Sword r_addend;
} Elf32_Rela;
typedef struct elf64_rela {
unsigned long long r_offset; /* Location at which to apply the action */
unsigned long long r_info; /* index and type of relocation */
unsigned long long r_addend; /* Constant addend used to compute value */
} Elf64_Rela;
typedef struct elf32_sym{
Elf32_Word st_name;
Elf32_Addr st_value;
Elf32_Word st_size;
unsigned char st_info;
unsigned char st_other;
Elf32_Half st_shndx;
} Elf32_Sym;
typedef struct elf64_sym {
unsigned int st_name; /* Symbol name, index in string tbl */
unsigned char st_info; /* Type and binding attributes */
unsigned char st_other; /* No defined meaning, 0 */
unsigned short st_shndx; /* Associated section index */
unsigned long long st_value; /* Value of the symbol */
unsigned long long st_size; /* Associated symbol size */
} Elf64_Sym;
#define EI_NIDENT 16
typedef struct elf32_hdr{
unsigned char e_ident[EI_NIDENT];
Elf32_Half e_type;
Elf32_Half e_machine;
Elf32_Word e_version;
Elf32_Addr e_entry; /* Entry point */
Elf32_Off e_phoff;
Elf32_Off e_shoff;
Elf32_Word e_flags;
Elf32_Half e_ehsize;
Elf32_Half e_phentsize;
Elf32_Half e_phnum;
Elf32_Half e_shentsize;
Elf32_Half e_shnum;
Elf32_Half e_shstrndx;
} Elf32_Ehdr;
typedef struct elf64_hdr {
unsigned char e_ident[16]; /* ELF "magic number" */
short int e_type;
short unsigned int e_machine;
int e_version;
unsigned long long e_entry; /* Entry point virtual address */
unsigned long long e_phoff; /* Program header table file offset */
unsigned long long e_shoff; /* Section header table file offset */
int e_flags;
short int e_ehsize;
short int e_phentsize;
short int e_phnum;
short int e_shentsize;
short int e_shnum;
short int e_shstrndx;
} Elf64_Ehdr;
/* These constants define the permissions on sections in the program
header, p_flags. */
#define PF_R 0x4
#define PF_W 0x2
#define PF_X 0x1
typedef struct elf32_phdr{
Elf32_Word p_type;
Elf32_Off p_offset;
Elf32_Addr p_vaddr;
Elf32_Addr p_paddr;
Elf32_Word p_filesz;
Elf32_Word p_memsz;
Elf32_Word p_flags;
Elf32_Word p_align;
} Elf32_Phdr;
typedef struct elf64_phdr {
int p_type;
int p_flags;
unsigned long long p_offset; /* Segment file offset */
unsigned long long p_vaddr; /* Segment virtual address */
unsigned long long p_paddr; /* Segment physical address */
unsigned long long p_filesz; /* Segment size in file */
unsigned long long p_memsz; /* Segment size in memory */
unsigned long long p_align; /* Segment alignment, file & memory */
} Elf64_Phdr;
/* sh_type */
#define SHT_NULL 0
#define SHT_PROGBITS 1
#define SHT_SYMTAB 2
#define SHT_STRTAB 3
#define SHT_RELA 4
#define SHT_HASH 5
#define SHT_DYNAMIC 6
#define SHT_NOTE 7
#define SHT_NOBITS 8
#define SHT_REL 9
#define SHT_SHLIB 10
#define SHT_DYNSYM 11
#define SHT_NUM 12
#define SHT_LOPROC 0x70000000
#define SHT_HIPROC 0x7fffffff
#define SHT_LOUSER 0x80000000
#define SHT_HIUSER 0xffffffff
/* sh_flags */
#define SHF_WRITE 0x1
#define SHF_ALLOC 0x2
#define SHF_EXECINSTR 0x4
#define SHF_MASKPROC 0xf0000000
/* special section indexes */
#define SHN_UNDEF 0
#define SHN_LORESERVE 0xff00
#define SHN_LOPROC 0xff00
#define SHN_HIPROC 0xff1f
#define SHN_ABS 0xfff1
#define SHN_COMMON 0xfff2
#define SHN_HIRESERVE 0xffff
typedef struct {
Elf32_Word sh_name;
Elf32_Word sh_type;
Elf32_Word sh_flags;
Elf32_Addr sh_addr;
Elf32_Off sh_offset;
Elf32_Word sh_size;
Elf32_Word sh_link;
Elf32_Word sh_info;
Elf32_Word sh_addralign;
Elf32_Word sh_entsize;
} Elf32_Shdr;
typedef struct elf64_shdr {
unsigned int sh_name; /* Section name, index in string tbl */
unsigned int sh_type; /* Type of section */
unsigned long long sh_flags; /* Miscellaneous section attributes */
unsigned long long sh_addr; /* Section virtual addr at execution */
unsigned long long sh_offset; /* Section file offset */
unsigned long long sh_size; /* Size of section in bytes */
unsigned int sh_link; /* Index of another section */
unsigned int sh_info; /* Additional section information */
unsigned long long sh_addralign; /* Section alignment */
unsigned long long sh_entsize; /* Entry size if section holds table */
} Elf64_Shdr;
#define EI_MAG0 0 /* e_ident[] indexes */
#define EI_MAG1 1
#define EI_MAG2 2
#define EI_MAG3 3
#define EI_CLASS 4
#define EI_DATA 5
#define EI_VERSION 6
#define EI_PAD 7
#define ELFMAG0 0x7f /* EI_MAG */
#define ELFMAG1 'E'
#define ELFMAG2 'L'
#define ELFMAG3 'F'
#define ELFMAG "\177ELF"
#define SELFMAG 4
#define ELFCLASSNONE 0 /* EI_CLASS */
#define ELFCLASS32 1
#define ELFCLASS64 2
#define ELFCLASSNUM 3
#define ELFDATANONE 0 /* e_ident[EI_DATA] */
#define ELFDATA2LSB 1
#define ELFDATA2MSB 2
#define EV_NONE 0 /* e_version, EI_VERSION */
#define EV_CURRENT 1
#define EV_NUM 2
/* Notes used in ET_CORE */
#define NT_PRSTATUS 1
#define NT_PRFPREG 2
#define NT_PRPSINFO 3
#define NT_TASKSTRUCT 4
/* Note header in a PT_NOTE section */
typedef struct elf32_note {
Elf32_Word n_namesz; /* Name size */
Elf32_Word n_descsz; /* Content size */
Elf32_Word n_type; /* Content type */
} Elf32_Nhdr;
/* Note header in a PT_NOTE section */
/*
* For now we use the 32 bit version of the structure until we figure
* out whether we need anything better. Note - on the Alpha, "unsigned int"
* is only 32 bits.
*/
typedef struct elf64_note {
unsigned int n_namesz; /* Name size */
unsigned int n_descsz; /* Content size */
unsigned int n_type; /* Content type */
} Elf64_Nhdr;
#define ELF_START_MMAP 0x80000000
#if ELF_CLASS == ELFCLASS32
extern Elf32_Dyn _DYNAMIC [];
#define elfhdr elf32_hdr
#define elf_phdr elf32_phdr
#define elf_note elf32_note
#else
extern Elf64_Dyn _DYNAMIC [];
#define elfhdr elf64_hdr
#define elf_phdr elf64_phdr
#define elf_note elf64_note
#endif

130
i386.ld Normal file
View File

@ -0,0 +1,130 @@
/* ld script to make i386 Linux kernel
* Written by Martin Mares <mj@atrey.karlin.mff.cuni.cz>;
*/
OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
OUTPUT_ARCH(i386)
SEARCH_DIR(/lib); SEARCH_DIR(/usr/lib); SEARCH_DIR(/usr/local/lib); SEARCH_DIR(/usr/alpha-unknown-linux-gnu/lib);
ENTRY(_start)
SECTIONS
{
/* Read-only sections, merged into text segment: */
. = 0x60000000 + SIZEOF_HEADERS;
.interp : { *(.interp) }
.hash : { *(.hash) }
.dynsym : { *(.dynsym) }
.dynstr : { *(.dynstr) }
.gnu.version : { *(.gnu.version) }
.gnu.version_d : { *(.gnu.version_d) }
.gnu.version_r : { *(.gnu.version_r) }
.rel.text :
{ *(.rel.text) *(.rel.gnu.linkonce.t*) }
.rela.text :
{ *(.rela.text) *(.rela.gnu.linkonce.t*) }
.rel.data :
{ *(.rel.data) *(.rel.gnu.linkonce.d*) }
.rela.data :
{ *(.rela.data) *(.rela.gnu.linkonce.d*) }
.rel.rodata :
{ *(.rel.rodata) *(.rel.gnu.linkonce.r*) }
.rela.rodata :
{ *(.rela.rodata) *(.rela.gnu.linkonce.r*) }
.rel.got : { *(.rel.got) }
.rela.got : { *(.rela.got) }
.rel.ctors : { *(.rel.ctors) }
.rela.ctors : { *(.rela.ctors) }
.rel.dtors : { *(.rel.dtors) }
.rela.dtors : { *(.rela.dtors) }
.rel.init : { *(.rel.init) }
.rela.init : { *(.rela.init) }
.rel.fini : { *(.rel.fini) }
.rela.fini : { *(.rela.fini) }
.rel.bss : { *(.rel.bss) }
.rela.bss : { *(.rela.bss) }
.rel.plt : { *(.rel.plt) }
.rela.plt : { *(.rela.plt) }
.init : { *(.init) } =0x47ff041f
.text :
{
*(.text)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
} =0x47ff041f
_etext = .;
PROVIDE (etext = .);
.fini : { *(.fini) } =0x47ff041f
.rodata : { *(.rodata) *(.gnu.linkonce.r*) }
.rodata1 : { *(.rodata1) }
.reginfo : { *(.reginfo) }
/* Adjust the address for the data segment. We want to adjust up to
the same address within the page on the next page up. */
. = ALIGN(0x100000) + (. & (0x100000 - 1));
.data :
{
*(.data)
*(.gnu.linkonce.d*)
CONSTRUCTORS
}
.data1 : { *(.data1) }
.ctors :
{
*(.ctors)
}
.dtors :
{
*(.dtors)
}
.plt : { *(.plt) }
.got : { *(.got.plt) *(.got) }
.dynamic : { *(.dynamic) }
/* We want the small data sections together, so single-instruction offsets
can access them all, and initialized data all before uninitialized, so
we can shorten the on-disk segment size. */
.sdata : { *(.sdata) }
_edata = .;
PROVIDE (edata = .);
__bss_start = .;
.sbss : { *(.sbss) *(.scommon) }
.bss :
{
*(.dynbss)
*(.bss)
*(COMMON)
}
_end = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* These must appear regardless of . */
}

973
linux-user/elfload.c Normal file
View File

@ -0,0 +1,973 @@
/* This is the Linux kernel elf-loading code, ported into user space */
#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <errno.h>
#include <unistd.h>
#include <sys/mman.h>
#include <stdlib.h>
#include <string.h>
#include "gemu.h"
#include "linux_bin.h"
#include "elf.h"
#include "segment.h"
/* Necessary parameters */
#define ALPHA_PAGE_SIZE 4096
#define X86_PAGE_SIZE 4096
#define ALPHA_PAGE_MASK (~(ALPHA_PAGE_SIZE-1))
#define X86_PAGE_MASK (~(X86_PAGE_SIZE-1))
#define ALPHA_PAGE_ALIGN(addr) ((((addr)+ALPHA_PAGE_SIZE)-1)&ALPHA_PAGE_MASK)
#define X86_PAGE_ALIGN(addr) ((((addr)+X86_PAGE_SIZE)-1)&X86_PAGE_MASK)
#define NGROUPS 32
#define X86_ELF_EXEC_PAGESIZE X86_PAGE_SIZE
#define X86_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(X86_ELF_EXEC_PAGESIZE-1))
#define X86_ELF_PAGEOFFSET(_v) ((_v) & (X86_ELF_EXEC_PAGESIZE-1))
#define ALPHA_ELF_PAGESTART(_v) ((_v) & ~(unsigned long)(ALPHA_PAGE_SIZE-1))
#define ALPHA_ELF_PAGEOFFSET(_v) ((_v) & (ALPHA_PAGE_SIZE-1))
#define INTERPRETER_NONE 0
#define INTERPRETER_AOUT 1
#define INTERPRETER_ELF 2
#define DLINFO_ITEMS 12
/* Where we find X86 libraries... */
//#define X86_DEFAULT_LIB_DIR "/usr/x86/"
#define X86_DEFAULT_LIB_DIR "/"
//extern void * mmap4k();
#define mmap4k(a, b, c, d, e, f) mmap((void *)(a), b, c, d, e, f)
extern unsigned long x86_stack_size;
static int load_aout_interp(void * exptr, int interp_fd);
#ifdef BSWAP_NEEDED
static void bswap_ehdr(Elf32_Ehdr *ehdr)
{
bswap16s(&ehdr->e_type); /* Object file type */
bswap16s(&ehdr->e_machine); /* Architecture */
bswap32s(&ehdr->e_version); /* Object file version */
bswap32s(&ehdr->e_entry); /* Entry point virtual address */
bswap32s(&ehdr->e_phoff); /* Program header table file offset */
bswap32s(&ehdr->e_shoff); /* Section header table file offset */
bswap32s(&ehdr->e_flags); /* Processor-specific flags */
bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
bswap16s(&ehdr->e_phnum); /* Program header table entry count */
bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
bswap16s(&ehdr->e_shnum); /* Section header table entry count */
bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
}
static void bswap_phdr(Elf32_Phdr *phdr)
{
bswap32s(&phdr->p_type); /* Segment type */
bswap32s(&phdr->p_offset); /* Segment file offset */
bswap32s(&phdr->p_vaddr); /* Segment virtual address */
bswap32s(&phdr->p_paddr); /* Segment physical address */
bswap32s(&phdr->p_filesz); /* Segment size in file */
bswap32s(&phdr->p_memsz); /* Segment size in memory */
bswap32s(&phdr->p_flags); /* Segment flags */
bswap32s(&phdr->p_align); /* Segment alignment */
}
#endif
static void * get_free_page(void)
{
void * retval;
/* User-space version of kernel get_free_page. Returns a page-aligned
* page-sized chunk of memory.
*/
retval = mmap4k(0, ALPHA_PAGE_SIZE, PROT_READ|PROT_WRITE,
MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
if((long)retval == -1) {
perror("get_free_page");
exit(-1);
}
else {
return(retval);
}
}
static void free_page(void * pageaddr)
{
(void)munmap(pageaddr, ALPHA_PAGE_SIZE);
}
/*
* 'copy_string()' copies argument/envelope strings from user
* memory to free pages in kernel mem. These are in a format ready
* to be put directly into the top of new user memory.
*
*/
static unsigned long copy_strings(int argc,char ** argv,unsigned long *page,
unsigned long p)
{
char *tmp, *tmp1, *pag = NULL;
int len, offset = 0;
if (!p) {
return 0; /* bullet-proofing */
}
while (argc-- > 0) {
if (!(tmp1 = tmp = get_user(argv+argc))) {
fprintf(stderr, "VFS: argc is wrong");
exit(-1);
}
while (get_user(tmp++));
len = tmp - tmp1;
if (p < len) { /* this shouldn't happen - 128kB */
return 0;
}
while (len) {
--p; --tmp; --len;
if (--offset < 0) {
offset = p % X86_PAGE_SIZE;
if (!(pag = (char *) page[p/X86_PAGE_SIZE]) &&
!(pag = (char *) page[p/X86_PAGE_SIZE] =
(unsigned long *) get_free_page())) {
return 0;
}
}
if (len == 0 || offset == 0) {
*(pag + offset) = get_user(tmp);
}
else {
int bytes_to_copy = (len > offset) ? offset : len;
tmp -= bytes_to_copy;
p -= bytes_to_copy;
offset -= bytes_to_copy;
len -= bytes_to_copy;
memcpy_fromfs(pag + offset, tmp, bytes_to_copy + 1);
}
}
}
return p;
}
static int in_group_p(gid_t g)
{
/* return TRUE if we're in the specified group, FALSE otherwise */
int ngroup;
int i;
gid_t grouplist[NGROUPS];
ngroup = getgroups(NGROUPS, grouplist);
for(i = 0; i < ngroup; i++) {
if(grouplist[i] == g) {
return 1;
}
}
return 0;
}
static int count(char ** vec)
{
int i;
for(i = 0; *vec; i++) {
vec++;
}
return(i);
}
static int prepare_binprm(struct linux_binprm *bprm)
{
struct stat st;
int mode;
int retval, id_change;
if(fstat(bprm->fd, &st) < 0) {
return(-errno);
}
mode = st.st_mode;
if(!S_ISREG(mode)) { /* Must be regular file */
return(-EACCES);
}
if(!(mode & 0111)) { /* Must have at least one execute bit set */
return(-EACCES);
}
bprm->e_uid = geteuid();
bprm->e_gid = getegid();
id_change = 0;
/* Set-uid? */
if(mode & S_ISUID) {
bprm->e_uid = st.st_uid;
if(bprm->e_uid != geteuid()) {
id_change = 1;
}
}
/* Set-gid? */
/*
* If setgid is set but no group execute bit then this
* is a candidate for mandatory locking, not a setgid
* executable.
*/
if ((mode & (S_ISGID | S_IXGRP)) == (S_ISGID | S_IXGRP)) {
bprm->e_gid = st.st_gid;
if (!in_group_p(bprm->e_gid)) {
id_change = 1;
}
}
memset(bprm->buf, 0, sizeof(bprm->buf));
retval = lseek(bprm->fd, 0L, SEEK_SET);
if(retval >= 0) {
retval = read(bprm->fd, bprm->buf, 128);
}
if(retval < 0) {
perror("prepare_binprm");
exit(-1);
/* return(-errno); */
}
else {
return(retval);
}
}
unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm,
struct image_info * info)
{
unsigned long stack_base;
int i;
extern unsigned long stktop;
stack_base = X86_STACK_TOP - MAX_ARG_PAGES*X86_PAGE_SIZE;
p += stack_base;
if (bprm->loader) {
bprm->loader += stack_base;
}
bprm->exec += stack_base;
/* Create enough stack to hold everything. If we don't use
* it for args, we'll use it for something else...
*/
if(x86_stack_size > MAX_ARG_PAGES*X86_PAGE_SIZE) {
if((long)mmap4k((void *)(X86_STACK_TOP-x86_stack_size), x86_stack_size + X86_PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
perror("stk mmap");
exit(-1);
}
}
else {
if((long)mmap4k((void *)stack_base, (MAX_ARG_PAGES+1)*X86_PAGE_SIZE,
PROT_READ | PROT_WRITE,
MAP_GROWSDOWN | MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
perror("stk mmap");
exit(-1);
}
}
stktop = stack_base;
for (i = 0 ; i < MAX_ARG_PAGES ; i++) {
if (bprm->page[i]) {
info->rss++;
memcpy((void *)stack_base, (void *)bprm->page[i], X86_PAGE_SIZE);
free_page((void *)bprm->page[i]);
}
stack_base += X86_PAGE_SIZE;
}
return p;
}
static void set_brk(unsigned long start, unsigned long end)
{
/* page-align the start and end addresses... */
start = ALPHA_PAGE_ALIGN(start);
end = ALPHA_PAGE_ALIGN(end);
if (end <= start)
return;
if((long)mmap4k(start, end - start,
PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0) == -1) {
perror("cannot mmap brk");
exit(-1);
}
}
/* We need to explicitly zero any fractional pages
after the data section (i.e. bss). This would
contain the junk from the file that should not
be in memory */
static void padzero(unsigned long elf_bss)
{
unsigned long nbyte;
char * fpnt;
nbyte = elf_bss & (ALPHA_PAGE_SIZE-1); /* was X86_PAGE_SIZE - JRP */
if (nbyte) {
nbyte = ALPHA_PAGE_SIZE - nbyte;
fpnt = (char *) elf_bss;
do {
*fpnt++ = 0;
} while (--nbyte);
}
}
static unsigned int * create_elf_tables(char *p, int argc, int envc,
struct elfhdr * exec,
unsigned long load_addr,
unsigned long interp_load_addr, int ibcs,
struct image_info *info)
{
unsigned int *argv, *envp, *dlinfo;
unsigned int *sp;
char **alpha_envp;
/*
* Force 16 byte alignment here for generality.
*/
sp = (unsigned int *) (~15UL & (unsigned long) p);
sp -= exec ? DLINFO_ITEMS*2 : 2;
dlinfo = sp;
sp -= envc+1;
envp = sp;
sp -= argc+1;
argv = sp;
if (!ibcs) {
put_user(envp,--sp);
put_user(argv,--sp);
}
alpha_envp = (char **)malloc((envc+1) * sizeof(char *));
#define NEW_AUX_ENT(id, val) \
put_user ((id), dlinfo++); \
put_user ((val), dlinfo++)
if (exec) { /* Put this here for an ELF program interpreter */
struct elf_phdr * eppnt;
eppnt = (struct elf_phdr *)((unsigned long)exec->e_phoff);
NEW_AUX_ENT (AT_PHDR, (unsigned int)(load_addr + exec->e_phoff));
NEW_AUX_ENT (AT_PHENT, (unsigned int)(sizeof (struct elf_phdr)));
NEW_AUX_ENT (AT_PHNUM, (unsigned int)(exec->e_phnum));
NEW_AUX_ENT (AT_PAGESZ, (unsigned int)(ALPHA_PAGE_SIZE));
NEW_AUX_ENT (AT_BASE, (unsigned int)(interp_load_addr));
NEW_AUX_ENT (AT_FLAGS, (unsigned int)0);
NEW_AUX_ENT (AT_ENTRY, (unsigned int) exec->e_entry);
NEW_AUX_ENT (AT_UID, (unsigned int) getuid());
NEW_AUX_ENT (AT_EUID, (unsigned int) geteuid());
NEW_AUX_ENT (AT_GID, (unsigned int) getgid());
NEW_AUX_ENT (AT_EGID, (unsigned int) getegid());
}
NEW_AUX_ENT (AT_NULL, 0);
#undef NEW_AUX_ENT
put_user((unsigned int)argc,--sp);
info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff);
while (argc-->0) {
put_user(p,argv++);
while (get_user(p++)) /* nothing */ ;
}
put_user(0,argv);
info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff);
__environ = alpha_envp;
while (envc-->0) {
*alpha_envp++ = (char *)p;
put_user(p,envp++);
while (get_user(p++)) /* nothing */ ;
}
put_user(0,envp);
*alpha_envp = 0;
info->env_end = (unsigned int)((unsigned long)p & 0xffffffff);
return sp;
}
static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex,
int interpreter_fd,
unsigned long *interp_load_addr)
{
struct elf_phdr *elf_phdata = NULL;
struct elf_phdr *eppnt;
unsigned long load_addr;
int load_addr_set = 0;
int retval;
unsigned long last_bss, elf_bss;
unsigned long error;
int i;
elf_bss = 0;
last_bss = 0;
error = 0;
/* We put this here so that mmap will search for the *first*
* available memory...
*/
load_addr = INTERP_LOADADDR;
/* First of all, some simple consistency checks */
if ((interp_elf_ex->e_type != ET_EXEC &&
interp_elf_ex->e_type != ET_DYN) ||
!elf_check_arch(interp_elf_ex->e_machine)) {
return ~0UL;
}
/* Now read in all of the header information */
if (sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > X86_PAGE_SIZE)
return ~0UL;
elf_phdata = (struct elf_phdr *)
malloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
if (!elf_phdata)
return ~0UL;
/*
* If the size of this structure has changed, then punt, since
* we will be doing the wrong thing.
*/
if (interp_elf_ex->e_phentsize != sizeof(struct elf_phdr))
{
free(elf_phdata);
return ~0UL;
}
retval = lseek(interpreter_fd, interp_elf_ex->e_phoff, SEEK_SET);
if(retval >= 0) {
retval = read(interpreter_fd,
(char *) elf_phdata,
sizeof(struct elf_phdr) * interp_elf_ex->e_phnum);
}
if (retval < 0) {
perror("load_elf_interp");
exit(-1);
free (elf_phdata);
return retval;
}
#ifdef BSWAP_NEEDED
eppnt = elf_phdata;
for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
bswap_phdr(eppnt);
}
#endif
eppnt = elf_phdata;
for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
if (eppnt->p_type == PT_LOAD) {
int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
int elf_prot = 0;
unsigned long vaddr = 0;
unsigned long k;
if (eppnt->p_flags & PF_R) elf_prot = PROT_READ;
if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
if (interp_elf_ex->e_type == ET_EXEC || load_addr_set) {
elf_type |= MAP_FIXED;
vaddr = eppnt->p_vaddr;
}
error = (unsigned long)mmap4k(load_addr+X86_ELF_PAGESTART(vaddr),
eppnt->p_filesz + X86_ELF_PAGEOFFSET(eppnt->p_vaddr),
elf_prot,
elf_type,
interpreter_fd,
eppnt->p_offset - X86_ELF_PAGEOFFSET(eppnt->p_vaddr));
if (error > -1024UL) {
/* Real error */
close(interpreter_fd);
free(elf_phdata);
return ~0UL;
}
if (!load_addr_set && interp_elf_ex->e_type == ET_DYN) {
load_addr = error;
load_addr_set = 1;
}
/*
* Find the end of the file mapping for this phdr, and keep
* track of the largest address we see for this.
*/
k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
if (k > elf_bss) elf_bss = k;
/*
* Do the same thing for the memory mapping - between
* elf_bss and last_bss is the bss section.
*/
k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
if (k > last_bss) last_bss = k;
}
/* Now use mmap to map the library into memory. */
close(interpreter_fd);
/*
* Now fill out the bss section. First pad the last page up
* to the page boundary, and then perform a mmap to make sure
* that there are zeromapped pages up to and including the last
* bss page.
*/
padzero(elf_bss);
elf_bss = X86_ELF_PAGESTART(elf_bss + ALPHA_PAGE_SIZE - 1); /* What we have mapped so far */
/* Map the last of the bss segment */
if (last_bss > elf_bss) {
mmap4k(elf_bss, last_bss-elf_bss,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
}
free(elf_phdata);
*interp_load_addr = load_addr;
return ((unsigned long) interp_elf_ex->e_entry) + load_addr;
}
static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs,
struct image_info * info)
{
struct elfhdr elf_ex;
struct elfhdr interp_elf_ex;
struct exec interp_ex;
int interpreter_fd = -1; /* avoid warning */
unsigned long load_addr;
int load_addr_set = 0;
unsigned int interpreter_type = INTERPRETER_NONE;
unsigned char ibcs2_interpreter;
int i;
void * mapped_addr;
struct elf_phdr * elf_ppnt;
struct elf_phdr *elf_phdata;
unsigned long elf_bss, k, elf_brk;
int retval;
char * elf_interpreter;
unsigned long elf_entry, interp_load_addr = 0;
int status;
unsigned long start_code, end_code, end_data;
unsigned long elf_stack;
char passed_fileno[6];
ibcs2_interpreter = 0;
status = 0;
load_addr = 0;
elf_ex = *((struct elfhdr *) bprm->buf); /* exec-header */
#ifdef BSWAP_NEEDED
bswap_ehdr(&elf_ex);
#endif
if (elf_ex.e_ident[0] != 0x7f ||
strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
return -ENOEXEC;
}
/* First of all, some simple consistency checks */
if ((elf_ex.e_type != ET_EXEC && elf_ex.e_type != ET_DYN) ||
(! elf_check_arch(elf_ex.e_machine))) {
return -ENOEXEC;
}
/* Now read in all of the header information */
elf_phdata = (struct elf_phdr *)malloc(elf_ex.e_phentsize*elf_ex.e_phnum);
if (elf_phdata == NULL) {
return -ENOMEM;
}
retval = lseek(bprm->fd, elf_ex.e_phoff, SEEK_SET);
if(retval > 0) {
retval = read(bprm->fd, (char *) elf_phdata,
elf_ex.e_phentsize * elf_ex.e_phnum);
}
if (retval < 0) {
perror("load_elf_binary");
exit(-1);
free (elf_phdata);
return -errno;
}
elf_ppnt = elf_phdata;
elf_bss = 0;
elf_brk = 0;
elf_stack = ~0UL;
elf_interpreter = NULL;
start_code = ~0UL;
end_code = 0;
end_data = 0;
for(i=0;i < elf_ex.e_phnum; i++) {
if (elf_ppnt->p_type == PT_INTERP) {
if ( elf_interpreter != NULL )
{
free (elf_phdata);
free(elf_interpreter);
close(bprm->fd);
return -EINVAL;
}
/* This is the program interpreter used for
* shared libraries - for now assume that this
* is an a.out format binary
*/
elf_interpreter = (char *)malloc(elf_ppnt->p_filesz+strlen(X86_DEFAULT_LIB_DIR));
if (elf_interpreter == NULL) {
free (elf_phdata);
close(bprm->fd);
return -ENOMEM;
}
strcpy(elf_interpreter, X86_DEFAULT_LIB_DIR);
retval = lseek(bprm->fd, elf_ppnt->p_offset, SEEK_SET);
if(retval >= 0) {
retval = read(bprm->fd,
elf_interpreter+strlen(X86_DEFAULT_LIB_DIR),
elf_ppnt->p_filesz);
}
if(retval < 0) {
perror("load_elf_binary2");
exit(-1);
}
/* If the program interpreter is one of these two,
then assume an iBCS2 image. Otherwise assume
a native linux image. */
/* JRP - Need to add X86 lib dir stuff here... */
if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0) {
ibcs2_interpreter = 1;
}
#if 0
printf("Using ELF interpreter %s\n", elf_interpreter);
#endif
if (retval >= 0) {
retval = open(elf_interpreter, O_RDONLY);
if(retval >= 0) {
interpreter_fd = retval;
}
else {
perror(elf_interpreter);
exit(-1);
/* retval = -errno; */
}
}
if (retval >= 0) {
retval = lseek(interpreter_fd, 0, SEEK_SET);
if(retval >= 0) {
retval = read(interpreter_fd,bprm->buf,128);
}
}
if (retval >= 0) {
interp_ex = *((struct exec *) bprm->buf); /* aout exec-header */
interp_elf_ex=*((struct elfhdr *) bprm->buf); /* elf exec-header */
}
if (retval < 0) {
perror("load_elf_binary3");
exit(-1);
free (elf_phdata);
free(elf_interpreter);
close(bprm->fd);
return retval;
}
}
elf_ppnt++;
}
/* Some simple consistency checks for the interpreter */
if (elf_interpreter){
interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
/* Now figure out which format our binary is */
if ((N_MAGIC(interp_ex) != OMAGIC) && (N_MAGIC(interp_ex) != ZMAGIC) &&
(N_MAGIC(interp_ex) != QMAGIC)) {
interpreter_type = INTERPRETER_ELF;
}
if (interp_elf_ex.e_ident[0] != 0x7f ||
strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0) {
interpreter_type &= ~INTERPRETER_ELF;
}
if (!interpreter_type) {
free(elf_interpreter);
free(elf_phdata);
close(bprm->fd);
return -ELIBBAD;
}
}
/* OK, we are done with that, now set up the arg stuff,
and then start this sucker up */
if (!bprm->sh_bang) {
char * passed_p;
if (interpreter_type == INTERPRETER_AOUT) {
sprintf(passed_fileno, "%d", bprm->fd);
passed_p = passed_fileno;
if (elf_interpreter) {
bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p);
bprm->argc++;
}
}
if (!bprm->p) {
if (elf_interpreter) {
free(elf_interpreter);
}
free (elf_phdata);
close(bprm->fd);
return -E2BIG;
}
}
/* OK, This is the point of no return */
info->end_data = 0;
info->end_code = 0;
info->start_mmap = (unsigned long)ELF_START_MMAP;
info->mmap = 0;
elf_entry = (unsigned long) elf_ex.e_entry;
/* Do this so that we can load the interpreter, if need be. We will
change some of these later */
info->rss = 0;
bprm->p = setup_arg_pages(bprm->p, bprm, info);
info->start_stack = bprm->p;
/* Now we do a little grungy work by mmaping the ELF image into
* the correct location in memory. At this point, we assume that
* the image should be loaded at fixed address, not at a variable
* address.
*/
for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; i++, elf_ppnt++) {
if (elf_ppnt->p_type == PT_LOAD) {
int elf_prot = 0;
if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
mapped_addr = mmap4k(X86_ELF_PAGESTART(elf_ppnt->p_vaddr),
(elf_ppnt->p_filesz +
X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
elf_prot,
(MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE),
bprm->fd,
(elf_ppnt->p_offset -
X86_ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
if((unsigned long)mapped_addr == 0xffffffffffffffff) {
perror("mmap");
exit(-1);
}
#ifdef LOW_ELF_STACK
if (X86_ELF_PAGESTART(elf_ppnt->p_vaddr) < elf_stack)
elf_stack = X86_ELF_PAGESTART(elf_ppnt->p_vaddr);
#endif
if (!load_addr_set) {
load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
load_addr_set = 1;
}
k = elf_ppnt->p_vaddr;
if (k < start_code) start_code = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
if (k > elf_bss) elf_bss = k;
#if 1
if ((elf_ppnt->p_flags & PF_X) && end_code < k)
#else
if ( !(elf_ppnt->p_flags & PF_W) && end_code < k)
#endif
end_code = k;
if (end_data < k) end_data = k;
k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
if (k > elf_brk) elf_brk = k;
}
}
if (elf_interpreter) {
if (interpreter_type & 1) {
elf_entry = load_aout_interp(&interp_ex, interpreter_fd);
}
else if (interpreter_type & 2) {
elf_entry = load_elf_interp(&interp_elf_ex, interpreter_fd,
&interp_load_addr);
}
close(interpreter_fd);
free(elf_interpreter);
if (elf_entry == ~0UL) {
printf("Unable to load interpreter\n");
free(elf_phdata);
exit(-1);
return 0;
}
}
free(elf_phdata);
if (interpreter_type != INTERPRETER_AOUT) close(bprm->fd);
info->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
#ifdef LOW_ELF_STACK
info->start_stack = bprm->p = elf_stack - 4;
#endif
bprm->p = (unsigned long)
create_elf_tables((char *)bprm->p,
bprm->argc,
bprm->envc,
(interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
load_addr,
interp_load_addr,
(interpreter_type == INTERPRETER_AOUT ? 0 : 1),
info);
if (interpreter_type == INTERPRETER_AOUT)
info->arg_start += strlen(passed_fileno) + 1;
info->start_brk = info->brk = elf_brk;
info->end_code = end_code;
info->start_code = start_code;
info->end_data = end_data;
info->start_stack = bprm->p;
/* Calling set_brk effectively mmaps the pages that we need for the bss and break
sections */
set_brk(elf_bss, elf_brk);
padzero(elf_bss);
#if 0
printf("(start_brk) %x\n" , info->start_brk);
printf("(end_code) %x\n" , info->end_code);
printf("(start_code) %x\n" , info->start_code);
printf("(end_data) %x\n" , info->end_data);
printf("(start_stack) %x\n" , info->start_stack);
printf("(brk) %x\n" , info->brk);
#endif
if ( info->personality == PER_SVR4 )
{
/* Why this, you ask??? Well SVr4 maps page 0 as read-only,
and some applications "depend" upon this behavior.
Since we do not have the power to recompile these, we
emulate the SVr4 behavior. Sigh. */
mapped_addr = mmap4k(NULL, ALPHA_PAGE_SIZE, PROT_READ | PROT_EXEC,
MAP_FIXED | MAP_PRIVATE, -1, 0);
}
#ifdef ELF_PLAT_INIT
/*
* The ABI may specify that certain registers be set up in special
* ways (on i386 %edx is the address of a DT_FINI function, for
* example. This macro performs whatever initialization to
* the regs structure is required.
*/
ELF_PLAT_INIT(regs);
#endif
info->entry = elf_entry;
return 0;
}
int elf_exec(const char * filename, char ** argv, char ** envp,
struct pt_regs * regs, struct image_info *infop)
{
struct linux_binprm bprm;
int retval;
int i;
bprm.p = X86_PAGE_SIZE*MAX_ARG_PAGES-sizeof(unsigned int);
for (i=0 ; i<MAX_ARG_PAGES ; i++) /* clear page-table */
bprm.page[i] = 0;
retval = open(filename, O_RDONLY);
if (retval == -1) {
perror(filename);
exit(-1);
/* return retval; */
}
else {
bprm.fd = retval;
}
bprm.filename = (char *)filename;
bprm.sh_bang = 0;
bprm.loader = 0;
bprm.exec = 0;
bprm.dont_iput = 0;
bprm.argc = count(argv);
bprm.envc = count(envp);
retval = prepare_binprm(&bprm);
if(retval>=0) {
bprm.p = copy_strings(1, &bprm.filename, bprm.page, bprm.p);
bprm.exec = bprm.p;
bprm.p = copy_strings(bprm.envc,envp,bprm.page,bprm.p);
bprm.p = copy_strings(bprm.argc,argv,bprm.page,bprm.p);
if (!bprm.p) {
retval = -E2BIG;
}
}
if(retval>=0) {
retval = load_elf_binary(&bprm,regs,infop);
}
if(retval>=0) {
/* success. Initialize important registers */
regs->esp = infop->start_stack;
regs->eip = infop->entry;
return retval;
}
/* Something went wrong, return the inode and free the argument pages*/
for (i=0 ; i<MAX_ARG_PAGES ; i++) {
free_page((void *)bprm.page[i]);
}
return(retval);
}
static int load_aout_interp(void * exptr, int interp_fd)
{
printf("a.out interpreter not yet supported\n");
return(0);
}

282
linux-user/ioctls.h Normal file
View File

@ -0,0 +1,282 @@
/* emulated ioctl list */
IOCTL(TCGETS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TCGETS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TCSETSF, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TCSETSW, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TIOCGWINSZ, IOC_R, MK_PTR(MK_STRUCT(STRUCT_winsize)))
IOCTL(TIOCSWINSZ, IOC_W, MK_PTR(MK_STRUCT(STRUCT_winsize)))
IOCTL(FIONREAD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TCGETA, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TCSETA, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TCSETAW, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TCSETAF, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TCSBRK, 0, TYPE_INT)
IOCTL(TCSBRKP, 0, TYPE_INT)
IOCTL(TCXONC, 0, TYPE_INT)
IOCTL(TCFLSH, 0, TYPE_INT)
IOCTL(TIOCEXCL, 0, TYPE_NULL)
IOCTL(TIOCNXCL, 0, TYPE_NULL)
IOCTL(TIOCSCTTY, 0, TYPE_INT)
IOCTL(TIOCGPGRP, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSPGRP, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCOUTQ, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSTI, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCMGET, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCMBIS, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCMBIC, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCMSET, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCGSOFTCAR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSSOFTCAR, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCLINUX, IOC_R | IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCCONS, 0, TYPE_NULL)
IOCTL(TIOCGSERIAL, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSSERIAL, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCPKT, IOC_W, MK_PTR(TYPE_INT))
IOCTL(FIONBIO, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCNOTTY, 0, TYPE_NULL)
IOCTL(TIOCGETD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSETD, IOC_W, MK_PTR(TYPE_INT))
IOCTL(FIOCLEX, 0, TYPE_NULL)
IOCTL(FIONCLEX, 0, TYPE_NULL)
IOCTL(FIOASYNC, IOC_W, MK_PTR(TYPE_INT))
IOCTL(TIOCGLCKTRMIOS, IOC_R, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TIOCSLCKTRMIOS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_termios)))
IOCTL(TIOCSERCONFIG, 0, TYPE_NULL)
IOCTL(TIOCSERGETLSR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(TIOCSERGETMULTI, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct)))
IOCTL(TIOCSERSETMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_serial_multiport_struct)))
IOCTL(TIOCMIWAIT, 0, TYPE_INT)
IOCTL(TIOCGICOUNT, IOC_R, MK_PTR(MK_STRUCT(STRUCT_serial_icounter_struct)))
IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT))
IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT))
IOCTL(BLKRRPART, 0, TYPE_NULL)
IOCTL(BLKGETSIZE, IOC_R, MK_PTR(TYPE_ULONG))
#ifdef BLKGETSIZE64
IOCTL(BLKGETSIZE64, IOC_R, MK_PTR(TYPE_ULONGLONG))
#endif
IOCTL(BLKFLSBUF, 0, TYPE_NULL)
IOCTL(BLKRASET, 0, TYPE_INT)
IOCTL(BLKRAGET, IOC_R, MK_PTR(TYPE_LONG))
#ifdef FIBMAP
IOCTL(FIBMAP, IOC_W | IOC_R, MK_PTR(TYPE_LONG))
#endif
#ifdef FIGETBSZ
IOCTL(FIGETBSZ, IOC_R, MK_PTR(TYPE_LONG))
#endif
IOCTL(SIOCADDRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
IOCTL(SIOCDELRT, IOC_W, MK_PTR(MK_STRUCT(STRUCT_rtentry)))
IOCTL(SIOCGIFNAME, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SIOCGIFFLAGS, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(SIOCSIFFLAGS, IOC_W, MK_PTR(MK_STRUCT(STRUCT_short_ifreq)))
IOCTL(SIOCGIFADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFBRDADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFBRDADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFDSTADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFDSTADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFNETMASK, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFNETMASK, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFHWADDR, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFHWADDR, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFTXQLEN, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFTXQLEN, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCGIFMETRIC, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
IOCTL(SIOCSIFMETRIC, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
IOCTL(SIOCGIFMTU, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
IOCTL(SIOCSIFMTU, IOC_W, MK_PTR(MK_STRUCT(STRUCT_int_ifreq)))
IOCTL(SIOCGIFMAP, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq)))
IOCTL(SIOCSIFMAP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ifmap_ifreq)))
IOCTL(SIOCGIFSLAVE, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
IOCTL(SIOCSIFSLAVE, IOC_W, MK_PTR(MK_STRUCT(STRUCT_char_ifreq)))
IOCTL(SIOCGIFMEM, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
IOCTL(SIOCSIFMEM, IOC_W, MK_PTR(MK_STRUCT(STRUCT_ptr_ifreq)))
IOCTL(SIOCADDMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCDELMULTI, IOC_W, MK_PTR(MK_STRUCT(STRUCT_sockaddr_ifreq)))
IOCTL(SIOCSIFLINK, 0, TYPE_NULL)
IOCTL(SIOCGIFCONF, IOC_W | IOC_R, MK_PTR(MK_STRUCT(STRUCT_ifconf)))
IOCTL(SIOCGIFENCAP, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SIOCSIFENCAP, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SIOCDARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCSARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCGARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCDRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCSRARP, IOC_W, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(SIOCGRARP, IOC_R, MK_PTR(MK_STRUCT(STRUCT_arpreq)))
IOCTL(CDROMPAUSE, 0, TYPE_NULL)
IOCTL(CDROMSTART, 0, TYPE_NULL)
IOCTL(CDROMSTOP, 0, TYPE_NULL)
IOCTL(CDROMRESUME, 0, TYPE_NULL)
IOCTL(CDROMEJECT, 0, TYPE_NULL)
IOCTL(CDROMEJECT_SW, 0, TYPE_INT)
IOCTL(CDROMCLOSETRAY, 0, TYPE_NULL)
IOCTL(CDROMRESET, 0, TYPE_NULL)
IOCTL(CDROMPLAYMSF, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMPLAYTRKIND, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMREADTOCHDR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(CDROMREADTOCENTRY, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMVOLCTRL, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMSUBCHNL, IOC_RW, MK_PTR(TYPE_INT))
/* XXX: incorrect (need specific handling) */
IOCTL(CDROMREADAUDIO, IOC_W, MK_PTR(MK_STRUCT(STRUCT_cdrom_read_audio)))
IOCTL(CDROMREADCOOKED, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMREADRAW, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMREADMODE1, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMREADMODE2, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMREADALL, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROMMULTISESSION, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(CDROM_GET_UPC, IOC_R, MK_PTR(TYPE_INT))
IOCTL(CDROMVOLREAD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(CDROMSEEK, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROMPLAYBLK, IOC_W, MK_PTR(TYPE_INT))
IOCTL(CDROM_MEDIA_CHANGED, 0, TYPE_NULL)
IOCTL(CDROM_SET_OPTIONS, 0, TYPE_INT)
IOCTL(CDROM_CLEAR_OPTIONS, 0, TYPE_INT)
IOCTL(CDROM_SELECT_SPEED, 0, TYPE_INT)
IOCTL(CDROM_SELECT_DISC, 0, TYPE_INT)
IOCTL(CDROM_DRIVE_STATUS, 0, TYPE_NULL)
IOCTL(CDROM_DISC_STATUS, 0, TYPE_NULL)
IOCTL(CDROMAUDIOBUFSIZ, 0, TYPE_INT)
IOCTL(SNDCTL_COPR_HALT, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_LOAD, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_RCODE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_RCVMSG, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_RDATA, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_RESET, 0, TYPE_NULL)
IOCTL(SNDCTL_COPR_RUN, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_SENDMSG, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_WCODE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_COPR_WDATA, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_CHANNELS, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETBLKSIZE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETCAPS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETFMTS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETIPTR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETISPACE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETOPTR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETOSPACE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_GETTRIGGER, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_MAPINBUF, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_MAPOUTBUF, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_NONBLOCK, 0, TYPE_NULL)
IOCTL(SNDCTL_DSP_POST, 0, TYPE_NULL)
IOCTL(SNDCTL_DSP_RESET, 0, TYPE_NULL)
IOCTL(SNDCTL_DSP_SETDUPLEX, 0, TYPE_NULL)
IOCTL(SNDCTL_DSP_SETFMT, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_SETFRAGMENT, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_SETSYNCRO, 0, TYPE_NULL)
IOCTL(SNDCTL_DSP_SETTRIGGER, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_SPEED, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_STEREO, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_SUBDIVIDE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_DSP_SYNC, 0, TYPE_NULL)
IOCTL(SNDCTL_FM_4OP_ENABLE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_FM_LOAD_INSTR, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_MIDI_INFO, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_MIDI_MPUCMD, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_MIDI_MPUMODE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_MIDI_PRETIME, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_CTRLRATE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_GETINCOUNT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_GETOUTCOUNT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_NRMIDIS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_NRSYNTHS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_OUTOFBAND, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_PANIC, 0, TYPE_NULL)
IOCTL(SNDCTL_SEQ_PERCMODE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_RESET, 0, TYPE_NULL)
IOCTL(SNDCTL_SEQ_RESETSAMPLES, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_SYNC, 0, TYPE_NULL)
IOCTL(SNDCTL_SEQ_TESTMIDI, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SEQ_THRESHOLD, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SYNTH_INFO, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_SYNTH_MEMAVL, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_TMR_CONTINUE, 0, TYPE_NULL)
IOCTL(SNDCTL_TMR_METRONOME, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_TMR_SELECT, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_TMR_SOURCE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_TMR_START, 0, TYPE_NULL)
IOCTL(SNDCTL_TMR_STOP, 0, TYPE_NULL)
IOCTL(SNDCTL_TMR_TEMPO, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SNDCTL_TMR_TIMEBASE, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_PCM_WRITE_FILTER, IOC_W | IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_PCM_READ_RATE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_PCM_READ_CHANNELS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_PCM_READ_BITS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_PCM_READ_FILTER, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_INFO, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_ACCESS, 0, TYPE_PTRVOID)
IOCTL(SOUND_MIXER_PRIVATE1, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_PRIVATE2, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_PRIVATE3, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_PRIVATE4, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_PRIVATE5, IOC_RW, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_VOLUME, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_BASS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_TREBLE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_SYNTH, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_PCM, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_SPEAKER, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_LINE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_MIC, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_CD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_IMIX, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_ALTPCM, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_RECLEV, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_IGAIN, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_OGAIN, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_LINE1, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_LINE2, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_LINE3, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_MUTE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_ENHANCE, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_LOUD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_RECSRC, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_DEVMASK, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_RECMASK, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_STEREODEVS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_READ_CAPS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_VOLUME, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_BASS, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_TREBLE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_SYNTH, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_PCM, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_SPEAKER, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_LINE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_MIC, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_CD, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_IMIX, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_ALTPCM, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_RECLEV, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_IGAIN, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_OGAIN, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_LINE1, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_LINE2, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_LINE3, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_MUTE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_ENHANCE, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_LOUD, IOC_W, MK_PTR(TYPE_INT))
IOCTL(SOUND_MIXER_WRITE_RECSRC, IOC_W, MK_PTR(TYPE_INT))
IOCTL(HDIO_GETGEO, IOC_R, MK_PTR(MK_STRUCT(STRUCT_hd_geometry)))
IOCTL(HDIO_GET_UNMASKINTR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_MULTCOUNT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_IDENTITY, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_KEEPSETTINGS, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_NOWERR, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_DMA, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_GET_32BIT, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_DRIVE_CMD, IOC_R, MK_PTR(TYPE_INT))
IOCTL(HDIO_SET_UNMASKINTR, 0, TYPE_INT)
IOCTL(HDIO_SET_MULTCOUNT, 0, TYPE_INT)
IOCTL(HDIO_SET_KEEPSETTINGS, 0, TYPE_INT)
IOCTL(HDIO_SET_NOWERR, 0, TYPE_INT)
IOCTL(HDIO_SET_DMA, 0, TYPE_INT)
IOCTL(HDIO_SET_32BIT, 0, TYPE_INT)
IOCTL(HDIO_SET_PIO_MODE, 0, TYPE_INT)

310
linux-user/main.c Normal file
View File

@ -0,0 +1,310 @@
/*
* emu main
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <elf.h>
#include <endian.h>
#include <errno.h>
#include "gemu.h"
#include "i386/hsw_interp.h"
unsigned long x86_stack_size;
unsigned long stktop;
void gemu_log(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/* virtual x86 CPU stuff */
extern int invoke_code16(Interp_ENV *, int, int);
extern int invoke_code32(Interp_ENV *, int);
extern char *e_print_cpuemu_regs(ENVPARAMS, int is32);
extern char *e_emu_disasm(ENVPARAMS, unsigned char *org, int is32);
extern void init_npu(void);
Interp_ENV env_global;
Interp_ENV *envp_global;
QWORD EMUtime = 0;
int CEmuStat = 0;
long instr_count;
/* who will initialize this? */
unsigned long io_bitmap[IO_BITMAP_SIZE+1];
/* debug flag, 0=disable 1..9=level */
int d_emu = 0;
unsigned long CRs[5] =
{
0x00000013, /* valid bits: 0xe005003f */
0x00000000, /* invalid */
0x00000000,
0x00000000,
0x00000000
};
/*
* DR0-3 = linear address of breakpoint 0-3
* DR4=5 = reserved
* DR6 b0-b3 = BP active
* b13 = BD
* b14 = BS
* b15 = BT
* DR7 b0-b1 = G:L bp#0
* b2-b3 = G:L bp#1
* b4-b5 = G:L bp#2
* b6-b7 = G:L bp#3
* b8-b9 = GE:LE
* b13 = GD
* b16-19= LLRW bp#0 LL=00(1),01(2),11(4)
* b20-23= LLRW bp#1 RW=00(x),01(w),11(rw)
* b24-27= LLRW bp#2
* b28-31= LLRW bp#3
*/
unsigned long DRs[8] =
{
0x00000000,
0x00000000,
0x00000000,
0x00000000,
0xffff1ff0,
0x00000400,
0xffff1ff0,
0x00000400
};
unsigned long TRs[2] =
{
0x00000000,
0x00000000
};
void FatalAppExit(UINT wAction, LPCSTR lpText)
{
fprintf(stderr, "Fatal error '%s' in CPU\n", lpText);
exit(1);
}
int e_debug_check(unsigned char *PC)
{
register unsigned long d7 = DRs[7];
if (d7&0x03) {
if (d7&0x30000) return 0; /* only execute(00) bkp */
if ((long)PC==DRs[0]) {
e_printf("DBRK: DR0 hit at %p\n",PC);
DRs[6] |= 1;
return 1;
}
}
if (d7&0x0c) {
if (d7&0x300000) return 0;
if ((long)PC==DRs[1]) {
e_printf("DBRK: DR1 hit at %p\n",PC);
DRs[6] |= 2;
return 1;
}
}
if (d7&0x30) {
if (d7&0x3000000) return 0;
if ((long)PC==DRs[2]) {
e_printf("DBRK: DR2 hit at %p\n",PC);
DRs[6] |= 4;
return 1;
}
}
if (d7&0xc0) {
if (d7&0x30000000) return 0;
if ((long)PC==DRs[3]) {
e_printf("DBRK: DR3 hit at %p\n",PC);
DRs[6] |= 8;
return 1;
}
}
return 0;
}
/* Debug stuff */
void logstr(unsigned long mask, const char *fmt,...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
/* unconditional message into debug log and stderr */
#undef error
void error(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
exit(1);
}
int PortIO(DWORD port, DWORD value, UINT size, BOOL is_write)
{
fprintf(stderr, "IO: %s port=0x%lx value=0x%lx size=%d",
is_write ? "write" : "read", port, value, size);
return value;
}
void LogProcName(WORD wSel, WORD wOff, WORD wAction)
{
}
void INT_handler(int num, void *env)
{
fprintf(stderr, "EM86: int %d\n", num);
}
/***********************************************************/
/* XXX: currently we use LDT entries */
#define __USER_CS (0x23|4)
#define __USER_DS (0x2B|4)
void usage(void)
{
printf("gemu version 0.1, Copyright (c) 2003 Fabrice Bellard\n"
"usage: gemu program [arguments...]\n"
"Linux x86 emulator\n"
);
exit(1);
}
int main(int argc, char **argv)
{
const char *filename;
struct pt_regs regs1, *regs = &regs1;
struct image_info info1, *info = &info1;
Interp_ENV *env;
if (argc <= 1)
usage();
filename = argv[1];
/* Zero out regs */
memset(regs, 0, sizeof(struct pt_regs));
/* Zero out image_info */
memset(info, 0, sizeof(struct image_info));
if(elf_exec(filename, argv+1, __environ, regs, info) != 0) {
printf("Error loading %s\n", filename);
exit(1);
}
#if 0
printf("start_brk 0x%08lx\n" , info->start_brk);
printf("end_code 0x%08lx\n" , info->end_code);
printf("start_code 0x%08lx\n" , info->start_code);
printf("end_data 0x%08lx\n" , info->end_data);
printf("start_stack 0x%08lx\n" , info->start_stack);
printf("brk 0x%08lx\n" , info->brk);
printf("esp 0x%08lx\n" , regs->esp);
printf("eip 0x%08lx\n" , regs->eip);
#endif
target_set_brk((char *)info->brk);
syscall_init();
env = &env_global;
envp_global = env;
memset(env, 0, sizeof(Interp_ENV));
env->rax.e = regs->eax;
env->rbx.e = regs->ebx;
env->rcx.e = regs->ecx;
env->rdx.e = regs->edx;
env->rsi.esi = regs->esi;
env->rdi.edi = regs->edi;
env->rbp.ebp = regs->ebp;
env->rsp.esp = regs->esp;
env->cs.cs = __USER_CS;
env->ds.ds = __USER_DS;
env->es.es = __USER_DS;
env->ss.ss = __USER_DS;
env->fs.fs = __USER_DS;
env->gs.gs = __USER_DS;
env->trans_addr = regs->eip;
LDT[__USER_CS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_CS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_CS >> 3].lpSelBase = NULL;
LDT[__USER_DS >> 3].w86Flags = DF_PRESENT | DF_PAGES | DF_32;
LDT[__USER_DS >> 3].dwSelLimit = 0xfffff;
LDT[__USER_DS >> 3].lpSelBase = NULL;
init_npu();
for(;;) {
int err;
uint8_t *pc;
err = invoke_code32(env, -1);
env->trans_addr = env->return_addr;
pc = env->seg_regs[0] + env->trans_addr;
switch(err) {
case EXCP0D_GPF:
if (pc[0] == 0xcd && pc[1] == 0x80) {
/* syscall */
env->trans_addr += 2;
env->rax.e = do_syscall(env->rax.e,
env->rbx.e,
env->rcx.e,
env->rdx.e,
env->rsi.esi,
env->rdi.edi,
env->rbp.ebp);
} else {
goto trap_error;
}
break;
default:
trap_error:
fprintf(stderr, "GEMU: Unknown error %d, aborting\n", err);
d_emu = 9;
fprintf(stderr, "%s\n%s\n",
e_print_cpuemu_regs(env, 1),
e_emu_disasm(env,pc,1));
abort();
}
}
return 0;
}

57
linux-user/qemu.h Normal file
View File

@ -0,0 +1,57 @@
#ifndef GEMU_H
#define GEMU_H
#include "thunk.h"
struct pt_regs {
long ebx;
long ecx;
long edx;
long esi;
long edi;
long ebp;
long eax;
int xds;
int xes;
long orig_eax;
long eip;
int xcs;
long eflags;
long esp;
int xss;
};
/* This struct is used to hold certain information about the image.
* Basically, it replicates in user space what would be certain
* task_struct fields in the kernel
*/
struct image_info {
unsigned long start_code;
unsigned long end_code;
unsigned long end_data;
unsigned long start_brk;
unsigned long brk;
unsigned long start_mmap;
unsigned long mmap;
unsigned long rss;
unsigned long start_stack;
unsigned long arg_start;
unsigned long arg_end;
unsigned long env_start;
unsigned long env_end;
unsigned long entry;
int personality;
};
int elf_exec(const char * filename, char ** argv, char ** envp,
struct pt_regs * regs, struct image_info *infop);
void target_set_brk(char *new_brk);
void syscall_init(void);
long do_syscall(int num, long arg1, long arg2, long arg3,
long arg4, long arg5, long arg6);
void gemu_log(const char *fmt, ...) __attribute__((format(printf,1,2)));
#endif

105
linux-user/signal.c Normal file
View File

@ -0,0 +1,105 @@
/*
* Emulation of Linux signal handling
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include <signal.h>
#include <sys/ucontext.h>
/* Algorithm strongly inspired from em86 : we queue the signals so
that we can handle them at precise points in the emulated code. */
struct emulated_sigaction {
struct target_sigaction sa;
int nb_pending;
struct target_siginfo info;
};
struct emulated_sigaction sigact_table[NSIG];
int signal_pending;
static inline int host_to_target_signal(int sig)
{
return sig;
}
static inline int target_to_host_signal(int sig)
{
return sig;
}
void signal_init(void)
{
struct sigaction act;
int i;
/* set all host signal handlers */
sigemptyset(&act.sa_mask);
act.sa_flags = SA_SIGINFO;
act.sa_sigaction = host_signal_handler;
for(i = 1; i < NSIG; i++) {
sigaction(i, &sa, NULL);
}
memset(sigact_table, 0, sizeof(sigact_table));
}
static void host_signal_handler(int host_signum, siginfo_t *info,
void *puc)
{
struct ucontext *uc = puc;
int signum;
/* get target signal number */
signum = host_to_target(host_signum);
if (signum >= TARGET_NSIG)
return;
/* we save the old mask */
}
void process_pending_signals(void)
{
int signum;
target_ulong _sa_handler;
struct emulated_sigaction *esig;
if (!signal_pending)
return;
esig = sigact_table;
for(signum = 1; signum < TARGET_NSIG; signum++) {
if (esig->nb_pending != 0)
goto handle_signal;
esig++;
}
/* if no signal is pending, just return */
signal_pending = 0;
return;
handle_signal:
_sa_handler = esig->sa._sa_handler;
if (_sa_handler == TARGET_SIG_DFL) {
/* default handling
}
}

1349
linux-user/syscall.c Normal file

File diff suppressed because it is too large Load Diff

283
linux-user/syscall_defs.h Normal file
View File

@ -0,0 +1,283 @@
/* common syscall defines for all architectures */
#define SOCKOP_socket 1
#define SOCKOP_bind 2
#define SOCKOP_connect 3
#define SOCKOP_listen 4
#define SOCKOP_accept 5
#define SOCKOP_getsockname 6
#define SOCKOP_getpeername 7
#define SOCKOP_socketpair 8
#define SOCKOP_send 9
#define SOCKOP_recv 10
#define SOCKOP_sendto 11
#define SOCKOP_recvfrom 12
#define SOCKOP_shutdown 13
#define SOCKOP_setsockopt 14
#define SOCKOP_getsockopt 15
#define SOCKOP_sendmsg 16
#define SOCKOP_recvmsg 17
struct target_timeval {
target_long tv_sec;
target_long tv_usec;
};
struct target_iovec {
target_long iov_base; /* Starting address */
target_long iov_len; /* Number of bytes */
};
struct target_rusage {
struct target_timeval ru_utime; /* user time used */
struct target_timeval ru_stime; /* system time used */
target_long ru_maxrss; /* maximum resident set size */
target_long ru_ixrss; /* integral shared memory size */
target_long ru_idrss; /* integral unshared data size */
target_long ru_isrss; /* integral unshared stack size */
target_long ru_minflt; /* page reclaims */
target_long ru_majflt; /* page faults */
target_long ru_nswap; /* swaps */
target_long ru_inblock; /* block input operations */
target_long ru_oublock; /* block output operations */
target_long ru_msgsnd; /* messages sent */
target_long ru_msgrcv; /* messages received */
target_long ru_nsignals; /* signals received */
target_long ru_nvcsw; /* voluntary context switches */
target_long ru_nivcsw; /* involuntary " */
};
typedef struct {
int val[2];
} kernel_fsid_t;
struct statfs {
int f_type;
int f_bsize;
int f_blocks;
int f_bfree;
int f_bavail;
int f_files;
int f_ffree;
kernel_fsid_t f_fsid;
int f_namelen;
int f_spare[6];
};
/* mostly generic signal stuff */
#define TARGET_SIG_DFL ((target_long)0) /* default signal handling */
#define TARGET_SIG_IGN ((target_long)1) /* ignore signal */
#define TARGET_SIG_ERR ((target_long)-1) /* error return from signal */
#ifdef TARGET_MIPS
#define TARGET_NSIG 128
#else
#define TARGET_NSIG 64
#endif
#define TARGET_NSIG_BPW TARGET_LONG_BITS
#define TARGET_NSIG_WORDS (TARGET_NSIG / TARGET_NSIG_BPW)
typedef struct {
target_ulong sig[TARGET_NSIG_WORDS];
} target_sigset_t;
/* Networking ioctls */
#define TARGET_SIOCADDRT 0x890B /* add routing table entry */
#define TARGET_SIOCDELRT 0x890C /* delete routing table entry */
#define TARGET_SIOCGIFNAME 0x8910 /* get iface name */
#define TARGET_SIOCSIFLINK 0x8911 /* set iface channel */
#define TARGET_SIOCGIFCONF 0x8912 /* get iface list */
#define TARGET_SIOCGIFFLAGS 0x8913 /* get flags */
#define TARGET_SIOCSIFFLAGS 0x8914 /* set flags */
#define TARGET_SIOCGIFADDR 0x8915 /* get PA address */
#define TARGET_SIOCSIFADDR 0x8916 /* set PA address */
#define TARGET_SIOCGIFDSTADDR 0x8917 /* get remote PA address */
#define TARGET_SIOCSIFDSTADDR 0x8918 /* set remote PA address */
#define TARGET_SIOCGIFBRDADDR 0x8919 /* get broadcast PA address */
#define TARGET_SIOCSIFBRDADDR 0x891a /* set broadcast PA address */
#define TARGET_SIOCGIFNETMASK 0x891b /* get network PA mask */
#define TARGET_SIOCSIFNETMASK 0x891c /* set network PA mask */
#define TARGET_SIOCGIFMETRIC 0x891d /* get metric */
#define TARGET_SIOCSIFMETRIC 0x891e /* set metric */
#define TARGET_SIOCGIFMEM 0x891f /* get memory address (BSD) */
#define TARGET_SIOCSIFMEM 0x8920 /* set memory address (BSD) */
#define TARGET_SIOCGIFMTU 0x8921 /* get MTU size */
#define TARGET_SIOCSIFMTU 0x8922 /* set MTU size */
#define TARGET_SIOCSIFHWADDR 0x8924 /* set hardware address (NI) */
#define TARGET_SIOCGIFENCAP 0x8925 /* get/set slip encapsulation */
#define TARGET_SIOCSIFENCAP 0x8926
#define TARGET_SIOCGIFHWADDR 0x8927 /* Get hardware address */
#define TARGET_SIOCGIFSLAVE 0x8929 /* Driver slaving support */
#define TARGET_SIOCSIFSLAVE 0x8930
#define TARGET_SIOCADDMULTI 0x8931 /* Multicast address lists */
#define TARGET_SIOCDELMULTI 0x8932
/* Bridging control calls */
#define TARGET_SIOCGIFBR 0x8940 /* Bridging support */
#define TARGET_SIOCSIFBR 0x8941 /* Set bridging options */
#define TARGET_SIOCGIFTXQLEN 0x8942 /* Get the tx queue length */
#define TARGET_SIOCSIFTXQLEN 0x8943 /* Set the tx queue length */
/* ARP cache control calls. */
#define TARGET_OLD_SIOCDARP 0x8950 /* old delete ARP table entry */
#define TARGET_OLD_SIOCGARP 0x8951 /* old get ARP table entry */
#define TARGET_OLD_SIOCSARP 0x8952 /* old set ARP table entry */
#define TARGET_SIOCDARP 0x8953 /* delete ARP table entry */
#define TARGET_SIOCGARP 0x8954 /* get ARP table entry */
#define TARGET_SIOCSARP 0x8955 /* set ARP table entry */
/* RARP cache control calls. */
#define TARGET_SIOCDRARP 0x8960 /* delete RARP table entry */
#define TARGET_SIOCGRARP 0x8961 /* get RARP table entry */
#define TARGET_SIOCSRARP 0x8962 /* set RARP table entry */
/* Driver configuration calls */
#define TARGET_SIOCGIFMAP 0x8970 /* Get device parameters */
#define TARGET_SIOCSIFMAP 0x8971 /* Set device parameters */
/* DLCI configuration calls */
#define TARGET_SIOCADDDLCI 0x8980 /* Create new DLCI device */
#define TARGET_SIOCDELDLCI 0x8981 /* Delete DLCI device */
/* From <linux/fs.h> */
#define TARGET_BLKROSET TARGET_IO(0x12,93) /* set device read-only (0 = read-write) */
#define TARGET_BLKROGET TARGET_IO(0x12,94) /* get read-only status (0 = read_write) */
#define TARGET_BLKRRPART TARGET_IO(0x12,95) /* re-read partition table */
#define TARGET_BLKGETSIZE TARGET_IO(0x12,96) /* return device size /512 (long *arg) */
#define TARGET_BLKFLSBUF TARGET_IO(0x12,97) /* flush buffer cache */
#define TARGET_BLKRASET TARGET_IO(0x12,98) /* Set read ahead for block device */
#define TARGET_BLKRAGET TARGET_IO(0x12,99) /* get current read ahead setting */
#define TARGET_BLKFRASET TARGET_IO(0x12,100)/* set filesystem (mm/filemap.c) read-ahead */
#define TARGET_BLKFRAGET TARGET_IO(0x12,101)/* get filesystem (mm/filemap.c) read-ahead */
#define TARGET_BLKSECTSET TARGET_IO(0x12,102)/* set max sectors per request (ll_rw_blk.c) */
#define TARGET_BLKSECTGET TARGET_IO(0x12,103)/* get max sectors per request (ll_rw_blk.c) */
#define TARGET_BLKSSZGET TARGET_IO(0x12,104)/* get block device sector size */
/* A jump here: 108-111 have been used for various private purposes. */
#define TARGET_BLKBSZGET TARGET_IOR(0x12,112,sizeof(int))
#define TARGET_BLKBSZSET TARGET_IOW(0x12,113,sizeof(int))
#define TARGET_BLKGETSIZE64 TARGET_IOR(0x12,114,sizeof(uint64_t)) /* return device size in bytes (u64 *arg) */
#define TARGET_FIBMAP TARGET_IO(0x00,1) /* bmap access */
#define TARGET_FIGETBSZ TARGET_IO(0x00,2) /* get the block size used for bmap */
/* cdrom commands */
#define TARGET_CDROMPAUSE 0x5301 /* Pause Audio Operation */
#define TARGET_CDROMRESUME 0x5302 /* Resume paused Audio Operation */
#define TARGET_CDROMPLAYMSF 0x5303 /* Play Audio MSF (struct cdrom_msf) */
#define TARGET_CDROMPLAYTRKIND 0x5304 /* Play Audio Track/index
(struct cdrom_ti) */
#define TARGET_CDROMREADTOCHDR 0x5305 /* Read TOC header
(struct cdrom_tochdr) */
#define TARGET_CDROMREADTOCENTRY 0x5306 /* Read TOC entry
(struct cdrom_tocentry) */
#define TARGET_CDROMSTOP 0x5307 /* Stop the cdrom drive */
#define TARGET_CDROMSTART 0x5308 /* Start the cdrom drive */
#define TARGET_CDROMEJECT 0x5309 /* Ejects the cdrom media */
#define TARGET_CDROMVOLCTRL 0x530a /* Control output volume
(struct cdrom_volctrl) */
#define TARGET_CDROMSUBCHNL 0x530b /* Read subchannel data
(struct cdrom_subchnl) */
#define TARGET_CDROMREADMODE2 0x530c /* Read TARGET_CDROM mode 2 data (2336 Bytes)
(struct cdrom_read) */
#define TARGET_CDROMREADMODE1 0x530d /* Read TARGET_CDROM mode 1 data (2048 Bytes)
(struct cdrom_read) */
#define TARGET_CDROMREADAUDIO 0x530e /* (struct cdrom_read_audio) */
#define TARGET_CDROMEJECT_SW 0x530f /* enable(1)/disable(0) auto-ejecting */
#define TARGET_CDROMMULTISESSION 0x5310 /* Obtain the start-of-last-session
address of multi session disks
(struct cdrom_multisession) */
#define TARGET_CDROM_GET_MCN 0x5311 /* Obtain the "Universal Product Code"
if available (struct cdrom_mcn) */
#define TARGET_CDROM_GET_UPC TARGET_CDROM_GET_MCN /* This one is depricated,
but here anyway for compatability */
#define TARGET_CDROMRESET 0x5312 /* hard-reset the drive */
#define TARGET_CDROMVOLREAD 0x5313 /* Get the drive's volume setting
(struct cdrom_volctrl) */
#define TARGET_CDROMREADRAW 0x5314 /* read data in raw mode (2352 Bytes)
(struct cdrom_read) */
/*
* These ioctls are used only used in aztcd.c and optcd.c
*/
#define TARGET_CDROMREADCOOKED 0x5315 /* read data in cooked mode */
#define TARGET_CDROMSEEK 0x5316 /* seek msf address */
/*
* This ioctl is only used by the scsi-cd driver.
It is for playing audio in logical block addressing mode.
*/
#define TARGET_CDROMPLAYBLK 0x5317 /* (struct cdrom_blk) */
/*
* These ioctls are only used in optcd.c
*/
#define TARGET_CDROMREADALL 0x5318 /* read all 2646 bytes */
/*
* These ioctls are (now) only in ide-cd.c for controlling
* drive spindown time. They should be implemented in the
* Uniform driver, via generic packet commands, GPCMD_MODE_SELECT_10,
* GPCMD_MODE_SENSE_10 and the GPMODE_POWER_PAGE...
* -Erik
*/
#define TARGET_CDROMGETSPINDOWN 0x531d
#define TARGET_CDROMSETSPINDOWN 0x531e
/*
* These ioctls are implemented through the uniform CD-ROM driver
* They _will_ be adopted by all CD-ROM drivers, when all the CD-ROM
* drivers are eventually ported to the uniform CD-ROM driver interface.
*/
#define TARGET_CDROMCLOSETRAY 0x5319 /* pendant of CDROMEJECT */
#define TARGET_CDROM_SET_OPTIONS 0x5320 /* Set behavior options */
#define TARGET_CDROM_CLEAR_OPTIONS 0x5321 /* Clear behavior options */
#define TARGET_CDROM_SELECT_SPEED 0x5322 /* Set the CD-ROM speed */
#define TARGET_CDROM_SELECT_DISC 0x5323 /* Select disc (for juke-boxes) */
#define TARGET_CDROM_MEDIA_CHANGED 0x5325 /* Check is media changed */
#define TARGET_CDROM_DRIVE_STATUS 0x5326 /* Get tray position, etc. */
#define TARGET_CDROM_DISC_STATUS 0x5327 /* Get disc type, etc. */
#define TARGET_CDROM_CHANGER_NSLOTS 0x5328 /* Get number of slots */
#define TARGET_CDROM_LOCKDOOR 0x5329 /* lock or unlock door */
#define TARGET_CDROM_DEBUG 0x5330 /* Turn debug messages on/off */
#define TARGET_CDROM_GET_CAPABILITY 0x5331 /* get capabilities */
/* Note that scsi/scsi_ioctl.h also uses 0x5382 - 0x5386.
* Future CDROM ioctls should be kept below 0x537F
*/
/* This ioctl is only used by sbpcd at the moment */
#define TARGET_CDROMAUDIOBUFSIZ 0x5382 /* set the audio buffer size */
/* conflict with SCSI_IOCTL_GET_IDLUN */
/* DVD-ROM Specific ioctls */
#define TARGET_DVD_READ_STRUCT 0x5390 /* Read structure */
#define TARGET_DVD_WRITE_STRUCT 0x5391 /* Write structure */
#define TARGET_DVD_AUTH 0x5392 /* Authentication */
#define TARGET_CDROM_SEND_PACKET 0x5393 /* send a packet to the drive */
#define TARGET_CDROM_NEXT_WRITABLE 0x5394 /* get next writable block */
#define TARGET_CDROM_LAST_WRITTEN 0x5395 /* get last block written on disc */
/* HD commands */
/* hd/ide ctl's that pass (arg) ptrs to user space are numbered 0x030n/0x031n */
#define TARGET_HDIO_GETGEO 0x0301 /* get device geometry */
#define TARGET_HDIO_GET_UNMASKINTR 0x0302 /* get current unmask setting */
#define TARGET_HDIO_GET_MULTCOUNT 0x0304 /* get current IDE blockmode setting */
#define TARGET_HDIO_GET_IDENTITY 0x0307 /* get IDE identification info */
#define TARGET_HDIO_GET_KEEPSETTINGS 0x0308 /* get keep-settings-on-reset flag */
#define TARGET_HDIO_GET_32BIT 0x0309 /* get current io_32bit setting */
#define TARGET_HDIO_GET_NOWERR 0x030a /* get ignore-write-error flag */
#define TARGET_HDIO_GET_DMA 0x030b /* get use-dma flag */
#define TARGET_HDIO_DRIVE_CMD 0x031f /* execute a special drive command */
/* hd/ide ctl's that pass (arg) non-ptr values are numbered 0x032n/0x033n */
#define TARGET_HDIO_SET_MULTCOUNT 0x0321 /* change IDE blockmode */
#define TARGET_HDIO_SET_UNMASKINTR 0x0322 /* permit other irqs during I/O */
#define TARGET_HDIO_SET_KEEPSETTINGS 0x0323 /* keep ioctl settings on reset */
#define TARGET_HDIO_SET_32BIT 0x0324 /* change io_32bit flags */
#define TARGET_HDIO_SET_NOWERR 0x0325 /* change ignore-write-error flag */
#define TARGET_HDIO_SET_DMA 0x0326 /* change use-dma flag */
#define TARGET_HDIO_SET_PIO_MODE 0x0327 /* reconfig interface to new speed */

View File

@ -0,0 +1,64 @@
STRUCT_SPECIAL(termios)
STRUCT(winsize,
TYPE_SHORT, TYPE_SHORT, TYPE_SHORT, TYPE_SHORT)
STRUCT(serial_multiport_struct,
TYPE_INT, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR,
TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_CHAR, TYPE_CHAR, TYPE_INT,
MK_ARRAY(TYPE_INT, 32))
STRUCT(serial_icounter_struct,
TYPE_INT, TYPE_INT, TYPE_INT, TYPE_INT, MK_ARRAY(TYPE_INT, 16))
STRUCT(sockaddr,
TYPE_SHORT, MK_ARRAY(TYPE_CHAR, 14))
STRUCT(rtentry,
TYPE_ULONG, MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr),
TYPE_SHORT, TYPE_SHORT, TYPE_ULONG, TYPE_PTRVOID, TYPE_SHORT, TYPE_PTRVOID,
TYPE_ULONG, TYPE_ULONG, TYPE_SHORT)
STRUCT(ifmap,
TYPE_ULONG, TYPE_ULONG, TYPE_SHORT, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR,
/* Spare 3 bytes */
TYPE_CHAR, TYPE_CHAR, TYPE_CHAR)
/* The *_ifreq_list arrays deal with the fact that struct ifreq has unions */
STRUCT(sockaddr_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_sockaddr))
STRUCT(short_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_SHORT)
STRUCT(int_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_INT)
STRUCT(ifmap_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), MK_STRUCT(STRUCT_ifmap))
STRUCT(char_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ),
MK_ARRAY(TYPE_CHAR, IFNAMSIZ))
STRUCT(ptr_ifreq,
MK_ARRAY(TYPE_CHAR, IFNAMSIZ), TYPE_PTRVOID)
STRUCT(ifconf,
TYPE_INT, TYPE_PTRVOID)
STRUCT(arpreq,
MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr),
MK_ARRAY(TYPE_CHAR, 16))
STRUCT(arpreq_old,
MK_STRUCT(STRUCT_sockaddr), MK_STRUCT(STRUCT_sockaddr), TYPE_INT, MK_STRUCT(STRUCT_sockaddr))
STRUCT(cdrom_read_audio,
TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_CHAR, TYPE_INT, TYPE_PTRVOID,
TYPE_NULL)
STRUCT(hd_geometry,
TYPE_CHAR, TYPE_CHAR, TYPE_SHORT, TYPE_ULONG)

760
syscall-i386.h Normal file
View File

@ -0,0 +1,760 @@
/* from linux/unistd.h */
#define TARGET_NR_exit 1
#define TARGET_NR_fork 2
#define TARGET_NR_read 3
#define TARGET_NR_write 4
#define TARGET_NR_open 5
#define TARGET_NR_close 6
#define TARGET_NR_waitpid 7
#define TARGET_NR_creat 8
#define TARGET_NR_link 9
#define TARGET_NR_unlink 10
#define TARGET_NR_execve 11
#define TARGET_NR_chdir 12
#define TARGET_NR_time 13
#define TARGET_NR_mknod 14
#define TARGET_NR_chmod 15
#define TARGET_NR_lchown 16
#define TARGET_NR_break 17
#define TARGET_NR_oldstat 18
#define TARGET_NR_lseek 19
#define TARGET_NR_getpid 20
#define TARGET_NR_mount 21
#define TARGET_NR_umount 22
#define TARGET_NR_setuid 23
#define TARGET_NR_getuid 24
#define TARGET_NR_stime 25
#define TARGET_NR_ptrace 26
#define TARGET_NR_alarm 27
#define TARGET_NR_oldfstat 28
#define TARGET_NR_pause 29
#define TARGET_NR_utime 30
#define TARGET_NR_stty 31
#define TARGET_NR_gtty 32
#define TARGET_NR_access 33
#define TARGET_NR_nice 34
#define TARGET_NR_ftime 35
#define TARGET_NR_sync 36
#define TARGET_NR_kill 37
#define TARGET_NR_rename 38
#define TARGET_NR_mkdir 39
#define TARGET_NR_rmdir 40
#define TARGET_NR_dup 41
#define TARGET_NR_pipe 42
#define TARGET_NR_times 43
#define TARGET_NR_prof 44
#define TARGET_NR_brk 45
#define TARGET_NR_setgid 46
#define TARGET_NR_getgid 47
#define TARGET_NR_signal 48
#define TARGET_NR_geteuid 49
#define TARGET_NR_getegid 50
#define TARGET_NR_acct 51
#define TARGET_NR_umount2 52
#define TARGET_NR_lock 53
#define TARGET_NR_ioctl 54
#define TARGET_NR_fcntl 55
#define TARGET_NR_mpx 56
#define TARGET_NR_setpgid 57
#define TARGET_NR_ulimit 58
#define TARGET_NR_oldolduname 59
#define TARGET_NR_umask 60
#define TARGET_NR_chroot 61
#define TARGET_NR_ustat 62
#define TARGET_NR_dup2 63
#define TARGET_NR_getppid 64
#define TARGET_NR_getpgrp 65
#define TARGET_NR_setsid 66
#define TARGET_NR_sigaction 67
#define TARGET_NR_sgetmask 68
#define TARGET_NR_ssetmask 69
#define TARGET_NR_setreuid 70
#define TARGET_NR_setregid 71
#define TARGET_NR_sigsuspend 72
#define TARGET_NR_sigpending 73
#define TARGET_NR_sethostname 74
#define TARGET_NR_setrlimit 75
#define TARGET_NR_getrlimit 76 /* Back compatible 2Gig limited rlimit */
#define TARGET_NR_getrusage 77
#define TARGET_NR_gettimeofday 78
#define TARGET_NR_settimeofday 79
#define TARGET_NR_getgroups 80
#define TARGET_NR_setgroups 81
#define TARGET_NR_select 82
#define TARGET_NR_symlink 83
#define TARGET_NR_oldlstat 84
#define TARGET_NR_readlink 85
#define TARGET_NR_uselib 86
#define TARGET_NR_swapon 87
#define TARGET_NR_reboot 88
#define TARGET_NR_readdir 89
#define TARGET_NR_mmap 90
#define TARGET_NR_munmap 91
#define TARGET_NR_truncate 92
#define TARGET_NR_ftruncate 93
#define TARGET_NR_fchmod 94
#define TARGET_NR_fchown 95
#define TARGET_NR_getpriority 96
#define TARGET_NR_setpriority 97
#define TARGET_NR_profil 98
#define TARGET_NR_statfs 99
#define TARGET_NR_fstatfs 100
#define TARGET_NR_ioperm 101
#define TARGET_NR_socketcall 102
#define TARGET_NR_syslog 103
#define TARGET_NR_setitimer 104
#define TARGET_NR_getitimer 105
#define TARGET_NR_stat 106
#define TARGET_NR_lstat 107
#define TARGET_NR_fstat 108
#define TARGET_NR_olduname 109
#define TARGET_NR_iopl 110
#define TARGET_NR_vhangup 111
#define TARGET_NR_idle 112
#define TARGET_NR_vm86old 113
#define TARGET_NR_wait4 114
#define TARGET_NR_swapoff 115
#define TARGET_NR_sysinfo 116
#define TARGET_NR_ipc 117
#define TARGET_NR_fsync 118
#define TARGET_NR_sigreturn 119
#define TARGET_NR_clone 120
#define TARGET_NR_setdomainname 121
#define TARGET_NR_uname 122
#define TARGET_NR_modify_ldt 123
#define TARGET_NR_adjtimex 124
#define TARGET_NR_mprotect 125
#define TARGET_NR_sigprocmask 126
#define TARGET_NR_create_module 127
#define TARGET_NR_init_module 128
#define TARGET_NR_delete_module 129
#define TARGET_NR_get_kernel_syms 130
#define TARGET_NR_quotactl 131
#define TARGET_NR_getpgid 132
#define TARGET_NR_fchdir 133
#define TARGET_NR_bdflush 134
#define TARGET_NR_sysfs 135
#define TARGET_NR_personality 136
#define TARGET_NR_afs_syscall 137 /* Syscall for Andrew File System */
#define TARGET_NR_setfsuid 138
#define TARGET_NR_setfsgid 139
#define TARGET_NR__llseek 140
#define TARGET_NR_getdents 141
#define TARGET_NR__newselect 142
#define TARGET_NR_flock 143
#define TARGET_NR_msync 144
#define TARGET_NR_readv 145
#define TARGET_NR_writev 146
#define TARGET_NR_getsid 147
#define TARGET_NR_fdatasync 148
#define TARGET_NR__sysctl 149
#define TARGET_NR_mlock 150
#define TARGET_NR_munlock 151
#define TARGET_NR_mlockall 152
#define TARGET_NR_munlockall 153
#define TARGET_NR_sched_setparam 154
#define TARGET_NR_sched_getparam 155
#define TARGET_NR_sched_setscheduler 156
#define TARGET_NR_sched_getscheduler 157
#define TARGET_NR_sched_yield 158
#define TARGET_NR_sched_get_priority_max 159
#define TARGET_NR_sched_get_priority_min 160
#define TARGET_NR_sched_rr_get_interval 161
#define TARGET_NR_nanosleep 162
#define TARGET_NR_mremap 163
#define TARGET_NR_setresuid 164
#define TARGET_NR_getresuid 165
#define TARGET_NR_vm86 166
#define TARGET_NR_query_module 167
#define TARGET_NR_poll 168
#define TARGET_NR_nfsservctl 169
#define TARGET_NR_setresgid 170
#define TARGET_NR_getresgid 171
#define TARGET_NR_prctl 172
#define TARGET_NR_rt_sigreturn 173
#define TARGET_NR_rt_sigaction 174
#define TARGET_NR_rt_sigprocmask 175
#define TARGET_NR_rt_sigpending 176
#define TARGET_NR_rt_sigtimedwait 177
#define TARGET_NR_rt_sigqueueinfo 178
#define TARGET_NR_rt_sigsuspend 179
#define TARGET_NR_pread 180
#define TARGET_NR_pwrite 181
#define TARGET_NR_chown 182
#define TARGET_NR_getcwd 183
#define TARGET_NR_capget 184
#define TARGET_NR_capset 185
#define TARGET_NR_sigaltstack 186
#define TARGET_NR_sendfile 187
#define TARGET_NR_getpmsg 188 /* some people actually want streams */
#define TARGET_NR_putpmsg 189 /* some people actually want streams */
#define TARGET_NR_vfork 190
#define TARGET_NR_ugetrlimit 191 /* SuS compliant getrlimit */
#define TARGET_NR_mmap2 192
#define TARGET_NR_truncate64 193
#define TARGET_NR_ftruncate64 194
#define TARGET_NR_stat64 195
#define TARGET_NR_lstat64 196
#define TARGET_NR_fstat64 197
#define TARGET_NR_lchown32 198
#define TARGET_NR_getuid32 199
#define TARGET_NR_getgid32 200
#define TARGET_NR_geteuid32 201
#define TARGET_NR_getegid32 202
#define TARGET_NR_setreuid32 203
#define TARGET_NR_setregid32 204
#define TARGET_NR_getgroups32 205
#define TARGET_NR_setgroups32 206
#define TARGET_NR_fchown32 207
#define TARGET_NR_setresuid32 208
#define TARGET_NR_getresuid32 209
#define TARGET_NR_setresgid32 210
#define TARGET_NR_getresgid32 211
#define TARGET_NR_chown32 212
#define TARGET_NR_setuid32 213
#define TARGET_NR_setgid32 214
#define TARGET_NR_setfsuid32 215
#define TARGET_NR_setfsgid32 216
#define TARGET_NR_pivot_root 217
#define TARGET_NR_mincore 218
#define TARGET_NR_madvise 219
#define TARGET_NR_madvise1 219 /* delete when C lib stub is removed */
#define TARGET_NR_getdents64 220
#define TARGET_NR_fcntl64 221
#define TARGET_NR_security 223 /* syscall for security modules */
#define TARGET_NR_gettid 224
#define TARGET_NR_readahead 225
#define TARGET_NR_setxattr 226
#define TARGET_NR_lsetxattr 227
#define TARGET_NR_fsetxattr 228
#define TARGET_NR_getxattr 229
#define TARGET_NR_lgetxattr 230
#define TARGET_NR_fgetxattr 231
#define TARGET_NR_listxattr 232
#define TARGET_NR_llistxattr 233
#define TARGET_NR_flistxattr 234
#define TARGET_NR_removexattr 235
#define TARGET_NR_lremovexattr 236
#define TARGET_NR_fremovexattr 237
#define TARGET_SIG_BLOCK 0 /* for blocking signals */
#define TARGET_SIG_UNBLOCK 1 /* for unblocking signals */
#define TARGET_SIG_SETMASK 2 /* for setting the signal mask */
struct target_stat {
unsigned short st_dev;
unsigned short __pad1;
unsigned long st_ino;
unsigned short st_mode;
unsigned short st_nlink;
unsigned short st_uid;
unsigned short st_gid;
unsigned short st_rdev;
unsigned short __pad2;
unsigned long st_size;
unsigned long st_blksize;
unsigned long st_blocks;
unsigned long st_atime;
unsigned long __unused1;
unsigned long st_mtime;
unsigned long __unused2;
unsigned long st_ctime;
unsigned long __unused3;
unsigned long __unused4;
unsigned long __unused5;
};
/* This matches struct stat64 in glibc2.1, hence the absolutely
* insane amounts of padding around dev_t's.
*/
struct target_stat64 {
unsigned short st_dev;
unsigned char __pad0[10];
#define STAT64_HAS_BROKEN_ST_INO 1
unsigned long __st_ino;
unsigned int st_mode;
unsigned int st_nlink;
unsigned long st_uid;
unsigned long st_gid;
unsigned short st_rdev;
unsigned char __pad3[10];
long long st_size;
unsigned long st_blksize;
unsigned long st_blocks; /* Number 512-byte blocks allocated. */
unsigned long __pad4; /* future possible st_blocks high bits */
unsigned long st_atime;
unsigned long __pad5;
unsigned long st_mtime;
unsigned long __pad6;
unsigned long st_ctime;
unsigned long __pad7; /* will be high 32 bits of ctime someday */
unsigned long long st_ino;
};
typedef unsigned long old_sigset_t; /* at least 32 bits */
struct target_old_sigaction {
target_ulong _sa_handler;
target_ulong sa_mask;
target_ulong sa_flags;
void (*sa_restorer)(void);
};
struct target_sigaction {
target_ulong _sa_handler;
target_sigset_t sa_mask;
target_ulong sa_flags;
target_ulong sa_restorer;
};
typedef union target_sigval {
int sival_int;
void *sival_ptr;
} target_sigval_t;
#define TARGET_SI_MAX_SIZE 128
#define TARGET_SI_PAD_SIZE ((TARGET_SI_MAX_SIZE/sizeof(int)) - 3)
typedef struct target_siginfo {
int si_signo;
int si_errno;
int si_code;
union {
int _pad[TARGET_SI_PAD_SIZE];
/* kill() */
struct {
pid_t _pid; /* sender's pid */
uid_t _uid; /* sender's uid */
} _kill;
/* POSIX.1b timers */
struct {
unsigned int _timer1;
unsigned int _timer2;
} _timer;
/* POSIX.1b signals */
struct {
pid_t _pid; /* sender's pid */
uid_t _uid; /* sender's uid */
sigval_t _sigval;
} _rt;
/* SIGCHLD */
struct {
pid_t _pid; /* which child */
uid_t _uid; /* sender's uid */
int _status; /* exit code */
clock_t _utime;
clock_t _stime;
} _sigchld;
/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
struct {
void *_addr; /* faulting insn/memory ref. */
} _sigfault;
/* SIGPOLL */
struct {
int _band; /* POLL_IN, POLL_OUT, POLL_MSG */
int _fd;
} _sigpoll;
} _sifields;
} target_siginfo_t;
/* ioctls */
/*
* The following is for compatibility across the various Linux
* platforms. The i386 ioctl numbering scheme doesn't really enforce
* a type field. De facto, however, the top 8 bits of the lower 16
* bits are indeed used as a type field, so we might just as well make
* this explicit here. Please be sure to use the decoding macros
* below from now on.
*/
#define TARGET_IOC_NRBITS 8
#define TARGET_IOC_TYPEBITS 8
#define TARGET_IOC_SIZEBITS 14
#define TARGET_IOC_DIRBITS 2
#define TARGET_IOC_NRMASK ((1 << TARGET_IOC_NRBITS)-1)
#define TARGET_IOC_TYPEMASK ((1 << TARGET_IOC_TYPEBITS)-1)
#define TARGET_IOC_SIZEMASK ((1 << TARGET_IOC_SIZEBITS)-1)
#define TARGET_IOC_DIRMASK ((1 << TARGET_IOC_DIRBITS)-1)
#define TARGET_IOC_NRSHIFT 0
#define TARGET_IOC_TYPESHIFT (TARGET_IOC_NRSHIFT+TARGET_IOC_NRBITS)
#define TARGET_IOC_SIZESHIFT (TARGET_IOC_TYPESHIFT+TARGET_IOC_TYPEBITS)
#define TARGET_IOC_DIRSHIFT (TARGET_IOC_SIZESHIFT+TARGET_IOC_SIZEBITS)
/*
* Direction bits.
*/
#define TARGET_IOC_NONE 0U
#define TARGET_IOC_WRITE 1U
#define TARGET_IOC_READ 2U
#define TARGET_IOC(dir,type,nr,size) \
(((dir) << TARGET_IOC_DIRSHIFT) | \
((type) << TARGET_IOC_TYPESHIFT) | \
((nr) << TARGET_IOC_NRSHIFT) | \
((size) << TARGET_IOC_SIZESHIFT))
/* used to create numbers */
#define TARGET_IO(type,nr) TARGET_IOC(TARGET_IOC_NONE,(type),(nr),0)
#define TARGET_IOR(type,nr,size) TARGET_IOC(TARGET_IOC_READ,(type),(nr),sizeof(size))
#define TARGET_IOW(type,nr,size) TARGET_IOC(TARGET_IOC_WRITE,(type),(nr),sizeof(size))
#define TARGET_IOWR(type,nr,size) TARGET_IOC(TARGET_IOC_READ|TARGET_IOC_WRITE,(type),(nr),sizeof(size))
/* 0x54 is just a magic number to make these relatively unique ('T') */
#define TARGET_TCGETS 0x5401
#define TARGET_TCSETS 0x5402
#define TARGET_TCSETSW 0x5403
#define TARGET_TCSETSF 0x5404
#define TARGET_TCGETA 0x5405
#define TARGET_TCSETA 0x5406
#define TARGET_TCSETAW 0x5407
#define TARGET_TCSETAF 0x5408
#define TARGET_TCSBRK 0x5409
#define TARGET_TCXONC 0x540A
#define TARGET_TCFLSH 0x540B
#define TARGET_TIOCEXCL 0x540C
#define TARGET_TIOCNXCL 0x540D
#define TARGET_TIOCSCTTY 0x540E
#define TARGET_TIOCGPGRP 0x540F
#define TARGET_TIOCSPGRP 0x5410
#define TARGET_TIOCOUTQ 0x5411
#define TARGET_TIOCSTI 0x5412
#define TARGET_TIOCGWINSZ 0x5413
#define TARGET_TIOCSWINSZ 0x5414
#define TARGET_TIOCMGET 0x5415
#define TARGET_TIOCMBIS 0x5416
#define TARGET_TIOCMBIC 0x5417
#define TARGET_TIOCMSET 0x5418
#define TARGET_TIOCGSOFTCAR 0x5419
#define TARGET_TIOCSSOFTCAR 0x541A
#define TARGET_FIONREAD 0x541B
#define TARGET_TIOCINQ FIONREAD
#define TARGET_TIOCLINUX 0x541C
#define TARGET_TIOCCONS 0x541D
#define TARGET_TIOCGSERIAL 0x541E
#define TARGET_TIOCSSERIAL 0x541F
#define TARGET_TIOCPKT 0x5420
#define TARGET_FIONBIO 0x5421
#define TARGET_TIOCNOTTY 0x5422
#define TARGET_TIOCSETD 0x5423
#define TARGET_TIOCGETD 0x5424
#define TARGET_TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
#define TARGET_TIOCTTYGSTRUCT 0x5426 /* For debugging only */
#define TARGET_TIOCSBRK 0x5427 /* BSD compatibility */
#define TARGET_TIOCCBRK 0x5428 /* BSD compatibility */
#define TARGET_TIOCGSID 0x5429 /* Return the session ID of FD */
#define TARGET_TIOCGPTN _IOR('T',0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
#define TARGET_TIOCSPTLCK _IOW('T',0x31, int) /* Lock/unlock Pty */
#define TARGET_FIONCLEX 0x5450 /* these numbers need to be adjusted. */
#define TARGET_FIOCLEX 0x5451
#define TARGET_FIOASYNC 0x5452
#define TARGET_TIOCSERCONFIG 0x5453
#define TARGET_TIOCSERGWILD 0x5454
#define TARGET_TIOCSERSWILD 0x5455
#define TARGET_TIOCGLCKTRMIOS 0x5456
#define TARGET_TIOCSLCKTRMIOS 0x5457
#define TARGET_TIOCSERGSTRUCT 0x5458 /* For debugging only */
#define TARGET_TIOCSERGETLSR 0x5459 /* Get line status register */
#define TARGET_TIOCSERGETMULTI 0x545A /* Get multiport config */
#define TARGET_TIOCSERSETMULTI 0x545B /* Set multiport config */
#define TARGET_TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
#define TARGET_TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
#define TARGET_TIOCGHAYESESP 0x545E /* Get Hayes ESP configuration */
#define TARGET_TIOCSHAYESESP 0x545F /* Set Hayes ESP configuration */
/* Used for packet mode */
#define TARGET_TIOCPKT_DATA 0
#define TARGET_TIOCPKT_FLUSHREAD 1
#define TARGET_TIOCPKT_FLUSHWRITE 2
#define TARGET_TIOCPKT_STOP 4
#define TARGET_TIOCPKT_START 8
#define TARGET_TIOCPKT_NOSTOP 16
#define TARGET_TIOCPKT_DOSTOP 32
#define TARGET_TIOCSER_TEMT 0x01 /* Transmitter physically empty */
/* from asm/termbits.h */
#define TARGET_NCCS 19
struct target_termios {
unsigned int c_iflag; /* input mode flags */
unsigned int c_oflag; /* output mode flags */
unsigned int c_cflag; /* control mode flags */
unsigned int c_lflag; /* local mode flags */
unsigned char c_line; /* line discipline */
unsigned char c_cc[TARGET_NCCS]; /* control characters */
};
/* c_iflag bits */
#define TARGET_IGNBRK 0000001
#define TARGET_BRKINT 0000002
#define TARGET_IGNPAR 0000004
#define TARGET_PARMRK 0000010
#define TARGET_INPCK 0000020
#define TARGET_ISTRIP 0000040
#define TARGET_INLCR 0000100
#define TARGET_IGNCR 0000200
#define TARGET_ICRNL 0000400
#define TARGET_IUCLC 0001000
#define TARGET_IXON 0002000
#define TARGET_IXANY 0004000
#define TARGET_IXOFF 0010000
#define TARGET_IMAXBEL 0020000
/* c_oflag bits */
#define TARGET_OPOST 0000001
#define TARGET_OLCUC 0000002
#define TARGET_ONLCR 0000004
#define TARGET_OCRNL 0000010
#define TARGET_ONOCR 0000020
#define TARGET_ONLRET 0000040
#define TARGET_OFILL 0000100
#define TARGET_OFDEL 0000200
#define TARGET_NLDLY 0000400
#define TARGET_NL0 0000000
#define TARGET_NL1 0000400
#define TARGET_CRDLY 0003000
#define TARGET_CR0 0000000
#define TARGET_CR1 0001000
#define TARGET_CR2 0002000
#define TARGET_CR3 0003000
#define TARGET_TABDLY 0014000
#define TARGET_TAB0 0000000
#define TARGET_TAB1 0004000
#define TARGET_TAB2 0010000
#define TARGET_TAB3 0014000
#define TARGET_XTABS 0014000
#define TARGET_BSDLY 0020000
#define TARGET_BS0 0000000
#define TARGET_BS1 0020000
#define TARGET_VTDLY 0040000
#define TARGET_VT0 0000000
#define TARGET_VT1 0040000
#define TARGET_FFDLY 0100000
#define TARGET_FF0 0000000
#define TARGET_FF1 0100000
/* c_cflag bit meaning */
#define TARGET_CBAUD 0010017
#define TARGET_B0 0000000 /* hang up */
#define TARGET_B50 0000001
#define TARGET_B75 0000002
#define TARGET_B110 0000003
#define TARGET_B134 0000004
#define TARGET_B150 0000005
#define TARGET_B200 0000006
#define TARGET_B300 0000007
#define TARGET_B600 0000010
#define TARGET_B1200 0000011
#define TARGET_B1800 0000012
#define TARGET_B2400 0000013
#define TARGET_B4800 0000014
#define TARGET_B9600 0000015
#define TARGET_B19200 0000016
#define TARGET_B38400 0000017
#define TARGET_EXTA B19200
#define TARGET_EXTB B38400
#define TARGET_CSIZE 0000060
#define TARGET_CS5 0000000
#define TARGET_CS6 0000020
#define TARGET_CS7 0000040
#define TARGET_CS8 0000060
#define TARGET_CSTOPB 0000100
#define TARGET_CREAD 0000200
#define TARGET_PARENB 0000400
#define TARGET_PARODD 0001000
#define TARGET_HUPCL 0002000
#define TARGET_CLOCAL 0004000
#define TARGET_CBAUDEX 0010000
#define TARGET_B57600 0010001
#define TARGET_B115200 0010002
#define TARGET_B230400 0010003
#define TARGET_B460800 0010004
#define TARGET_CIBAUD 002003600000 /* input baud rate (not used) */
#define TARGET_CRTSCTS 020000000000 /* flow control */
/* c_lflag bits */
#define TARGET_ISIG 0000001
#define TARGET_ICANON 0000002
#define TARGET_XCASE 0000004
#define TARGET_ECHO 0000010
#define TARGET_ECHOE 0000020
#define TARGET_ECHOK 0000040
#define TARGET_ECHONL 0000100
#define TARGET_NOFLSH 0000200
#define TARGET_TOSTOP 0000400
#define TARGET_ECHOCTL 0001000
#define TARGET_ECHOPRT 0002000
#define TARGET_ECHOKE 0004000
#define TARGET_FLUSHO 0010000
#define TARGET_PENDIN 0040000
#define TARGET_IEXTEN 0100000
/* c_cc character offsets */
#define TARGET_VINTR 0
#define TARGET_VQUIT 1
#define TARGET_VERASE 2
#define TARGET_VKILL 3
#define TARGET_VEOF 4
#define TARGET_VTIME 5
#define TARGET_VMIN 6
#define TARGET_VSWTC 7
#define TARGET_VSTART 8
#define TARGET_VSTOP 9
#define TARGET_VSUSP 10
#define TARGET_VEOL 11
#define TARGET_VREPRINT 12
#define TARGET_VDISCARD 13
#define TARGET_VWERASE 14
#define TARGET_VLNEXT 15
#define TARGET_VEOL2 16
/* soundcard defines (XXX: move them to generic file syscall_defs.h) */
#define TARGET_SNDCTL_COPR_HALT 0xc0144307
#define TARGET_SNDCTL_COPR_LOAD 0xcfb04301
#define TARGET_SNDCTL_COPR_RCODE 0xc0144303
#define TARGET_SNDCTL_COPR_RCVMSG 0x8fa44309
#define TARGET_SNDCTL_COPR_RDATA 0xc0144302
#define TARGET_SNDCTL_COPR_RESET 0x00004300
#define TARGET_SNDCTL_COPR_RUN 0xc0144306
#define TARGET_SNDCTL_COPR_SENDMSG 0xcfa44308
#define TARGET_SNDCTL_COPR_WCODE 0x40144305
#define TARGET_SNDCTL_COPR_WDATA 0x40144304
#define TARGET_SNDCTL_DSP_CHANNELS 0xc0045006
#define TARGET_SNDCTL_DSP_GETBLKSIZE 0xc0045004
#define TARGET_SNDCTL_DSP_GETCAPS 0x8004500f
#define TARGET_SNDCTL_DSP_GETFMTS 0x8004500b
#define TARGET_SNDCTL_DSP_GETIPTR 0x800c5011
#define TARGET_SNDCTL_DSP_GETISPACE 0x8010500d
#define TARGET_SNDCTL_DSP_GETOPTR 0x800c5012
#define TARGET_SNDCTL_DSP_GETOSPACE 0x8010500c
#define TARGET_SNDCTL_DSP_GETTRIGGER 0x80045010
#define TARGET_SNDCTL_DSP_MAPINBUF 0x80085013
#define TARGET_SNDCTL_DSP_MAPOUTBUF 0x80085014
#define TARGET_SNDCTL_DSP_NONBLOCK 0x0000500e
#define TARGET_SNDCTL_DSP_POST 0x00005008
#define TARGET_SNDCTL_DSP_RESET 0x00005000
#define TARGET_SNDCTL_DSP_SAMPLESIZE 0xc0045005
#define TARGET_SNDCTL_DSP_SETDUPLEX 0x00005016
#define TARGET_SNDCTL_DSP_SETFMT 0xc0045005
#define TARGET_SNDCTL_DSP_SETFRAGMENT 0xc004500a
#define TARGET_SNDCTL_DSP_SETSYNCRO 0x00005015
#define TARGET_SNDCTL_DSP_SETTRIGGER 0x40045010
#define TARGET_SNDCTL_DSP_SPEED 0xc0045002
#define TARGET_SNDCTL_DSP_STEREO 0xc0045003
#define TARGET_SNDCTL_DSP_SUBDIVIDE 0xc0045009
#define TARGET_SNDCTL_DSP_SYNC 0x00005001
#define TARGET_SNDCTL_FM_4OP_ENABLE 0x4004510f
#define TARGET_SNDCTL_FM_LOAD_INSTR 0x40285107
#define TARGET_SNDCTL_MIDI_INFO 0xc074510c
#define TARGET_SNDCTL_MIDI_MPUCMD 0xc0216d02
#define TARGET_SNDCTL_MIDI_MPUMODE 0xc0046d01
#define TARGET_SNDCTL_MIDI_PRETIME 0xc0046d00
#define TARGET_SNDCTL_PMGR_ACCESS 0xcfb85110
#define TARGET_SNDCTL_PMGR_IFACE 0xcfb85001
#define TARGET_SNDCTL_SEQ_CTRLRATE 0xc0045103
#define TARGET_SNDCTL_SEQ_GETINCOUNT 0x80045105
#define TARGET_SNDCTL_SEQ_GETOUTCOUNT 0x80045104
#define TARGET_SNDCTL_SEQ_NRMIDIS 0x8004510b
#define TARGET_SNDCTL_SEQ_NRSYNTHS 0x8004510a
#define TARGET_SNDCTL_SEQ_OUTOFBAND 0x40085112
#define TARGET_SNDCTL_SEQ_PANIC 0x00005111
#define TARGET_SNDCTL_SEQ_PERCMODE 0x40045106
#define TARGET_SNDCTL_SEQ_RESET 0x00005100
#define TARGET_SNDCTL_SEQ_RESETSAMPLES 0x40045109
#define TARGET_SNDCTL_SEQ_SYNC 0x00005101
#define TARGET_SNDCTL_SEQ_TESTMIDI 0x40045108
#define TARGET_SNDCTL_SEQ_THRESHOLD 0x4004510d
#define TARGET_SNDCTL_SEQ_TRESHOLD 0x4004510d
#define TARGET_SNDCTL_SYNTH_INFO 0xc08c5102
#define TARGET_SNDCTL_SYNTH_MEMAVL 0xc004510e
#define TARGET_SNDCTL_TMR_CONTINUE 0x00005404
#define TARGET_SNDCTL_TMR_METRONOME 0x40045407
#define TARGET_SNDCTL_TMR_SELECT 0x40045408
#define TARGET_SNDCTL_TMR_SOURCE 0xc0045406
#define TARGET_SNDCTL_TMR_START 0x00005402
#define TARGET_SNDCTL_TMR_STOP 0x00005403
#define TARGET_SNDCTL_TMR_TEMPO 0xc0045405
#define TARGET_SNDCTL_TMR_TIMEBASE 0xc0045401
#define TARGET_SOUND_PCM_WRITE_FILTER 0xc0045007
#define TARGET_SOUND_PCM_READ_RATE 0x80045002
#define TARGET_SOUND_PCM_READ_CHANNELS 0x80045006
#define TARGET_SOUND_PCM_READ_BITS 0x80045005
#define TARGET_SOUND_PCM_READ_FILTER 0x80045007
#define TARGET_SOUND_MIXER_INFO 0x80304d65
#define TARGET_SOUND_MIXER_ACCESS 0xc0804d66
#define TARGET_SOUND_MIXER_PRIVATE1 0xc0044d6f
#define TARGET_SOUND_MIXER_PRIVATE2 0xc0044d70
#define TARGET_SOUND_MIXER_PRIVATE3 0xc0044d71
#define TARGET_SOUND_MIXER_PRIVATE4 0xc0044d72
#define TARGET_SOUND_MIXER_PRIVATE5 0xc0044d73
#define TARGET_SOUND_MIXER_READ_VOLUME 0x80044d00
#define TARGET_SOUND_MIXER_READ_BASS 0x80044d01
#define TARGET_SOUND_MIXER_READ_TREBLE 0x80044d02
#define TARGET_SOUND_MIXER_READ_SYNTH 0x80044d03
#define TARGET_SOUND_MIXER_READ_PCM 0x80044d04
#define TARGET_SOUND_MIXER_READ_SPEAKER 0x80044d05
#define TARGET_SOUND_MIXER_READ_LINE 0x80044d06
#define TARGET_SOUND_MIXER_READ_MIC 0x80044d07
#define TARGET_SOUND_MIXER_READ_CD 0x80044d08
#define TARGET_SOUND_MIXER_READ_IMIX 0x80044d09
#define TARGET_SOUND_MIXER_READ_ALTPCM 0x80044d0a
#define TARGET_SOUND_MIXER_READ_RECLEV 0x80044d0b
#define TARGET_SOUND_MIXER_READ_IGAIN 0x80044d0c
#define TARGET_SOUND_MIXER_READ_OGAIN 0x80044d0d
#define TARGET_SOUND_MIXER_READ_LINE1 0x80044d0e
#define TARGET_SOUND_MIXER_READ_LINE2 0x80044d0f
#define TARGET_SOUND_MIXER_READ_LINE3 0x80044d10
#define TARGET_SOUND_MIXER_READ_MUTE 0x80044d1f
#define TARGET_SOUND_MIXER_READ_ENHANCE 0x80044d1f
#define TARGET_SOUND_MIXER_READ_LOUD 0x80044d1f
#define TARGET_SOUND_MIXER_READ_RECSRC 0x80044dff
#define TARGET_SOUND_MIXER_READ_DEVMASK 0x80044dfe
#define TARGET_SOUND_MIXER_READ_RECMASK 0x80044dfd
#define TARGET_SOUND_MIXER_READ_STEREODEVS 0x80044dfb
#define TARGET_SOUND_MIXER_READ_CAPS 0x80044dfc
#define TARGET_SOUND_MIXER_WRITE_VOLUME 0xc0044d00
#define TARGET_SOUND_MIXER_WRITE_BASS 0xc0044d01
#define TARGET_SOUND_MIXER_WRITE_TREBLE 0xc0044d02
#define TARGET_SOUND_MIXER_WRITE_SYNTH 0xc0044d03
#define TARGET_SOUND_MIXER_WRITE_PCM 0xc0044d04
#define TARGET_SOUND_MIXER_WRITE_SPEAKER 0xc0044d05
#define TARGET_SOUND_MIXER_WRITE_LINE 0xc0044d06
#define TARGET_SOUND_MIXER_WRITE_MIC 0xc0044d07
#define TARGET_SOUND_MIXER_WRITE_CD 0xc0044d08
#define TARGET_SOUND_MIXER_WRITE_IMIX 0xc0044d09
#define TARGET_SOUND_MIXER_WRITE_ALTPCM 0xc0044d0a
#define TARGET_SOUND_MIXER_WRITE_RECLEV 0xc0044d0b
#define TARGET_SOUND_MIXER_WRITE_IGAIN 0xc0044d0c
#define TARGET_SOUND_MIXER_WRITE_OGAIN 0xc0044d0d
#define TARGET_SOUND_MIXER_WRITE_LINE1 0xc0044d0e
#define TARGET_SOUND_MIXER_WRITE_LINE2 0xc0044d0f
#define TARGET_SOUND_MIXER_WRITE_LINE3 0xc0044d10
#define TARGET_SOUND_MIXER_WRITE_MUTE 0xc0044d1f
#define TARGET_SOUND_MIXER_WRITE_ENHANCE 0xc0044d1f
#define TARGET_SOUND_MIXER_WRITE_LOUD 0xc0044d1f
#define TARGET_SOUND_MIXER_WRITE_RECSRC 0xc0044dff

315
thunk.c Normal file
View File

@ -0,0 +1,315 @@
/*
* Generic thunking code to convert data between host and target CPU
*
* Copyright (c) 2003 Fabrice Bellard
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <stdlib.h>
#include <stdio.h>
#include <stdarg.h>
#include "gemu.h"
#include "thunk.h"
//#define DEBUG
#define MAX_STRUCTS 128
/* XXX: make it dynamic */
static StructEntry struct_entries[MAX_STRUCTS];
static inline int thunk_type_size(const argtype *type_ptr, int is_host)
{
int type, size;
const StructEntry *se;
type = *type_ptr;
switch(type) {
case TYPE_CHAR:
return 1;
case TYPE_SHORT:
return 2;
case TYPE_INT:
return 4;
case TYPE_LONGLONG:
case TYPE_ULONGLONG:
return 8;
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
case TYPE_PTR:
if (is_host) {
return HOST_LONG_SIZE;
} else {
return TARGET_LONG_SIZE;
}
break;
case TYPE_ARRAY:
size = type_ptr[1];
return size * thunk_type_size(type_ptr + 2, is_host);
case TYPE_STRUCT:
se = struct_entries + type_ptr[1];
return se->size[is_host];
default:
return -1;
}
}
static inline int thunk_type_align(const argtype *type_ptr, int is_host)
{
int type;
const StructEntry *se;
type = *type_ptr;
switch(type) {
case TYPE_CHAR:
return 1;
case TYPE_SHORT:
return 2;
case TYPE_INT:
return 4;
case TYPE_LONGLONG:
case TYPE_ULONGLONG:
return 8;
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
case TYPE_PTR:
if (is_host) {
return HOST_LONG_SIZE;
} else {
return TARGET_LONG_SIZE;
}
break;
case TYPE_ARRAY:
return thunk_type_align(type_ptr + 2, is_host);
case TYPE_STRUCT:
se = struct_entries + type_ptr[1];
return se->align[is_host];
default:
return -1;
}
}
static inline const argtype *thunk_type_next(const argtype *type_ptr)
{
int type;
type = *type_ptr++;
switch(type) {
case TYPE_CHAR:
case TYPE_SHORT:
case TYPE_INT:
case TYPE_LONGLONG:
case TYPE_ULONGLONG:
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
return type_ptr;
case TYPE_PTR:
return thunk_type_next(type_ptr);
case TYPE_ARRAY:
return thunk_type_next(type_ptr + 1);
case TYPE_STRUCT:
return type_ptr + 1;
default:
return NULL;
}
}
void thunk_register_struct(int id, const char *name, const argtype *types)
{
const argtype *type_ptr;
StructEntry *se;
int nb_fields, offset, max_align, align, size, i, j;
se = struct_entries + id;
/* first we count the number of fields */
type_ptr = types;
nb_fields = 0;
while (*type_ptr != TYPE_NULL) {
type_ptr = thunk_type_next(type_ptr);
nb_fields++;
}
se->field_types = types;
se->nb_fields = nb_fields;
se->name = name;
#ifdef DEBUG
printf("struct %s: id=%d nb_fields=%d\n",
se->name, id, se->nb_fields);
#endif
/* now we can alloc the data */
for(i = 0;i < 2; i++) {
offset = 0;
max_align = 1;
se->field_offsets[i] = malloc(nb_fields * sizeof(int));
type_ptr = se->field_types;
for(j = 0;j < nb_fields; j++) {
size = thunk_type_size(type_ptr, i);
align = thunk_type_align(type_ptr, i);
offset = (offset + align - 1) & ~(align - 1);
se->field_offsets[i][j] = offset;
offset += size;
if (align > max_align)
max_align = align;
}
offset = (offset + max_align - 1) & ~(max_align - 1);
se->size[i] = offset;
se->align[i] = max_align;
#ifdef DEBUG
printf("%s: size=%d align=%d\n",
i == THUNK_HOST ? "host" : "target", offset, max_align);
#endif
}
}
void thunk_register_struct_direct(int id, const char *name, StructEntry *se1)
{
StructEntry *se;
se = struct_entries + id;
*se = *se1;
se->name = name;
}
/* now we can define the main conversion functions */
const argtype *thunk_convert(void *dst, const void *src,
const argtype *type_ptr, int to_host)
{
int type;
type = *type_ptr++;
switch(type) {
case TYPE_CHAR:
*(uint8_t *)dst = *(uint8_t *)src;
break;
case TYPE_SHORT:
*(uint16_t *)dst = tswap16(*(uint16_t *)src);
break;
case TYPE_INT:
*(uint32_t *)dst = tswap32(*(uint32_t *)src);
break;
case TYPE_LONGLONG:
case TYPE_ULONGLONG:
*(uint64_t *)dst = tswap64(*(uint64_t *)src);
break;
#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
*(uint32_t *)dst = tswap32(*(uint32_t *)src);
break;
#elif HOST_LONG_BITS == 64 && TARGET_LONG_BITS == 32
case TYPE_LONG:
case TYPE_ULONG:
case TYPE_PTRVOID:
if (target_to_host) {
*(uint64_t *)dst = tswap32(*(uint32_t *)src);
} else {
*(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
}
break;
#else
#error unsupported conversion
#endif
case TYPE_ARRAY:
{
int array_length, i, dst_size, src_size;
const uint8_t *s;
uint8_t *d;
array_length = *type_ptr++;
dst_size = thunk_type_size(type_ptr, to_host);
src_size = thunk_type_size(type_ptr, 1 - to_host);
d = dst;
s = src;
for(i = 0;i < array_length; i++) {
thunk_convert(d, s, type_ptr, to_host);
d += dst_size;
s += src_size;
}
type_ptr = thunk_type_next(type_ptr);
}
break;
case TYPE_STRUCT:
{
int i;
const StructEntry *se;
const uint8_t *s;
uint8_t *d;
const argtype *field_types;
const int *dst_offsets, *src_offsets;
se = struct_entries + *type_ptr++;
if (se->convert[0] != NULL) {
/* specific conversion is needed */
(*se->convert[to_host])(dst, src);
} else {
/* standard struct conversion */
field_types = se->field_types;
dst_offsets = se->field_offsets[to_host];
src_offsets = se->field_offsets[1 - to_host];
d = dst;
s = src;
for(i = 0;i < se->nb_fields; i++) {
field_types = thunk_convert(d + dst_offsets[i],
s + src_offsets[i],
field_types, to_host);
}
}
}
break;
default:
fprintf(stderr, "Invalid type 0x%x\n", type);
break;
}
return type_ptr;
}
/* from em86 */
/* Utility function: Table-driven functions to translate bitmasks
* between X86 and Alpha formats...
*/
unsigned int target_to_host_bitmask(unsigned int x86_mask,
bitmask_transtbl * trans_tbl)
{
bitmask_transtbl * btp;
unsigned int alpha_mask = 0;
for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
if((x86_mask & btp->x86_mask) == btp->x86_bits) {
alpha_mask |= btp->alpha_bits;
}
}
return(alpha_mask);
}
unsigned int host_to_target_bitmask(unsigned int alpha_mask,
bitmask_transtbl * trans_tbl)
{
bitmask_transtbl * btp;
unsigned int x86_mask = 0;
for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
x86_mask |= btp->x86_mask;
}
}
return(x86_mask);
}

195
thunk.h Normal file
View File

@ -0,0 +1,195 @@
#ifndef THUNK_H
#define THUNK_H
#include <inttypes.h>
#include <byteswap.h>
#undef WORDS_BIGENDIAN
#if __BYTE_ORDER == __BIG_ENDIAN
#define WORDS_BIGENDIAN
#endif
#ifdef WORD_BIGENDIAN
#define BSWAP_NEEDED
#endif
/* XXX: auto autoconf */
#define TARGET_I386
#define TARGET_LONG_BITS 32
#if defined(__alpha__)
#define HOST_LONG_BITS 64
#else
#define HOST_LONG_BITS 32
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
#define HOST_LONG_SIZE (TARGET_LONG_BITS / 8)
static inline uint16_t bswap16(uint16_t x)
{
return bswap_16(x);
}
static inline uint32_t bswap32(uint32_t x)
{
return bswap_32(x);
}
static inline uint64_t bswap64(uint64_t x)
{
return bswap_64(x);
}
static void inline bswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static void inline bswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static void inline bswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#ifdef BSWAP_NEEDED
static inline uint16_t tswap16(uint16_t s)
{
return bswap16(s);
}
static inline uint32_t tswap32(uint32_t s)
{
return bswap32(s);
}
static inline uint64_t tswap64(uint64_t s)
{
return bswap64(s);
}
static void inline tswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
static void inline tswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
static void inline tswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
#else
static inline uint16_t tswap16(uint16_t s)
{
return s;
}
static inline uint32_t tswap32(uint32_t s)
{
return s;
}
static inline uint64_t tswap64(uint64_t s)
{
return s;
}
static void inline tswap16s(uint16_t *s)
{
}
static void inline tswap32s(uint32_t *s)
{
}
static void inline tswap64s(uint64_t *s)
{
}
#endif
#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
#else
#define tswapl(s) tswap64(s)
#define tswapls(s) tswap64s((uint64_t *)(s))
#endif
#if TARGET_LONG_SIZE == 4
typedef int32_t target_long;
typedef uint32_t target_ulong;
#elif TARGET_LONG_SIZE == 8
typedef int64_t target_long;
typedef uint64_t target_ulong;
#else
#error TARGET_LONG_SIZE undefined
#endif
/* types enums definitions */
typedef enum argtype {
TYPE_NULL,
TYPE_CHAR,
TYPE_SHORT,
TYPE_INT,
TYPE_LONG,
TYPE_ULONG,
TYPE_PTRVOID, /* pointer on unknown data */
TYPE_LONGLONG,
TYPE_ULONGLONG,
TYPE_PTR,
TYPE_ARRAY,
TYPE_STRUCT,
} argtype;
#define MK_PTR(type) TYPE_PTR, type
#define MK_ARRAY(type, size) TYPE_ARRAY, size, type
#define MK_STRUCT(id) TYPE_STRUCT, id
#define THUNK_TARGET 0
#define THUNK_HOST 1
typedef struct {
/* standard struct handling */
const argtype *field_types;
int nb_fields;
int *field_offsets[2];
/* special handling */
void (*convert[2])(void *dst, const void *src);
int size[2];
int align[2];
const char *name;
} StructEntry;
/* Translation table for bitmasks... */
typedef struct bitmask_transtbl {
unsigned int x86_mask;
unsigned int x86_bits;
unsigned int alpha_mask;
unsigned int alpha_bits;
} bitmask_transtbl;
void thunk_register_struct(int id, const char *name, const argtype *types);
void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
const argtype *thunk_convert(void *dst, const void *src,
const argtype *type_ptr, int to_host);
unsigned int target_to_host_bitmask(unsigned int x86_mask,
bitmask_transtbl * trans_tbl);
unsigned int host_to_target_bitmask(unsigned int alpha_mask,
bitmask_transtbl * trans_tbl);
#endif