最新消息:20210816 当前crifan.com域名已被污染,为防止失联,请关注(页面右下角的)公众号

eXecute In Place – XIP

工作和技术 crifan 2303浏览 0评论

eXecute In Place

XIP eXecute In Place

XIP (eXecute In Place ) is a useful option available with uClinux systems. Its main value lies in providing a means of allowing several copies of a program to be running without duplicating the text segment. Indeed the text segment can reside in flash memory and need not be copied to the system Ram at all. This is useful for tasks that have large program bodies with many executable instances running in the system.
Only the Stack, BSS and data segments of an executable needs to be produced for each running program. The text segment can then reside in flash memory or, if execution speed is an issue, then copy the file system to ram first and mount it from there. If executables in the file system are compiled to support XIP and also flagged in their headers as XIP they will load and execute with just a single copy of the text segment.

XIP and Kernel

The Kernel is always "XIP" the only question here is if the kernel is copied ram first before it is executed. This depends on a number of things.

  • Does the kernel use any variables in the text section
  • Is the kernel link map defined to base the kernel in Read Only Memory.
  • Does the kernel startup code (head.S or crt0.s in the kernel source tree) force the kernel to relocate to Ram.

Rumour has it that some arm kernel variables are specified in the text segment which may make it difficult to execute an Arm kernel from read only memory. (TODO: fire up the simulator and trap these )

The 68k (Dragonball) and Coldfire Kernels should be able to execute from read only memory. Make sure that all the init code is actually placed in ram to allow the init memory to be recovered (or just disable this process).

XIP and user tasks

User tasks can be defined as XIP. In this case only the data, BSS, reloc information and stack is present in a task specific ram area. Note that the stack area cannot grow. It is fixed at the time elf2flt is run. It can be modified by rerunning elf2flt or by using flthdr ( see below ).
Note: you cannot make non-XIP code into XIP code by using this flag. You can, however, force XIP code to load individual copies of the text section.

The kernel code that loads all flat files is:
linux-2.[04].x/fs/binfmt_flat.c .

An extract is shown below. This is where the ram required is allocated.

<font size="3"><strong>

     extra = MAX(bss_len + stack_len, relocs * sizeof(unsigned long));
 
     down_write(¤t-&gt;mm-&gt;mmap_sem);
     realdatastart = do_mmap(0, 0, data_len + extra +
                             MAX_SHARED_LIBS * sizeof(unsigned long),
                             PROT_READ|PROT_WRITE|PROT_EXEC, 0, 0);
     up_write(¤t-&gt;mm-&gt;mmap_sem);

</strong></font>

Flat File Relocs

The loader process has to handle any fixups required to the image due to changes in addresses as the data segment is allocated. This is a problem of working without an MMU. We cannot simply "make memory appear" at the right location. A list of relocations is specified by the elf2flt program at the time the elf file is converted to a flat file format.

There are two different kinds of reloc to consider.

Global Offset Table – GOT

Not really part of this document but worth a mention. If it is included due to a compile time option, the data segment will start with a GOT. The addresses in this table will need to be relocated to reflect the actual location of the data section. The GOT table (if present) will be terminated by a -1 ( 0xffffffff ).

Here is the code segment from binfmt_flat.c. This shows the GOT table update.

<font size="3"><strong>

  if (flags &amp; FLAT_FLAG_GOTPIC) {
     for (rp = (unsigned long *)datapos; *rp != 0xffffffff;rp++) {
        unsigned long addr;
        if (*rp) {
           addr = calc_reloc(*rp, libinfo, id, 0);
           if (addr == RELOC_FAILED)
              return -ENOEXEC;
           *rp = addr;
        }
     }
  }
</strong></font>

Code RELOCS

This operation uses a table of relocs generated by the elf2flt process. Note that, if the file is required to be XIP, then these relocs cannot affect any items in the text segment since this is intended to be shared by more than one executable.

Each entry in the table is an address of a location that needs to be relocated. The address needs to be modified first to contend with the fact that this location itself has been relocated. Once the modified address has been calculated the contents of that address can be determined and the new address applied to the location.

Complications arise when there are different byte ordering formats on the addresses (big/little endian) and the fact that the actual address of the reloc may be unaligned.

Once again the code segment from binfmt_flat.c. This shows the reloc resolution.

<font size="3"><strong>

    for (i=0; i &lt; relocs; i++) {
       unsigned long addr;
 
       /* Get the address of the pointer to be
          relocated (of course, the address has to be
          relocated first).  */
       rp = (unsigned long *)calc_reloc(ntohl(reloc[i]), libinfo, id, 1);
       if (rp == (unsigned long *)RELOC_FAILED)
          return -ENOEXEC;
 
       /* Get the pointer's value.  */
       addr = get_unaligned (rp);
 
       if (addr != 0) {
          /*
           * Do the relocation.  PIC relocs in the data section are
           * already in target order
           */
           addr = calc_reloc( (flags &amp;FLAT_FLAG_GOTPIC) ? addr : ntohl(addr),
                             libinfo, id, 0);
           if (addr == RELOC_FAILED)
              return -ENOEXEC;
           /* Write back the relocated pointer.  */
           put_unaligned (addr, rp);
        }
     }   
