<html><title>data</title><body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#330088" ALINK="#FF0044"><H1>Adding Application Support for a New Architecture in Plan 9</H1><DL><DD><I>Bob Flandrena<br>bobf@plan9.bell-labs.com<br></I></DL><H4>Introduction</H4><br> <br>Plan 9 has five classes of architecture-dependent software:headers, kernels, compilers and loaders, the<TT>libc</TT>system library, and a few application programs. In general,architecture-dependent programsconsist of a portable part shared by all architectures and aprocessor-specific portion for each supported architecture.The portable code is often compiled and stored in a libraryassociated witheach architecture. A program is built bycompiling the architecture-specific code and loading it with thelibrary. Support for a new architecture is providedby building a compiler for the architecture, using it tocompile the portable code into libraries,writing the architecture-specific code, andthen loading that code withthe libraries.<br> <br>This document describes the organization of the architecture-dependentcode and headers on Plan 9.The first section briefly discusses the layout ofthe headers and the source code for the kernels, compilers, loaders, and thesystem library, <TT>libc</TT>.The second section provides a detaileddiscussion of the structure of<TT>libmach</TT>,a library containing almostall architecture-dependent codeused by application programs.The final section describes the steps required to addapplication program support for a new architecture.<H4>Directory Structure</H4><P>Architecture-dependent information for the new processoris stored in the directory tree rooted at</I><TT>/<I>m</TT><I>where</I><I>m</I><I>is the name of the new architecture (e.g.,</I><TT>mips</TT><I>).The new directory should be initialized with several importantsubdirectories, notably</I><TT>bin</TT><I>,</I><TT>include</TT><I>,and</I><TT>lib</TT><I>.The directory tree of an existing architectureserves as a good model for the new tree.The architecture-dependent</I><TT>mkfile</TT><I>must be stored in the newly created root directoryfor the architecture. It is easiest to copy themkfile for an existing architecture and modifyit for the new architecture. When the mkfileis correct, change the</I><TT>OS</TT><I>and</I><TT>CPUS</TT><I>variables in the</I><TT>/sys/src/mkfile.proto</TT><I>to reflect the addition of the new architecture.</P></I><H4>Headers</H4><br> <br>Architecture-dependent headers are stored in directory<TT>/<I>m</I>/include</TT>where<I>m</I>is the name of the architecture (e.g.,<TT>mips</TT>).Two header files are required:<TT>u.h</TT>and<TT>ureg.h</TT>.The first defines fundamental data types,bit settings for the floating pointstatus and control registers, and<TT>va_list</TT>processing which depends on the stackmodel for the architecture. This fileis best built by copying and modifying the<TT>u.h</TT>file from an architecturewith a similar stack model.The<TT>ureg.h</TT>filecontains a structure describing the layoutof the saved register set forthe architecture; it is defined by the kernel.<br> <br>Header file<TT>/sys/include/a.out.h</TT>contains the definitions of the magicnumbers used to identify executables foreach architecture. When support for a newarchitecture is added, the magic numberfor the architecture must be added to this file.<br> <br>The header format of a bootable executable is defined byeach manufacturer. Header file<TT>/sys/include/bootexec.h</TT>contains structures describing the headers currentlysupported. If the new architecture uses a common headersuch as COFF,the header format is probably already defined,but if the bootable header format is non-standard,a structure defining the format must be added to this file.<br> <br><H4>Kernel</H4><br> <br>Although the kernel depends critically on the properties of the underlyinghardware, most of thehigher-level kernel functions, including processmanagement, paging, pseudo-devices, and somenetworking code, are independent of processorarchitecture. The portable kernel codeis divided into two parts: that implementing kernelfunctions and that devoted to the boot process.Code in the first class is stored in directory<TT>/sys/src/9/port</TT>and the portable boot code is stored in<TT>/sys/src/9/boot</TT>.Architecture-dependent kernel code is stored in thesubdirectories of<TT>/sys/src/9</TT>named for each architecture.<br> <br>The relationship between the kernel code and the boot codeis convoluted and subtle. The portable boot codeis compiled into a library for each architecture. An architecture-specificmain program is loaded with the appropriate library and the resultingexecutable is compiled into the kernel where it is executed asa user process during the final stages of kernel initialization. The boot processperforms authentication, attaches the name space root to the appropriatefile system and starts the<TT>init</TT>process.<br> <br>The organization of the portable kernel source code differs from thatof most other architecture-specific code.Instead of storing the portable code in a libraryand loading it with the architecture-specificcode, the portable code is compiled directly intothe directory containing the architecture-specific codeand linked with the object files built from the source in that directory.<br> <br><H4>Compilers and Loaders</H4><br> <br>The compiler source code conforms to the usualorganization: portable code is compiled into a libraryfor each architectureand the architecture-dependent code is loaded withthat library.The common compiler code is stored in<TT>/sys/src/cmd/cc</TT>.The<TT>mkfile</TT>in this directory compiles the portable source andarchives the objects in a library for each architecture.The architecture-specific compiler sourceis stored in a subdirectory of<TT>/sys/src/cmd</TT>with the same name as the compiler (e.g.,<TT>/sys/src/cmd/vc</TT>).<br> <br>There is no portable code shared by the loaders.Each directory of loader sourcecode is self-contained, except fora header file and an instruction name tableincluded from thedirectory of the associatedcompiler.<br> <br><H4>Libraries</H4><br> <br>Most C library modules areportable; the source code is stored indirectories<TT>/sys/src/libc/port</TT>and<TT>/sys/src/libc/9sys</TT>.Architecture-dependent library codeis stored in the subdirectory of<TT>/sys/src/libc</TT>named the same as the target processor.Non-portable functions not onlyimplement architecture-dependent operationsbut also supply assembly language implementationsof functions where speed is critical.Directory<TT>/sys/src/libc/9syscall</TT>is unusual because itcontains architecture-dependent informationfor all architectures.It holds only a header file definingthe names and numbers of system callsand a<TT>mkfile</TT>.The<TT>mkfile</TT>executes an<TT>rc</TT>script that parses the header file, constructsassembler language functions implementing the systemcall for each architecture, assembles the code,and archives the object files in<TT>libc</TT>.The assembler language syntax and the system interfacediffer for each architecture.The<TT>rc</TT>script in this<TT>mkfile</TT>must be modified to support a new architecture.<br> <br><H4>Applications</H4><br> <br>Application programs process two forms of architecture-dependentinformation: executable images and intermediate object files.Almost all processing is on executable files.System library<TT>libmach</TT>provides functions that convertarchitecture-specific datato a portable format so application programscan process this data independent of itsunderlying representation.Further, when a new architecture is implementedalmost all code changesare confined to the library;most affected application programs need only be reloaded.The source code for the library is stored in<TT>/sys/src/libmach</TT>.<br> <br>An application program running on one type ofprocessor must be able to interpretarchitecture-dependent information for allsupported processors.For example, a debugger must be able to debugthe executables ofall architectures, not just thearchitecture on which it is executing, since<TT>/proc</TT>may be imported from a different machine.<br> <br>A small part of the application libraryprovides functions toextract symbol references from object files.The remainder provides the following processingof executable files or memory images:<DL><DD><br> <br><DL COMPACT><DT>*<DD>Header interpretation.<DT>*<DD>Symbol table interpretation.<DT>*<DD>Execution context interpretation, such as stack tracesand stack frame location.<DT>*<DD>Instruction interpretation including disassembly andinstruction size and follow-set calculations.<DT>*<DD>Exception and floating point number interpretation.<DT>*<DD>Architecture-independent read and write access through arelocation map.</DL></dl><br> <br>Header file<TT>/sys/include/mach.h</TT>defines the interfaces to theapplication library. Manual pages<A href="/magic/man2html/2/mach"><I>mach</I>(2),</A><A href="/magic/man2html/2/symbol"><I>symbol</I>(2),</A>and<A href="/magic/man2html/2/object"><I>object</I>(2)</A>describe the details of thelibrary functions.<br> <br>Two data structures, called<TT>Mach</TT>and<TT>Machdata</TT>,contain architecture-dependent parameters anda jump table of functions.Global variables<TT>mach</TT>and<TT>machdata</TT>point to the<TT>Mach</TT>and<TT>Machdata</TT>data structures associated with the target architecture.An application determines the target architecture ofa file or executable image, sets the global pointersto the data structures associated with that architecture,and subsequently performs all references indirectly through thepointers.As a result, direct references to the tables for eacharchitecture are avoided and the application code intrinsicallysupports all architectures (though only one at a time).<br> <br>Object file processing is handled similarly: architecture-dependentfunctions identify anddecode the intermediate files for the processor.The application indirectlyinvokes a classification function to identifythe architecture of the object code and to select theappropriate decoding function. Subsequent callsthen use that function to decode each record. Again,the layer of indirection allows the application codeto support all architectures without modification.<br> <br>Splitting the architecture-dependent informationbetween the<TT>Mach</TT>and<TT>Machdata</TT>data structuresallows applications to choosean appropriate level of service. Even though an applicationdoes not directly reference the architecture-specific data structures,it must load thearchitecture-dependent tables and code for all architectures it supports. The size of this datacan be substantial and many applications do not requirethe full range of architecture-dependent functionality.For example, the<TT>size</TT>command does not require the disassemblers for every architecture;it only needs to decode the header.The<TT>Mach</TT>data structure contains a few architecture-specific parametersand a description of the processor register set.The size of the structurevaries with the size of the registerset but is generally small.The<TT>Machdata</TT>data structure containsa jump table of architecture-dependent functions;the amount of code and data referenced by this tableis usually large.<H4>Libmach Source Code Organization</H4><br> <br>The<TT>libmach</TT>library provides four classes of functionality:<br> <br><DL COMPACT><DT>Header and Symbol Table Decoding - <DD>Files<TT>executable.c</TT>and<TT>sym.c</TT>contain code to interpret the header andsymbol tables ofan executable file or executing image.Function<TT>crackhdr</TT>decodes the header,reformats theinformation into an<TT>Fhdr</TT>data structure, and pointsglobal variable<TT>mach</TT>to the<TT>Mach</TT>data structure of the target architecture.The symbol table processinguses the data in the<TT>Fhdr</TT>structure to decode the symbol table.A variety of symbol table access functions then supportqueries on the reformatted table.<DT>Debugger Support - <DD>Files named<TT><I>m</I>.c</TT>,where<I>m</I>is the code letter assigned to the architecture,contain the initialized<TT>Mach</TT>data structure and the definition of the registerset for each architecture.Architecture-specific debugger support functions andan initialized<TT>Machdata</TT>structure are stored infiles named<TT><I>m</I>db.c</TT>.Files<TT>machdata.c</TT>and<TT>setmach.c</TT>contain debugger support functions sharedby multiple architectures.<DT>Architecture-Independent Access - <DD>Files<TT>map.c</TT>,<TT>access.c</TT>,and<TT>swap.c</TT>provide accesses through a relocation mapto data in an executable file or executing image.Byte-swapping is performed as needed. Global variables<TT>mach</TT>and<TT>machdata</TT>must point to the<TT>Mach</TT>and<TT>Machdata</TT>data structures of the target architecture.<DT>Object File Interpretation - <DD>These files contain functions to identify thetarget architecture of anintermediate object fileand extract references to symbols. File<TT>obj.c</TT>contains code common to all architectures;file<TT><I>m</I>obj.c</TT>contains the architecture-specific source codefor the machine with code character<I>m</I>.</dl><br> <br>The<TT>Machdata</TT>data structure is primarily a jumptable of architecture-dependent debugger supportfunctions. Functions select the<TT>Machdata</TT>structure for a target architecture basedon the value of the<TT>type</TT>code in the<TT>Fhdr</TT>structure or the name of the architecture.The jump table provides functions to swap bytes, interpretmachine instructions,perform stacktraces, find stack frames, format floating pointnumbers, and decode machine exceptions. Some functions, such asmachine exception decoding, are idiosyncratic and must besupplied for each architecture. Others dependon the compiler run-time model and severalarchitectures may share code common to a model. Forexample, many architectures share the code toprocess the fixed-frame stack model implemented byseveral of the compilers.Finally, somefunctions, such as byte-swapping, provide a general capability andthe jump table need only select an implementation appropriateto the architecture.<br> <br><H4>Adding Application Support for a New Architecture</H4><br> <br>This section describes thesteps required to add application-levelsupport for a new architecture.We assumethe kernel, compilers, loaders and system librariesfor the new architecture are already in place. Thisimplies that a code-character has been assigned andthat the architecture-specific headers have beenupdated.With the exception of two programs,application-level changes are confined to headerfiles and the source code inLines 1–500 of 911. Load more
<html> <title> data </title> <body BGCOLOR="#FFFFFF" TEXT="#000000" LINK="#0000FF" VLINK="#330088" ALINK="#FF0044"> <H1>Adding Application Support for a New Architecture in Plan 9 </H1> <DL><DD><I>Bob Flandrena<br> bobf@plan9.bell-labs.com<br> </I></DL> <H4>Introduction </H4> <br> <br> Plan 9 has five classes of architecture-dependent software: headers, kernels, compilers and loaders, the <TT>libc</TT> system library, and a few application programs. In general, architecture-dependent programs consist of a portable part shared by all architectures and a processor-specific portion for each supported architecture. The portable code is often compiled and stored in a library associated with each architecture. A program is built by compiling the architecture-specific code and loading it with the library. Support for a new architecture is provided by building a compiler for the architecture, using it to compile the portable code into libraries, writing the architecture-specific code, and then loading that code with the libraries. <br> <br> This document describes the organization of the architecture-dependent code and headers on Plan 9. The first section briefly discusses the layout of the headers and the source code for the kernels, compilers, loaders, and the system library, <TT>libc</TT>. The second section provides a detailed discussion of the structure of <TT>libmach</TT>, a library containing almost all architecture-dependent code used by application programs. The final section describes the steps required to add application program support for a new architecture. <H4>Directory Structure </H4> <P> Architecture-dependent information for the new processor is stored in the directory tree rooted at </I><TT>/<I>m</TT><I> where </I><I>m</I><I> is the name of the new architecture (e.g., </I><TT>mips</TT><I>). The new directory should be initialized with several important subdirectories, notably </I><TT>bin</TT><I>, </I><TT>include</TT><I>, and </I><TT>lib</TT><I>. The directory tree of an existing architecture serves as a good model for the new tree. The architecture-dependent </I><TT>mkfile</TT><I> must be stored in the newly created root directory for the architecture. It is easiest to copy the mkfile for an existing architecture and modify it for the new architecture. When the mkfile is correct, change the </I><TT>OS</TT><I> and </I><TT>CPUS</TT><I> variables in the </I><TT>/sys/src/mkfile.proto</TT><I> to reflect the addition of the new architecture. </P> </I><H4>Headers </H4> <br> <br> Architecture-dependent headers are stored in directory <TT>/<I>m</I>/include</TT> where <I>m</I> is the name of the architecture (e.g., <TT>mips</TT>). Two header files are required: <TT>u.h</TT> and <TT>ureg.h</TT>. The first defines fundamental data types, bit settings for the floating point status and control registers, and <TT>va_list</TT> processing which depends on the stack model for the architecture. This file is best built by copying and modifying the <TT>u.h</TT> file from an architecture with a similar stack model. The <TT>ureg.h</TT> file contains a structure describing the layout of the saved register set for the architecture; it is defined by the kernel. <br> <br> Header file <TT>/sys/include/a.out.h</TT> contains the definitions of the magic numbers used to identify executables for each architecture. When support for a new architecture is added, the magic number for the architecture must be added to this file. <br> <br> The header format of a bootable executable is defined by each manufacturer. Header file <TT>/sys/include/bootexec.h</TT> contains structures describing the headers currently supported. If the new architecture uses a common header such as COFF, the header format is probably already defined, but if the bootable header format is non-standard, a structure defining the format must be added to this file. <br> <br> <H4>Kernel </H4> <br> <br> Although the kernel depends critically on the properties of the underlying hardware, most of the higher-level kernel functions, including process management, paging, pseudo-devices, and some networking code, are independent of processor architecture. The portable kernel code is divided into two parts: that implementing kernel functions and that devoted to the boot process. Code in the first class is stored in directory <TT>/sys/src/9/port</TT> and the portable boot code is stored in <TT>/sys/src/9/boot</TT>. Architecture-dependent kernel code is stored in the subdirectories of <TT>/sys/src/9</TT> named for each architecture. <br> <br> The relationship between the kernel code and the boot code is convoluted and subtle. The portable boot code is compiled into a library for each architecture. An architecture-specific main program is loaded with the appropriate library and the resulting executable is compiled into the kernel where it is executed as a user process during the final stages of kernel initialization. The boot process performs authentication, attaches the name space root to the appropriate file system and starts the <TT>init</TT> process. <br> <br> The organization of the portable kernel source code differs from that of most other architecture-specific code. Instead of storing the portable code in a library and loading it with the architecture-specific code, the portable code is compiled directly into the directory containing the architecture-specific code and linked with the object files built from the source in that directory. <br> <br> <H4>Compilers and Loaders </H4> <br> <br> The compiler source code conforms to the usual organization: portable code is compiled into a library for each architecture and the architecture-dependent code is loaded with that library. The common compiler code is stored in <TT>/sys/src/cmd/cc</TT>. The <TT>mkfile</TT> in this directory compiles the portable source and archives the objects in a library for each architecture. The architecture-specific compiler source is stored in a subdirectory of <TT>/sys/src/cmd</TT> with the same name as the compiler (e.g., <TT>/sys/src/cmd/vc</TT>). <br> <br> There is no portable code shared by the loaders. Each directory of loader source code is self-contained, except for a header file and an instruction name table included from the directory of the associated compiler. <br> <br> <H4>Libraries </H4> <br> <br> Most C library modules are portable; the source code is stored in directories <TT>/sys/src/libc/port</TT> and <TT>/sys/src/libc/9sys</TT>. Architecture-dependent library code is stored in the subdirectory of <TT>/sys/src/libc</TT> named the same as the target processor. Non-portable functions not only implement architecture-dependent operations but also supply assembly language implementations of functions where speed is critical. Directory <TT>/sys/src/libc/9syscall</TT> is unusual because it contains architecture-dependent information for all architectures. It holds only a header file defining the names and numbers of system calls and a <TT>mkfile</TT>. The <TT>mkfile</TT> executes an <TT>rc</TT> script that parses the header file, constructs assembler language functions implementing the system call for each architecture, assembles the code, and archives the object files in <TT>libc</TT>. The assembler language syntax and the system interface differ for each architecture. The <TT>rc</TT> script in this <TT>mkfile</TT> must be modified to support a new architecture. <br> <br> <H4>Applications </H4> <br> <br> Application programs process two forms of architecture-dependent information: executable images and intermediate object files. Almost all processing is on executable files. System library <TT>libmach</TT> provides functions that convert architecture-specific data to a portable format so application programs can process this data independent of its underlying representation. Further, when a new architecture is implemented almost all code changes are confined to the library; most affected application programs need only be reloaded. The source code for the library is stored in <TT>/sys/src/libmach</TT>. <br> <br> An application program running on one type of processor must be able to interpret architecture-dependent information for all supported processors. For example, a debugger must be able to debug the executables of all architectures, not just the architecture on which it is executing, since <TT>/proc</TT> may be imported from a different machine. <br> <br> A small part of the application library provides functions to extract symbol references from object files. The remainder provides the following processing of executable files or memory images: <DL><DD> <br> <br> <DL COMPACT> <DT>*<DD> Header interpretation. <DT>*<DD> Symbol table interpretation. <DT>*<DD> Execution context interpretation, such as stack traces and stack frame location. <DT>*<DD> Instruction interpretation including disassembly and instruction size and follow-set calculations. <DT>*<DD> Exception and floating point number interpretation. <DT>*<DD> Architecture-independent read and write access through a relocation map. </DL> </dl> <br> <br> Header file <TT>/sys/include/mach.h</TT> defines the interfaces to the application library. Manual pages <A href="/magic/man2html/2/mach"><I>mach</I>(2), </A><A href="/magic/man2html/2/symbol"><I>symbol</I>(2), </A>and <A href="/magic/man2html/2/object"><I>object</I>(2) </A>describe the details of the library functions. <br> <br> Two data structures, called <TT>Mach</TT> and <TT>Machdata</TT>, contain architecture-dependent parameters and a jump table of functions. Global variables <TT>mach</TT> and <TT>machdata</TT> point to the <TT>Mach</TT> and <TT>Machdata</TT> data structures associated with the target architecture. An application determines the target architecture of a file or executable image, sets the global pointers to the data structures associated with that architecture, and subsequently performs all references indirectly through the pointers. As a result, direct references to the tables for each architecture are avoided and the application code intrinsically supports all architectures (though only one at a time). <br> <br> Object file processing is handled similarly: architecture-dependent functions identify and decode the intermediate files for the processor. The application indirectly invokes a classification function to identify the architecture of the object code and to select the appropriate decoding function. Subsequent calls then use that function to decode each record. Again, the layer of indirection allows the application code to support all architectures without modification. <br> <br> Splitting the architecture-dependent information between the <TT>Mach</TT> and <TT>Machdata</TT> data structures allows applications to choose an appropriate level of service. Even though an application does not directly reference the architecture-specific data structures, it must load the architecture-dependent tables and code for all architectures it supports. The size of this data can be substantial and many applications do not require the full range of architecture-dependent functionality. For example, the <TT>size</TT> command does not require the disassemblers for every architecture; it only needs to decode the header. The <TT>Mach</TT> data structure contains a few architecture-specific parameters and a description of the processor register set. The size of the structure varies with the size of the register set but is generally small. The <TT>Machdata</TT> data structure contains a jump table of architecture-dependent functions; the amount of code and data referenced by this table is usually large. <H4>Libmach Source Code Organization </H4> <br> <br> The <TT>libmach</TT> library provides four classes of functionality: <br> <br> <DL COMPACT> <DT>Header and Symbol Table Decoding - <DD> Files <TT>executable.c</TT> and <TT>sym.c</TT> contain code to interpret the header and symbol tables of an executable file or executing image. Function <TT>crackhdr</TT> decodes the header, reformats the information into an <TT>Fhdr</TT> data structure, and points global variable <TT>mach</TT> to the <TT>Mach</TT> data structure of the target architecture. The symbol table processing uses the data in the <TT>Fhdr</TT> structure to decode the symbol table. A variety of symbol table access functions then support queries on the reformatted table. <DT>Debugger Support - <DD> Files named <TT><I>m</I>.c</TT>, where <I>m</I> is the code letter assigned to the architecture, contain the initialized <TT>Mach</TT> data structure and the definition of the register set for each architecture. Architecture-specific debugger support functions and an initialized <TT>Machdata</TT> structure are stored in files named <TT><I>m</I>db.c</TT>. Files <TT>machdata.c</TT> and <TT>setmach.c</TT> contain debugger support functions shared by multiple architectures. <DT>Architecture-Independent Access - <DD> Files <TT>map.c</TT>, <TT>access.c</TT>, and <TT>swap.c</TT> provide accesses through a relocation map to data in an executable file or executing image. Byte-swapping is performed as needed. Global variables <TT>mach</TT> and <TT>machdata</TT> must point to the <TT>Mach</TT> and <TT>Machdata</TT> data structures of the target architecture. <DT>Object File Interpretation - <DD> These files contain functions to identify the target architecture of an intermediate object file and extract references to symbols. File <TT>obj.c</TT> contains code common to all architectures; file <TT><I>m</I>obj.c</TT> contains the architecture-specific source code for the machine with code character <I>m</I>. </dl> <br> <br> The <TT>Machdata</TT> data structure is primarily a jump table of architecture-dependent debugger support functions. Functions select the <TT>Machdata</TT> structure for a target architecture based on the value of the <TT>type</TT> code in the <TT>Fhdr</TT> structure or the name of the architecture. The jump table provides functions to swap bytes, interpret machine instructions, perform stack traces, find stack frames, format floating point numbers, and decode machine exceptions. Some functions, such as machine exception decoding, are idiosyncratic and must be supplied for each architecture. Others depend on the compiler run-time model and several architectures may share code common to a model. For example, many architectures share the code to process the fixed-frame stack model implemented by several of the compilers. Finally, some functions, such as byte-swapping, provide a general capability and the jump table need only select an implementation appropriate to the architecture. <br> <br> <H4>Adding Application Support for a New Architecture </H4> <br> <br> This section describes the steps required to add application-level support for a new architecture. We assume the kernel, compilers, loaders and system libraries for the new architecture are already in place. This implies that a code-character has been assigned and that the architecture-specific headers have been updated. With the exception of two programs, application-level changes are confined to header files and the source code in