Author Topic: Using scanf and linking it with ld  (Read 6110 times)

Offline Kunal

  • Jr. Member
  • *
  • Posts: 2
Using scanf and linking it with ld
« on: April 17, 2014, 03:17:08 PM »
I am trying to write an assembly program that would accept one floating point number and exit. I have used the scanf function in my code.
I link it with the command: ld -lc program_object_file.o -o program
The linker doesn't raise an error. However, when I do this: ./program, it gives me this-
bash: ./program: /usr/lib/ bad ELF interpreter: No such file or directory

I believe this is an error in the configuration of the linker. How to resolve it?

Offline Rob Neff

  • Forum Moderator
  • Full Member
  • *****
  • Posts: 429
  • Country: us
Re: Using scanf and linking it with ld
« Reply #1 on: April 17, 2014, 03:32:02 PM »
When using libc additional startup code is usually required.  To verify this try "compiling/linking" with gcc first:
Code: [Select]
gcc program_object_file.o -o program

Assuming that works for you then you need to identify the additional modules required for linking.
These are usually named something like crt1.o, crti.o, crtn.o and are normally found in /usr/lib/i386-gnu-linux or something similar depending on your configuration.

Offline Kunal

  • Jr. Member
  • *
  • Posts: 2
Re: Using scanf and linking it with ld
« Reply #2 on: April 18, 2014, 04:27:35 AM »
Thank you Rob.
That helped me; When I used gcc, the program linked and ran as expected.  :)
But I still want to link the object file using ld. I also want to know why I get that error and what those additional modules like crt1.o, crti.o, crtn.o signify?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Using scanf and linking it with ld
« Reply #3 on: April 18, 2014, 09:30:34 AM »
I used to get a similar error, but it didn't tell me which file it couldn't find. Just "bash: no such file or directory". Quite confusing, since my "program" was right there. Examination of the executable (just a text editor) showed the text "/lib/" which does not exist. The "--dynamic-linker" switch has a shorter alias "-I" (Interpreter). Telling ld "-I /lib/" solved it for me. Sounds like your setup may need "/usr" in there, as well, but probably something similar.

I'm told, but never tried it, that you can fix it by changing a line in a configuration file and rebuilding ld. It's part of the "binutils" package, not the "gcc" package. I don't know why it still defaults to a filename that apparently hasn't been used for quite a while. Balkward compatibility?

I would have expected, as Rob says, that we need that "startup code" if we're going to use the library routines. To my surprise, this seems not to be true. At the cost of typing a lengthy command line to ld, I seem to be able to use the libraries without the "startup code". There may be some massive bug waiting to bite me, but so far it "seems to work".

The flip side of this is that it doesn't cost much to let gcc link in "crt?.o", even if we don't actually need it. A couple of k, as I recall. No big deal. In return, gcc "knows where the bodies are buried" and knows how to tell ld what it wants, so we don't have to figure it out.

The "main" thing the startup code does for us is "call main". It contains the "_start" label. The _start label was not called, so there's no return address on the stack. The first thing on the stack is the argument count (always at least 1, the program name). Then, working up the stack, is a zero-terminated array of pointers to zero-terminated strings - your command line arguments. Then there's a zero-terminated array of pointers to environment variables (also zero-terminated strings) - no count of these. When "main" gets control, there's a return address, argc, and pointers to arrays of arguments and environment variables. There's an extra dereference involved to get at the stuff. There may be other things the startup code does for us, but that's what I know of that we need to be aware of. Source code is available, if you care enough.

We do need that interpreter/dynamic loader to use the libraries. If you "strace myprog" you can see it opening files and mmapping them like crazy. It's a busy little beaver before it gets to your code. In contrast, if you stick to system calls, your code gets executed right away. To get a float, it's worth the detour! :)