</strong></font>

Connections

As you can see that a number of systems have to work properly together to make this happen.

  • binfmt_flat.c must understand the output of elf2flt.
  • elf2flt must produce a proper output especially with the relocs area
  • The compiler must produce the correct GOT information and PIC code.
  • The library components especially crt0.o must co-operate with all of the above.

A revision level has been created to try to keep all of these components in sync.

Flathdr – The flat file manager

This is a program that allows you to examine or modify the contents of the flat header in a flat file produced by elf2flt

Here is a use example

<font size="3"><strong>

/usr/local/bin/flthdr romfs/bin/boa
romfs/bin/boa
    Magic:        bFLT
    Rev:          4
    Entry:        0x50
    Data Start:   0x11980
    Data End:     0x13d40
    BSS End:      0x15604
    Stack Size:   0x2000
    Reloc Start:  0x13d40
    Reloc Count:  0x4f
    Flags:        0x2 ( Has-PIC-GOT )flt. 
</strong></font>

The options available with flthdr are ..

<font size="3"><strong>

       -p      : print current settings
       -z      : compressed flat file
       -d      : compressed data-only flat file
       -Z      : un-compressed flat file
       -r      : ram load
       -R      : do not RAM load
       -s size : stack size
       -o file : output-file
                 (default is to modify input file)
</strong></font>

Here is an example of using flthdr to produce a compressed flatfile

<font size="3"><strong>

/usr/local/bin/flthdr -z romfs/bin/boa -o romfs/bin/boaz  

And the result

/usr/local/bin/flthdr -p romfs/bin/boaz
romfs/bin/boaz
    Magic:        bFLT
    Rev:          4
    Entry:        0x50
    Data Start:   0x11980
    Data End:     0x13d40
    BSS End:      0x15604
    Stack Size:   0x2000
    Reloc Start:  0x13d40
    Reloc Count:  0x4f
    Flags:        0x6 ( Has-PIC-GOT Gzip-Compressed )

ls -l romfs/bin/boa*
-rwxr--r--    1 philw    philw       81532 Jul 18 04:22 romfs/bin/boa
-rw-rw-r--    1 philw    philw       40261 Jul 18 04:16 romfs/bin/boaz
</strong></font>

The load to ram bit can be modified using the -r or -R options

<font size="3"><strong>

 /usr/local/bin/flthdr -r romfs/bin/boa 

Output follows...

/usr/local/bin/flthdr -p romfs/bin/boa
romfs/bin/boa
    Magic:        bFLT
    Rev:          4
    Entry:        0x50
    Data Start:   0x11980
    Data End:     0x13d40
    BSS End:      0x15604
    Stack Size:   0x2000
    Reloc Start:  0x13d40
    Reloc Count:  0x4f
    Flags:        0x3 ( Load-to-Ram Has-PIC-GOT )
</strong></font>

The stack size may also be adjusted using the -s option

<font size="3"><strong>
/usr/local/bin/flthdr  -s 16384 romfs/bin/boa 

And the output
usr/local/bin/flthdr -p romfs/bin/boa
romfs/bin/boa
    Magic:        bFLT
    Rev:          4
    Entry:        0x50
    Data Start:   0x11980
    Data End:     0x13d40
    BSS End:      0x15604
    Stack Size:   0x4000
    Reloc Start:  0x13d40
    Reloc Count:  0x4f
    Flags:        0x2 ( Has-PIC-GOT )
</strong></font>

Compile flags

Here we come to the core of this document. What compile flags are required for each system to get XIP to work. Here is a table that I hope will help. (TODO review and complete ) GOT options ???

ArchitectureUser AppsKernel
M68K (Dragonball)-msep_data-DMAGIC_ROM_PTR
Coldfire-msep_data-DMAGIC_ROM_PTR
Arm-D__PIC__ -fpic -msingle-pic-base(The -D__PIC__ is a temp hack)
SH3
<font size="3"><strong> </strong></font>
<font size="3"><strong> </strong></font>
Mips-G 0 -mabicalls -fpic-G0 -mno-abicalls -fno-pic
sparc
<font size="3"><strong> </strong></font>
<font size="3"><strong> </strong></font>
Etrax (cris)
<font size="3"><strong> </strong></font>
<font size="3"><strong> </strong></font>

Authors

The document produced by Phil Wilshire and forms part of the training program offered by System Design & Consulting Services (SDCS).

转载请注明:在路上 » eXecute In Place – XIP

发表我的评论
取消评论

表情

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
79 queries in 0.185 seconds, using 22.08MB memory