You really need to read up on compilers and compiler design.
Start with http://www.freetechbooks.com/compiler-design-and-construction-f14.html
Here's the summary.
The goal is to get stuff copied into memory that will execute and run. Then the OS hands control over to that stuff.
The "loader" copies stuff into memory from various files. These files are actually a kind of language describing where stuff goes in memory and what goes in those places. It's a kind of "load memory" language.
The job of compiler and linker is to create files that will make the loader do the right thing.
The compiler's output is "object" files -- essentially loader instructions in many small fragmented files with many external references. The compiler's output is ideally some machine code with place-holders for external references to be plugged in. All the internal references have been resolved as offsets into heap memory or stack frames or function names.
The linker's output is larger loader files with fewer external references. It's largely the same as the compiler's output in format. But it has more stuff folded in.
Read this on the ld command: http://linux.about.com/library/cmd/blcmdl1_ld.htm
Read this on the nm command: http://linux.about.com/library/cmd/blcmdl1_nm.htm
Here's some details.
"...how would it call functions or refer to variables?"
The function names, generally, are preserved until the later stages of producing output.
The variable names are transformed into something else. "Global" variables are allocated statically and the compiler has a map from variable name to type to offset into the static ("heap") memory.
Local variables within a function are (usually) allocated in the stack frame. The compiler has a map from variable name to type to offset into the stack frame. When the function is entered, a stack frame of the required size is allocated and the variables are simply offsets into that frame.
"...how would it call functions or refer to variables for operations?"
You have to provide a hint to the compiler. The extern
keyword tells the compiler that a name is not defined in this module, but is defined in another module and the reference must be resolved at link (or load) time.
"...if there is nothing to link..."
This is never true. Your program is only one piece of the overall executable. Most C libraries include the real main program which then calls your function named "main".
"will the linker change the object code output of assembler?"
This varies a lot with OS. In many OS's the linker and the loading all happen at once. What often happens is that the output from the C compiler is thrown into an archive without having really had much resolution performed.
When the executable is loaded into memory, the archive references and any external shared object files are loaded, also.
"The program is not running, its just in the manufacturing stage."
This doesn't mean anything. Not sure why you're including this.
"How could linker map to memory? How would it look like?"
The OS will allocate a block of memory into which the executable program must be copied. The linker/loader reads the object file, any object archive files, and copies the stuff in those files into that memory. The linker does the copying and name resolution and writes a new object file that's more compiler. The loader does it into real memory and turns over execution to the resulting text page.
"Its at the run time right?"
That's the only way to debug -- run time. It can't mean anything else, or it's not debugging.