[snip]
The best thing is to try some things out and you will realize what's
needed and work out what's going on. Compile the .obj files you're
loading with minimal compiler optimizations to keep them as simple as
possible, and investigate disassembler programs; I would recommend GNU
objdump.
And I really thought that I was getting somewere too. Okay one
question and it sounds simple enough but here goes: How in the world do
I set it up to that muladd would jump to the right place? Also, would
doing things in this mannor require things that could not be automated?
I was really hoping that there would be some way to execute things
that were in the psudo-filesystem without actually doing manual work.
Of course, everything can be automated.
Besides the compiled code for all the functions, the .o file also
contains tables telling you where each function starts and how long the
code for each function is, and also which bits of the compiled code need
to be "patched" after the code for each function has been loaded into
memory.
Here's the source of an extended blah.c:
int add(a, b)
{
return a + b;
}
int muladd(a, b, c)
{
return add(a, b * c);
}
int muladd2(a, b, c)
{
return muladd(a, b, c);
}
Now I compile it and look at the object file with objdump:
$ objdump -r blah.o
RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000001a R_386_PC32 add
00000030 R_386_PC32 muladd
What this tells me is that at offset 0x1a into the text section (which
is offset 0x4e in the file, since the text section starts at 0x34), I
need to insert the offset to the start of the function <add>. And at
offset 0x30 in the text section (0x64 in the file), I need to insert the
offset to the start of the function <muladd>.
The .o file also contains a table of where the start of each function
is:
$ objdump -t blah.o
00000000 g F .text 0000000b add
0000000b g F .text 00000018 muladd
00000023 g F .text 00000016 muladd2
This tells me the code for add is at the beginning, muladd starts at 0xb
and muladd2 starts at 0x23. It also tells me how long each function is
(0xb, 0x18 and 0x16 bytes respectively).
So I have all the information I need here to load all the functions into
memory and patch things up.
Here's one way to do it for example:
1. Load the whole .text section (from 0x34 to 0x34 + 0x23 + 0x16 in
blah.o) into a char * buffer allocated with malloc.
2. Patch the relocations. Code to do this at the end of this post.
I have done this "manually" in the sense that I used objdump to examine
blah.o and then hardcoded the numbers into the program. but the
information is all there in blah.o (that's where objdump got it from
after all).
So to automate the process properly you need to parse the .o file.
This is a helpful guide I found to loading and linking generally:
http://www.linuxjournal.com/node/6463/print
There is also a library called libelf you could consider using to parse
the .o file:
http://directory.fsf.org/libs/misc/libelf.html
Note that all this applies to ELF files. If you're using .obj files on
Windows, I don't think they're exactly the same, but the general
principle is similar. You'd have to find some docs for that, which may
be harder as Windows is not free software. Or, alternatively, just
specify that the "executable format" your miniOS uses is based on ELF.
Or you could write a script that actually invokes objdump to get the
information you need and generates a much simpler ".xex" file for your
miniOS in a format you define yourself.
Here's the code then that does some minimal "linking":
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
char *load_text(void)
{
FILE *fp = fopen("./blah.o", "rb");
char *buf = malloc(0x57);
int32_t *p;
/* Read the whole of the .text section into the buffer */
fseek(fp, 0x34L, SEEK_SET);
fread(buf, 1, 0x57, fp);
/* Fix up the "relocations". */
p = (int32_t *) (buf + 0x1a);
/*
* This is the call from muladd to add. add starts at 0, muladd starts at
* 0x1a. Offset is from instruction after muladd. So go back 0x1a + 4 bytes
*/
*p = -(0x1a + 4 - 0);
/*
* This is the call from muladd2 to muladd. muladd2 starts at 0x30, muladd
* starts at 0xb.
*/
p = (int32_t *) (buf + 0x30);
*p = -(0x30 + 4 - 0xb);
return buf;
}
typedef int (*add_t)(int, int);
typedef int (*muladd_t)(int, int, int);
int main(int argc, char **argv)
{
char *code = load_text();
add_t add = (add_t) code;
muladd_t muladd = (muladd_t) (code + 0xb);
int result = muladd(2, 3, 4);
printf("%d\n", result);
free(code);
return 0;
}