mirror of
https://github.com/autc04/Retro68.git
synced 2024-11-27 14:50:23 +00:00
226 lines
10 KiB
HTML
226 lines
10 KiB
HTML
|
<html>
|
|||
|
<head>
|
|||
|
<title>uClinux - BFLT Binary Flat Format</title>
|
|||
|
<META name="description" content="Setting up a development system for uClinux from scratch is not hard. This article covers the uClinux Kernel 2.0.38, m68k-coff, m68k-pic-coff, m68k-pic32-coff and m68k-elf Tool Chains, coff2flt converter, uC-libc and uC-libm libraries, gdb and the new uClinux 2.4.0 kernel. All the sources are downloadable,with links provided.">
|
|||
|
<META name="keywords" content="uClinux, m68k-pic-coff, m68k-coff, m68k-elf, coff2flt, elf2flt, arm-linux-elf, bFLT, Binary Flat, Relocations, GOT Global Offset Table">
|
|||
|
</head>
|
|||
|
|
|||
|
<body leftmargin="0" topmargin="0" marginheight="0" marginwidth="0" background="/bgyellow.gif" BASEFONT FACE=ARIAL>
|
|||
|
<STYLE TYPE="text/css">
|
|||
|
#TITLEBLOCK { text-decoration: none; color:#FFFFFF }
|
|||
|
TD,P,FONT,A,LI,B {font-family : Arial}
|
|||
|
PRE,TT {color:#100080}
|
|||
|
</STYLE>
|
|||
|
|
|||
|
<BR><CENTER>
|
|||
|
<TABLE BOARDER=0 WIDTH="95%"><TR>
|
|||
|
<TD WIDTH="25%"><CENTER><a href="http://www.beyondlogic.org"><img src="/beyondsmall.gif" alt="Beyond Logic" border=0></a></CENTER></TD>
|
|||
|
<TD WIDTH="50%"><CENTER>
|
|||
|
|
|||
|
<script type="text/javascript"><!--
|
|||
|
google_ad_client = "pub-7725444460812017";
|
|||
|
google_ad_width = 468;
|
|||
|
google_ad_height = 60;
|
|||
|
google_ad_format = "468x60_as";
|
|||
|
google_ad_type = "text_image";
|
|||
|
google_ad_channel ="";
|
|||
|
google_color_border = "0033FF";
|
|||
|
google_color_bg = "FFFFFF";
|
|||
|
google_color_link = "0000FF";
|
|||
|
google_color_url = "008000";
|
|||
|
google_color_text = "000000";
|
|||
|
//--></script>
|
|||
|
<script type="text/javascript"
|
|||
|
src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
|
|||
|
</script>
|
|||
|
<NOSCRIPT><FONT COLOR=RED>This page is optimised with JavaScript 1.2. Currently your browser has JavaScript switched off.</NOSCRIPT>
|
|||
|
</CENTER></TD>
|
|||
|
<TD ALIGN=RIGHT VALIGN=CENTER><BR><FONT FACE=ARIAL>
|
|||
|
<script language=javascript src="http://www.beyondlogic.org/menu/beyondmenu_plain.js"></script>
|
|||
|
<NOSCRIPT></TD></TR></TABLE></CENTER></noscript>
|
|||
|
|
|||
|
<TABLE WIDTH="95%"><TR><TD>
|
|||
|
<BR>
|
|||
|
<CENTER><FONT COLOR=GREEN SIZE=5>uClinux - BFLT Binary Flat Format</FONT></CENTER>
|
|||
|
</CENTER>
|
|||
|
<UL>
|
|||
|
<P>
|
|||
|
uClinux uses a Binary Flat format commonly known as BFLT. It is a relatively simple
|
|||
|
and lightweight executable format based on the original a.out format. It has seen
|
|||
|
two major revisions, version 2 and more recently version 4. Version 2 is used by the
|
|||
|
m68k-coff compilers and is still in use with the ARM elf2flt converter while version
|
|||
|
4 is used with the m68k elf2flt converter. Like many open source projects worked on
|
|||
|
by many individuals, little features have creped into versions without the revision
|
|||
|
field changing. As a consequence what we detail in each version may not strictly be
|
|||
|
the case in all circumstances. Both the 2.0.x and 2.4.x kernels<6C> bFLT loaders in the
|
|||
|
CVS support both formats. Earlier kernels may need to have binfmt_flat.c and flat.c
|
|||
|
patched to support version 4, should version 4 binaries report the following message
|
|||
|
when loading
|
|||
|
</P>
|
|||
|
<UL><PRE>
|
|||
|
bFLT:not found.
|
|||
|
bad magic/rev(4,need 2)
|
|||
|
</PRE></UL>
|
|||
|
<TABLE>
|
|||
|
<TR><TD>
|
|||
|
<P>
|
|||
|
Each flat binary is preceded by a header of the structure shown below in listing 1. It starts
|
|||
|
with 4 ASCII bytes, <20>bFLT<4C> or 0x62, 0x46, 0x4C, 0x54 which identifies the binary
|
|||
|
as conforming to the flat format. The next field designates the version number of
|
|||
|
the flat header. As mentioned there are two major versions, version 2 and version
|
|||
|
4. Each version differs by the supported flags and the format of the relocations.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
The next group of fields in the header specify the starting address of each segment
|
|||
|
relative to the start of the flat file. Most files start the .text segment at 0x40
|
|||
|
(immediately after the end of the header).
|
|||
|
The data_start, data_end and bss_end fields specify the start or finish of the
|
|||
|
designated segments. With the absence of text_end and bss_start fields, it is
|
|||
|
assumed that the text segment comes first, followed immediately by the data segment.
|
|||
|
While the comments for the flat file header would suggest there is a bss segment
|
|||
|
somewhere in the flat file, this is not true. bss_end is used to represent the
|
|||
|
length of the bss segment, thus should be set to data_end + size of bss.
|
|||
|
</P>
|
|||
|
</TD><TD>
|
|||
|
<CENTER><img src="bflt.gif" alt="bFLT File Format" border=0><BR><I>Figure 1 : Flat File Format</I></CENTER>
|
|||
|
</TD></TR>
|
|||
|
</TABLE>
|
|||
|
|
|||
|
<UL><PRE>
|
|||
|
struct flat_hdr {
|
|||
|
char magic[4];
|
|||
|
unsigned long rev; /* version */
|
|||
|
unsigned long entry; /* Offset of first executable instruction
|
|||
|
with text segment from beginning of file */
|
|||
|
unsigned long data_start; /* Offset of data segment from beginning of
|
|||
|
file */
|
|||
|
unsigned long data_end; /* Offset of end of data segment
|
|||
|
from beginning of file */
|
|||
|
unsigned long bss_end; /* Offset of end of bss segment from beginning
|
|||
|
of file */
|
|||
|
|
|||
|
/* (It is assumed that data_end through bss_end forms the bss segment.) */
|
|||
|
|
|||
|
unsigned long stack_size; /* Size of stack, in bytes */
|
|||
|
unsigned long reloc_start; /* Offset of relocation records from
|
|||
|
beginning of file */
|
|||
|
unsigned long reloc_count; /* Number of relocation records */
|
|||
|
unsigned long flags;
|
|||
|
unsigned long filler[6]; /* Reserved, set to zero */
|
|||
|
};
|
|||
|
</PRE></UL>
|
|||
|
<P>
|
|||
|
<CENTER><I>Listing 1 : The bFLT header structure extracted from flat.h</I></CENTER>
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
Following the segments<74> start and end pointers comes the stack size field specified
|
|||
|
in bytes. This is normally set to 4096 by the m68k bFLT converters and can be
|
|||
|
changed by passing an argument (-s) to the elf2flt / coff2flt utility.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
The next two fields specify the details of the relocations. Each relocation is a
|
|||
|
long (32 bits) with the relocation table following the data segment in the flat
|
|||
|
binary file. The relocation entries are different per bFLT version.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
Version 2 specified a 2 bit type and 30 bit offset per relocation. This causes a
|
|||
|
headache with endianess problems. The 30 bit relocation is a pointer relative to
|
|||
|
zero where an absolute address is used. The type indicates whether the absolute
|
|||
|
address points to .text, .data or .bss.
|
|||
|
</P>
|
|||
|
<UL><PRE>
|
|||
|
#define FLAT_RELOC_TYPE_TEXT 0
|
|||
|
#define FLAT_RELOC_TYPE_DATA 1
|
|||
|
#define FLAT_RELOC_TYPE_BSS 2
|
|||
|
|
|||
|
struct flat_reloc {
|
|||
|
#if defined(__BIG_ENDIAN_BITFIELD) /* bit fields, ugh ! */
|
|||
|
unsigned long type : 2;
|
|||
|
signed long offset : 30;
|
|||
|
#elif defined(__LITTLE_ENDIAN_BITFIELD)
|
|||
|
signed long offset : 30;
|
|||
|
unsigned long type : 2;
|
|||
|
#endif
|
|||
|
</PRE></UL>
|
|||
|
<P>
|
|||
|
<CENTER><I>Listing 2 : Version 2 relocation structures - Not for use in new code.</I></CENTER>
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
This enables the flat loader to fix-up absolute addressing at runtime by jumping
|
|||
|
to the absolute address specified by the relocation entry and adding the loaded
|
|||
|
base address to the existing address.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
Version 4 removed the need of specifying a relocation type. Each relocation entry
|
|||
|
simply contains a pointer to an absolute address in need of fix-up. As the bFLT
|
|||
|
loader can determine the length of the .text segment at runtime (data_start -
|
|||
|
entry) we can use this to determine what segment the relocation is for. If the
|
|||
|
absolute address before fix-up is less that the text length, we can safety
|
|||
|
assume the relocation is pointing to the text segment and this add the base address
|
|||
|
of this segment to the absolute address.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
On the other hand if the absolute address before fix-up is greater than the text
|
|||
|
length, then the absolute address must be pointing to .data or .bss. As .bss
|
|||
|
always immediately follows the data segment there is no need to have a distinction,
|
|||
|
we just add the base address of the data segment and subtract the length of the
|
|||
|
text segment. We subtract the text segment as the absolute address in version 4
|
|||
|
is relative to zero and not to the start of the data segment.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
Now you could say we may take it one step further. As every absolute address is
|
|||
|
referenced to zero, we can simply add the base address of the text segment to
|
|||
|
each address needing fix-up. This would be true if the data segment immediately
|
|||
|
follows the text segment, but we now have complications of -msep-data where the
|
|||
|
text segment can be in ROM and the data segment in another location in RAM.
|
|||
|
Therefore we can no longer assume that the .data+.bss segment and text segment
|
|||
|
will immediately follow each other.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
The last defined field in the header is the flags. This appeared briefly in some
|
|||
|
version 2 headers (Typically ARM) but was cemented in place with version 4. The
|
|||
|
flags are defined as follows
|
|||
|
</P>
|
|||
|
<UL><PRE>
|
|||
|
#define FLAT_FLAG_RAM 0x0001 /* load program entirely into RAM */
|
|||
|
#define FLAT_FLAG_GOTPIC 0x0002 /* program is PIC with GOT */
|
|||
|
#define FLAT_FLAG_GZIP 0x0004 /* all but the header is compressed */
|
|||
|
</PRE></UL>
|
|||
|
<P>
|
|||
|
<CENTER><I>Listing 3 : New flags defined in Version 4</I></CENTER>
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
Early version 2 binaries saw both the .text and .data segments loaded into RAM
|
|||
|
regardless. XIP (eXecute in Place) was later introduced allowing programs to
|
|||
|
execute from ROM with only the data segment being copied into RAM. In version
|
|||
|
4, it is now assumed that each binary is loaded from ROM if GOTPIC is true and
|
|||
|
FLAT_FLAG_GZIP and FLAT_FLAG_RAM is false. A binary can be forced to load into
|
|||
|
RAM by forcing the FLAT_FLAG_RAM flag.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
The FLAT_FLAG_GOTPIC informs the loader that a GOT (Global Offset Table) is
|
|||
|
present at the start of the data segment. This table includes offsets that
|
|||
|
need to be relocated at runtime and thus allows XIP to work. (Data is accessed
|
|||
|
through the GOT, thus relocations need not be made to the .text residing in ROM.) The
|
|||
|
GOT is terminated with a -1, followed immediately by the data segment.
|
|||
|
</P>
|
|||
|
<P>
|
|||
|
The FLAT_FLAG_GZIP indicates the binary is compressed with the GZIP algorithm.
|
|||
|
The header is left untouched, but the .text, .data and relocations are
|
|||
|
compressed. Some bFLT loaders do not support GZIP and will report an error
|
|||
|
at loading.
|
|||
|
</P>
|
|||
|
|
|||
|
<P>
|
|||
|
<BR>
|
|||
|
<FONT SIZE=-1><I>Acknowledgments to Pauli from Lineo for pointing out some minor errors.</I></FONT>
|
|||
|
</P>
|
|||
|
|
|||
|
</UL>
|
|||
|
</TD></TR></TABLE>
|
|||
|
<BR>
|
|||
|
<CENTER><FONT SIZE=2>Copyright 2001-2005 <A href="/about.htm">Craig Peacock </a> - 15th June 2005.</FONT></CENTER>
|
|||
|
<BR>
|
|||
|
</BODY>
|
|||
|
</HTML>
|