Ubuntu: How to link a binary
Ubuntu sets your PATH environment variable to include ~/bin
. So the easiest way to make xyz
executable from anywhere is move xyz
to ~/bin
, or to make a symlink from ~/bin to the xyz
's directory:
ln -s /path/to/xyz/directory/ ~/bin
Or, you could add /path/to/xyz/directory/
to your PATH environment variable.
How can I change the binary file link to something else
The command run when you type python
is determined primarily by the setting of your $PATH
. The first executable file called python
that is found in a directory listed on your $PATH
will be the one executed. There is no 'link' per se. The which
command will tell you what the shell executes when you type python
.
If you want python
to open a different program, there are a number of ways to do it. If you have $HOME/bin
on your $PATH
ahead of /usr/bin
, then you can create a symlink:
ln -s /usr/bal/bla/python2.7 $HOME/bin/python
This will now be executed instead of /usr/bin/python
. Alternatively, you can create an alias:
alias python=/usr/bal/bla/python2.7
Alternatively again, if /usr/bal/bla
contains other useful programs, you could add /usr/bal/bla
to your $PATH
ahead of /usr/bin
.
There are other mechanisms too, but one of these is likely to be the one you use. I'd most probably use the symlink in $HOME/bin
.
Link libraries to linux biinary file in c++
That's because the dynamic linker loading runtime dependencies looks for them in some specified locations, which are "by default" your system library directories (where those libraries got installed by apt
).
The other user should ideally install those libraries too (which could be done "automatically" if you build a .deb package with proper dependencies)
Otherwise you would have to change the runpath of your program by adding -Wl,-rpath='$ORIGIN'
, which makes the dynamic linker look for dependencies just where the binary is located.
$ORIGIN
here is a special variable meaning "this executable" which is what you wanted to achieve.
see rpath
and A description of RPATH $ORIGIN
Why do I have to use ld to link my binary
Why do I have to use the linker ld?
You don't have to use ld
, but it's much easier to use it than not (see below).
What exactly is wrong with the bin file?
Nothing in the .bin
file tells the OS how to load and run it.
At what address should the OS map this file into memory? Where should it set the RIP
register to start executing it?
When you create a program which will run on a "bare metal" system, you can arrange for this program to be loaded at exactly the processor reset address, and the processor will start fetching and executing instructions from that address when it is powered on.
But you aren't trying to do that -- you are using Linux, and it needs to be told where to load the program and how to start it.
Usually this info is supplied by the ELF
file header and program headers (which the linker prepares), although Linux can execute other file formats as well.
Can I do something to make it run without ld?
Sure. You can supply all the ELF
header and program header bits without involving a linker at all. Example. It's just much harder to do correctly, and to debug when things go wrong.
Linux linking to any available library version
In the magical Linux world it is very difficult to compile and link on one machine and then copy the binary to another machine and run it there. There are a lot of variations, as you have also experienced not all aer compatible with each other, so this make the porting of binaries very difficult, if not altogether impossible. It might work with some setups, and not with others. Now you have two possibilities:
I assume, your 12.04 is a production environment so you cannot do whatever you want... So, in this case create an identical (virtual) machine to the Ubuntu 12.04 compile and link on it. Copy the executable to the 12.04 you need to run on it. Chances are that it will work without problems.
If the assumption about the production environment is not true, then install the compilers and necessary environment and compile the source on the remote machine. This way you will know it will work all the time on that machine.
How can I link dynamically to glibc in Ubuntu
ld
's default dynamic linker for i386 is /usr/lib/libc.so.1
, which is wrong on most Linux systems today. You did try to override it, but the path you gave wasn't right either. Two options:
- Manually pass the right one when you link:
ld hello.o -o hello -dynamic-linker /lib/ld-linux.so.2 -lc -m elf_i386
- Use
gcc
to link instead, as fuz mentioned:gcc -nostartfiles -m32 -o hello hello.o
If you're curious how I knew what the right dynamic linker was for option 1, I did it by doing option 2 once first and checking which one it used.
See also Red Hat's Bug 868662 - /lib/ld64.so.1: bad ELF Interpreter: No such file or directory, someone else who had basically the exact same problem you did (but they got a more helpful error message than you did for some reason).
Edit: there's two other potential problems with your code, that could cause problems in real code but just happened not to in this tiny example:
First, as Employed Russian pointed out in a comment, glibc expects that its own initialization code from its crt
will run before your application code starts calling its functions. You were lucky; since you made a dynamically-linked binary, the dynamic linker's use of glibc resulted it in it being initialized for you. Had you made a statically-linked binary instead, it wouldn't have worked. To avoid relying on the dynamic linker that way, the easiest solution is to use main
as your entry point instead of _start
, and then use gcc -m32 -o hello hello.o
to link (note we're not using -nostartfiles
anymore). In theory you could still use ld
directly to link, but it's complicated enough to get right that there's basically no reason to bother.
Second, you're not aligning the stack correctly. You need to make sure it's aligned to a 16-byte boundary before you call
other functions. At the beginning of _start
(if you still use that for some reason), the stack will already be aligned like that, so you just have to maintain it. At the beginning of main
or any other function, the 4-byte return address will have gotten pushed, so you'd need to push 12 more bytes to realign it.
With both of the above fixes, here's your new hello.asm
:
;hello.asm
global main
extern scanf, printf, exit
section .data
read_name db '%255s', 0
msg db 'Hello, %s', 0
section .text
main:
sub esp, 260 ; the 4 extra bytes here are padding for alignment. If you wanted to get value out of them, you could use %259s instead of %255s now
push esp
push read_name
call scanf
add esp, 8
push esp
push msg
call printf
add esp, 260 ; we pushed 268 bytes so far, but I'm leaving 8 bytes for alignment
push dword 0
call exit
Also, now that you're using main
and not _start
, you can just return from it instead of calling exit
. You just need to make sure you put the stack pointer back where it was at the beginning. To do that, replace everything after call printf
with this:
add esp, 268
xor eax, eax
ret
Final note: if you're wondering why I did xor eax, eax
and not mov eax, 0
, see What is the best way to set a register to zero in x86 assembly: xor, mov or and?.
Related Topics
Linux: Disable Using Loopback and Send Data via Wire Between 2 Eth Cards of One Comp
Differences Between Arm "Versions" (Armv7 Only)
How to Use Systemd to Restart a Service When Down
Os X Permission Denied for /Usr/Local/Lib
Capture Stdin/Stderr/Stdout of a Process After It's Been Started, Using Command Line
How to Translate X11 Keycode Back to Scancode or Hid Usage Id Reliably
Substituting a String in Place of Variable in Shell
Amazon Ec2 Lost Private Key, How to Get Access to The Server
Recommended Irc Server (Ircd) for a Small Site
Qemu on Raspberry Pi Arch Linux Latest Sd Image
Stdin into Zip Command, How to Specify a File Name
Finding The Max and Min Values and Printing The Line from a File
Is There a 'ssh-Add' Linux Alpine One Liner
Any Good Guides on Using Ptrace_Sysemu
Calculate Total Disk I/O by a Single Process