I have written a full MIPS I simulator that can load ELF binaries. You can get the source code here maybe you'll get answers to your questions. There are also some demo programs included.
The key point is to get the compiler to generate a freestanding executable that does not use any run-time library, not even the gcc's support library.
Up vote 0 down vote favorite 1 share g+ share fb share tw.
I have designed a MIPS I simulator using Verilator which allows me to wrap verilog code into c++. I am attempting to run a c++ program on my processor but I've reached some problems. My goal is to: write a test program in c++ compile this program using a cross compiler g++ (mips-linux) take generated ELF file and disassemble it using objdump store the entire binary object dump in a text file open text file in my simulator run some text manipulating functions to isolate the HEX dump portion of the objdump load entire elf hex dump into my processor's memory (a c++ memory map containing elements keyed by their address in memory as defined by the ELF file.
) run the program by setting the program counter and letting it go until exit syscall of program. The problem would be steps 7 and 8. I have a very rudimentary understanding of the ELF file format.
As far as I can tell (readelf can be used to output a program starting point) the program ounter should be set initially at the address of the beginning of the . Text section. Unfortunately doing this does not result in a proper program run on my processor.
I have verified proper program execution of my processor by writing assembly programs, loading them into MIPS assembly simulators, and verifying, instruction by instruction, that the register file and generated addressing matches. What I don't understand is why I can't get even a "helloworld" program to run by writing in c++, compiling, and loading into my "memory"? I'm not particularly knowledgeable in this field.
I could really use some help figuring this out. My understanding is that . Text and .
Data contain everything needed for my program to run. This is obviously not the case because as I traverse the . Text section, my program does not execute correctly.
Is there something else I need to do with the ELF file before loading it into memory? C++ assembly linker loader link|improve this question edited Jul 12 '10 at 19:48 asked Jul 12 '10 at 19:44Dan Snyder21229 97% accept rate.
Also, I've tried writing inline assembly and compiling to verify my processor but after compilation I'm unable to find my program (I just repeat an addi $0x12ab..." over and over again. Then I search for 0x12ab within the hex dump of the elf file. I haven't been able to find my program within the elf file this way.
– Dan Snyder Jul 12 '10 at 19:54 So, from looking at ZVRBA's simulator it seems as though the ELF file is loaded into memory very similarly to the way I do it. I basically chop out all characters from the elf file after HEX dumping it, and I add an element to a memory map using each hex instruction/data address as the key. I then access using the address key.
So the important aspects in terms of this process are to load all elements to their correct address and set the program, global,stack,and frame pointers to their required locations. Because this is what I'm doing I think I can assume that I should change my compiler. – Dan Snyder Jul 12 '10 at 21:00.
I have written a full MIPS I simulator that can load ELF binaries. You can get the source code here, maybe you'll get answers to your questions. There are also some demo programs included.
The key point is to get the compiler to generate a freestanding executable that does not use any run-time library, not even the gcc's support library.
I have also written a paper that describes in detail the workings of the simulator (including some ELF aspects). The paper abstract is here: computer.org/portal/web/csdl/doi/10.1109... Send me an email, so I can mail you the paper (I cannot publish it online due to copyright issues). – zvrba Jul 12 '10 at 20:02 I think that it would be a good idea for me to build my own cross compiler (instead of using the glitchy one supplied to me).
Do you know of a good resource describing this process? Specifically for the mipsel-elf gcc target? – Dan Snyder Jul 12 '10 at 20:51 I sent you an email.
Not sure if it made it through your filtering though. – Dan Snyder Jul 12 '10 at 21:27 Hm, it's not that hard to build a gcc cross-compiler. I deleted a VM where it lived, so I lost the configure options :-( With newer gcc versions I had to omit stack checking code and something related to mfpr library in order to get a working cross-compiler.
– zvrba Jul 13 '10 at 6:31 Hmm, well, I have 2 options right now. Either fix my current cross compiler or build one on my own. I suppose building one would be better as I would then have an idea of how it works.
(My BS ECE degree was not too focused on the concepts of linking and loading). As of now I just have a compiler that doesn't respond to ANY flags as far as I can see. Is there an easy fix for that or would it be better to just start over?
– Dan Snyder Jul 13 '10 at 13:44.
Here is an explanation of elf that I liked, although it seems that you understand the elf issues. They also explain how g++ outputs elf files, so it might help you parse your output file (more good info in part 1 as well). Hope some of that info helps.
Good explanation. Easier to get through than the Wikipedia article. Thanks.
– Dan Snyder Jul 12 '10 at 21:02.
Zvrba may have hit the nail on the head, you cannot/should not call C library functions like printf in your program. Write a simple C program to start with maybe: const unsigned char hello="helloworld"; void notmain ( void ) { unsigned int ra; for(ra=0;hellora;ra++) { PUT32(0x1234,hellora); } } and call notmain from the assembler programs that you have written and have working and link together. PUT32 just writes some data to some address, I normally implement these in assembler, ymmv.
Choose some address other than 0x1234, my assumption is with your sim environment you can watch accesses to an address location and watch the characters. No need yet to talk to a uart and have to decode serial in a simulation when you can watch the bytes on a bus. Elf files really are simple to parse, if you have written a simulator, reading an elf file is not a big deal.
I don't bother with libraries they just make it harder. It is a few structures if you chose to use structures. I can provide you with code that will get you started if you like.
An alternative is to use gnu tools to convert the elf into a binary file (mips-whatever-objcopy file. Elf -O binary file. Bin).
If your . Text and . Data are not close to each other the objcopy program will make a huge file with zeros for fill between the two address spaces.
For embedded you want to avoid having anything in your . Data section anyway, always initialize variables in the program not ahead of time and read only tables make const so they are in . Text instead of .
Data is this a project for fun or work or general public consumption? I might be interested in using it someday I like the concept of verilator but its either limited or too rigid to the verilog standard and so much verilog out there won't run under it without work, so I have not gotten to really play with it. Good luck.
The main reason why I used a map in c++ to represent my memory is because all empty memory locations are implied. If an element/key pair was established then there is an element in memory, if nothing was allotted to a specific space, when it is addressed by the simulator the return value is by default "0". – Dan Snyder Jul 13 '10 at 13:09 This project is for research but the simulator I am constructing isn't really proprietary.
It's just a tool I'll be using to try out various super pipe-lined architectures to compensate for the reduction in performance as supply voltage is dropped to near sub-threshold levels. I'd be happy to send it to you when it's up and running. – Dan Snyder Jul 13 '10 at 13:09 Verilator's biggest advantage is that it's very fast.
This is mainly due to the fact that it only compiles synthesizable verilog which does place a constraint on your coding freedom but because you can also write everything directly in C++ too, there's a nice sweet spot where one can take advantage of both verilog and c++. Also the founder of Verilator is very easy to get in contact with for questions so it's easy to figure out. – Dan Snyder Jul 13 '10 at 13:12 Also, I'm using objdump to disassemble the ELF file.
I was using readelf in the past but it seems pointless to separately load each segment file by file. I just run obj dump, place disassembled output into a text file, delete everything but addressing and hex words and load away. Works well.
I'll try out PUT32 and see if I can indeed access this element in memory. AS of now my compiler is stating that PUT32 is undecared. I'll see whats up with it.
– Dan Snyder Jul 13 '10 at 13:20 PUT32 is my own function, not a C library thing, simple to implement. Esp in your environment, which is similar to where I live, you can write one program in C, note PUT32 is not in the same source file it is implemented in a separate file. You could implement PUT32 so that it reaches into the verilator simulation thorugh C++ and hits the hardware, but the program is running on the host, or compile the program for the target and use a different implementation of PUT32 for the target and run on the target in simulation – dwelch Jul 13 '107 at 20:31.
I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.