ASSIGNMENT 3

Note: this was a draft version, and has now become the final version.

Assignment goal:

Basic understanding of object-code files. In particular, ELF format executable files, and the (basic) process of merging two pieces of code. Another goal is better hands-on experience with direct Linux system calls. In order to concerntrate on architecture, rather than systems programming issues, we will assume that one of the programs to be merged, also to be written in this exercise, is written as position independent code.

Program goal:

You are to write a program in 80X86 assembly language, that merges program A and program B, where both programs are executable ELF files. The result should be a single ELF file that includes the code and data of both programs, and such that program A runs to termination, and then program B is run. Your program should be written in fully (i.e. strictest) position independent code.

Details

Your program adds program A as an execution prequel to program B. Your program should support any ELF executable for Linux - 80386 and upwards, for program B. However, you may assume for simplicity that program A is a fully position independent code program, where all code is either

You will be able to tell the difference, because in both cases, the start address in the ELF file header will point to the first byte of executable code of program A. Thus, in the first case it will point to an address in .text, and in the second case it will point to an address that has no applicable section. Additionally, all of A's data resides on the stack, or resides next to the code in the same section (or "non-section", in the 2nd case), i.e. there are no data sections in the file.

Note, however, that your program should also obey the above rules. To obey these rules, you need to make sure that all your modifyable data is either in registers, or on the stack (like C local variables). Your jumps must all be relative, or must be done through an appropriate offset maintained in a register. The latter holds for all function calls, as well. Calling any external functions is also disallowed - but naturally you can use direct Linux system calls.

How do we achieve these goals?

Note that we do not have to perform real linking functions, only insert the code of program A and make it run before program B. This will be done by adding the code of program A to the end of the ELF file of program B, and tweaking the entry point of the program, so as to run the extra section first. Additionally, you must make sure that your additional code gets loaded into memory by adding or modifying the executable ELF file's program headers. After program A executes, control should be transfered to program B, i.e. to the original entry point.

Additional Requirements and Assumptions

You will write two versions of the program. In the first version, the program will receive two parameters - the names of the ELF files, of program A and program B, respectively. For simplicity, these parameters are not command-line parameters - they should be read from the user or from a file.

In the second version of the program, the program receives no parameters. Instead, it reads (using Linux system calls) the names of files in the current directory. Then, it uses the first filename in the directory as the the ELF file for program A, and the second filename in the directory as the ELF file for program B.

In both cases, your program should check that the files to be processed are ELF files, by checking the magic number and the "ELF" string in the file. If either is not an ELF file, your program should quietly terminate.

You may further assume, about the code of program A (but note that your own program should also observe these rules!):

What to submit

Deadline: January 15. Extended to January 18. Extended again (grace period) to January 20.