5

I am learning to analyze binaries using radare2 and have been confused about what occurs within imported functions. In the binary below, titled Lab2B, I statically disassembled the binary and then disassembled one of the imported library functions, sym.imp.printf. As you can see below it merely lists one instruction: jmp dword [reloc.printf]. When I seek to the location [reloc.printf] and I print the disassembled functions contained at it, the command line prints "Cannot find function at 0x0804a00c". I have noticed the same behavior with all of the other imported functions. They often have a single instruction that points to an address that doesn't contain any instructions.

Why are there no instructions contained at the address that the instruction tells the compiler to jump to?

enter image description here

5

I assume you are statically inspecting the program, hence, the addresses of the imported symbols wasn't calculated yet by the linker. To understand that better you need to get familiar with two terms, PLT and GOT. Anyway, even if you are debugging the file, these are not functiona but a table with pointers. So pdf isn't what you should try. Give a shot to pd.

Dynamic Linking

The Procedure Linkage Table is a memory structure that contains a code stub for external functions that their addresses are unknown at the time of linking.

Whenever we see a CALL instruction to a function in the .text segment it doesn’t call the function directly. Instead, it calls the stub code at the PLT, say func_name@plt. The stub then jumps to the address listed for this function in the Global Offset Table (GOT). If it is the first CALL to this function, the GOT entry will point back to the PLT which in turn would call a dynamic linker that will resolve the real address of the desired function. The next time that func_name@plt is called, the stub directly obtains the function address from the GOT.

To read more about the linking process, I highly recommend this series of articles about linkers by Ian Lance Taylor.


Radare2 is detecting the addresses of the PLT and GOT. Where you see sym.imp.printf it is actually the reserved address for printf() int the PLT. When you see reloc.printf is the address reserved for it in the GOT.

By using iS you can list the sections of PLT and GOT.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.