Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Difference between printf@plt and puts@plt

Tags:

c

disassembly

I've been learning assembly language by disassembling some C code. When I disassemble this basic C code with GDB:

#include <stdio.h>
void main(void) {
    printf("Hello World\n");
}

Among assembly code, it gives this line:

0x08048424 <+25>:   call   0x80482e0 <puts@plt>

However, when I disassemble below code which has an integer in printf function:

#include <stdio.h>
void main(void) {
    int a = 1;
    printf("Hello Word %d\n", a);
}

It gives this line:

0x0804842e <+35>:   call   0x80482e0 <printf@plt>

What is the difference between printf@plt and puts@plt?

Why disassembler does not recognize printf function without an integer parameter?

like image 281
Berat Postalcioglu Avatar asked Aug 17 '16 22:08

Berat Postalcioglu


People also ask

What does puts plt do?

PLT means Procedure Linkage Table. It is a special technique used in ELF files to localize fixing up at load time on machines where relative addressing is available. The function you're calling is located in another module (typically, libc.

What does puts do in assembly?

The big difference between the two functions, at the assembly level, is that the puts() function will just take one argument (a pointer to the string to display) and the printf() function will take one argument (a pointer to the format string) and, then, an arbitrary number of arguments in the stack ( printf() is a ...

What is @PLT in assembly?

The PLT is the procedure linkage table, one of the structures which makes dynamic loading and linking easier to use. printf@plt is actually a small stub which (eventually) calls the real printf function, modifying things on the way to make subsequent calls faster.


2 Answers

In GCC printf and puts are built-in functions. Which means that the compiler has full knowledge of their semantics. In such cases the compiler is free to replace a call to one function with an equivalent call to another, if it thinks that it will produce better (faster and/or more compact) code.

puts is a generally more efficient function since it does not have to parse and interpret a format string.

This is exactly what happened in your case. Your first call to printf does not really need any printf-specific features. The format string you supplied to printf is trivial: it has no conversion specifiers in it. The compiler thought that your first call to printf is better served with an equivalent call to puts.

Meanwhile, your second call to printf makes non-trivial use of printf format string, i.e. it relies on printf-specific features.

(Some rather thorough research of this specific matter from 2005: http://www.ciselant.de/projects/gcc_printf/gcc_printf.html)

like image 129
AnT Avatar answered Sep 21 '22 17:09

AnT


I don't know about the @plt part, but printf and puts are simply two different standard library functions. printf takes a format string and zero or more other parameters, possibly of different types. puts takes just a string and prints it, followed by a newline. Consult any C reference for more information, or type

man 3 printf
man 3 puts

assuming you're on a Unix-like system with man pages installed. (man printf without the 3 will show you the printf command; you want the printf function.)

Your compiler is able to optimize the call

printf("Hello, world\n");

to the equivalent of:

puts("Hello, world");

because it knows what both functions do, so it can determine that they do exactly the same thing.

It can't optimize

printf("Hello Word %d\n", a);

because the value of a is unknown at compile time, so it doesn't print a fixed string. (It might figure it out at higher optimization levels by observing that a is never modified after its initialization).

The disassembler is merely showing you the code generated by the compiler.

(Incidentally, void main(void) is incorrect; use int main(void).)

like image 39
Keith Thompson Avatar answered Sep 20 '22 17:09

Keith Thompson