pete > courses > CS 315 Fall 26 > Assignment 04
Assignment 04
If any of this is unclear, please get in touch with me ASAP. There are definitely things in the course I want you to struggle with. I absolutely do NOT want you struggling with understanding my expectations.
In this assignment, you will implement your own runtime linker. The ultimate result will be a program that, when run, will call a function in libc that does not cause the official linker to run. You will presumably precede this function call by code of your own devising that will obviate the need to call the official linker. You may hardcode memory addresses as necessary and able but, when you do, you must document the hardcoded address with its source: describe in great detail how you decided on each particular address.
Additionally, you must turn in the script of a gdb session in which you demonstrate that your runtime linker does what it should do. Annotate this script with notes that make perfectly clear why it does indeed do what it’s supposed to do. Unless you want to copy and paste a lot, you might find the script(1) program handy here.
You will find the following functions useful:
- dlopen(3)
- dlclose(3)
- dlsym(3)
Your program must work both from the shell and from within gdb.
Casting
You will also likely want to perform casting, which is a note to the compiler to ignore type mismatches. Consider the following code:
char *c; int *i; c = i;
The compiler will reject this code because the types of the variable on the left-hand side of the assignment (c, a character pointer) does not match the type of the value on the right-hand side of the assignment (i, an integer pointer). Assuming you are 100% sure you know what you’re doing, you can get around this by telling the compiler the type of an expression, as in the following code, which will compile.
c = (char *) i;
Global offset table
You will need to locate the global offset table (GOT) in memory. Fortunately, there exists a symbol that will help! To use it, you must declare it as an extern variable (because it is technically an undefined reference, even though you are going to be using it within your program). Note that this variable is the first entry; it does not point to the first entry. If you want its address, you’ll have to ampersand it.
extern void *_GLOBAL_OFFSET_TABLE_;
printf("The first entry of the global offset table is %p\n", _GLOBAL_OFFSET_TABLE_);
printf("The GOT starts at address %p\n", &_GLOBAL_OFFSET_TABLE_);
Due to factors beyond the (current) scope of this course, this symbol can be a bit elusive, especially when compiling/running on weathertop. To make it reliably useful, both within and without gdb, you must compile with the -fpie option.
Behavioral requirements
Your program must issue a call to an external function (something in libc, like puts or strcpy is easiest). The GOT entry for this external function must point to the actual implementation of the function before the function is ever called from your program. This means you must implement logic that executes before the function call in question that modifies the GOT appropriately.
Should you hard-code memory addresses, you must document exactly how you calculated them. It’s easiest if you do so in comments near the use, rather than in the README.
Your program must work from the shell as well as within gdb.
Deliverable requirements
Three files:
self-linker.c, whose contents and behavior are described above.
Makefile, whose default target should build the aforementioned source file into a program named self-linker. You may have other targets if you like, but the default one must build self-linker.
README, which will include a list of authors, a list of known bugs, and a list of resources you consulted in your work (a list of URLs is totally acceptable—if I can see the kinds of references you’re using, I can get a better idea of how to tailor the instruction to your needs—just keep the README file open as you work and paste them there when you find something useful).
The README should also contain your annotated gdb session that demonstrates the correctness of your implementation.
Style requirements
Your code must exhibit:
- appropriate use of comments;
- appropriate use of stack, heap, and global variables;
- appropriate use of constants;
- appropriate decomposition;
- clear organization (eg, grouped header files, struct definitions, function prototypes);
- well-named variables, functions, and other identifiers;
- verification of command-line arguments, if applicable;
- checking and appropriate handling of all return values;
- consistent style (capitalization, indenting, etc).
Submission Process
Your submission files should be in a git repository on basin in this directory:
/home/<username>/<secret>/assignment4
Email me when you want feedback, with a description of the type of feedback you would like.