How to check if a macro exists in an object file in C? - c

For example, I define a macro:
#ifdef VERSION
//.... do something
#endif
How can I check if VERSION exist in my object file or not? I tried to disassemble it with objdump, but found no actual value of my macro VERSION. VERSION is defined in Makefile.

Try compiling with -g3 option in gcc. It stores macro information too in the generated ELF file.
After this, if you've defined a macro MACRO_NAME just grep for it in the output executable or your object file. For example,
$ grep MACRO_NAME a.out # any object file will do instead of a.out
Binary file a.out matches
Or you can even try,
$ strings -a -n 1 a.out | grep MACRO_NAME
-a Do not scan only the initialized and loaded sections of object files;
scan the whole files.
-n min-len Print sequences of characters that are at least min-len characters long,
instead of the default 4.

The following command displays contents of .debug_macro DWARF section:
$ readelf --debug-dump=macro path/to/binary
or
$ objdump --dwarf=macro path/to/binary
You can also use dwarfdump path/to/binary, but it's not easy to leave only .debug_macro section in the output.

Related

How to see the instructions inside of compiled language executable files?

When i compile a C/C++ source file the compiler generates another executable file. How to see the instructions of that file? What is the process known as?
gcc hello.c -o hello
./hello
Here, the first after executing the first line a file name 'hello' gets generated. I need to see the instructions of this 'hello' file.
The executable a.out file is in binary format.
You can open that in any text editor(Ex: vi, vim etc) or hex editor but you won't be able to understand the contents.
You can use some commands to get more information about what is contained in the executable file.
Some example commands are: nm, strings, objdump
Example:
$ nm a.out
$ strings a.out
$ objdump -xD --demangle a.out
Read their manual to know more about them

What is the difference between executable files?

I have the following C program:
#include<stdio.h>
int main()
{
printf("hhhh");
return 0;
}
Commands to compile, copy and compare:
$ gcc print.c -o a.out
$ objcopy a.out b.out
$ cmp a.out b.out
I have compiled this program and created an executable. Then, I have used the objcopy command to make a copy of the executable. But, when I compare these files, I get this:
files differ: byte 41, line 1
How can I know what contents are missing?
Any help or pointers would be appreciated. Thanks!
How can I know what contents are missing?
What made you believe that any contents is missing?
The way objcopy works is:
parse the contents of the input file into internal representation.
copy parts of the original file to the output file as instructed by options
Nowhere does objdump guarantee that when "copy entire file" is given, the result will be bit-identical.
In particular, non-loadable sections could be reordered or changed in other ways.
The difference is EntSize of .init_array section is 0 bytes in a.out file and it is 8 bytes in the b.out
The EntSize of 0 doesn't make sense for a non-empty section. If you really have such section in your a.out, it's likely that your linker has a bug.

Can I use Preprocessor Directives in .ld file

Can I use Preprocessor Directives in .ld file?
I need to to use one of two sets of .ld file and wants to let Build engine deside that using macro, Can I do that?
Yes, you can. You need to run preprocessor manually for your linker script, like this:
in="your_linker_script.ld"
out="generated_script.ld"
cflags=-Iinclude/
gcc -E -P -x c $cflags $in >$out
Flags:
-E specifies GCC to only run preprocessor
-P prevents preprocessor from generating linemarkers (#line directives)
-x c tells GCC to treat your linker script as C source file (it's needed to run GCC with your LD script)
Or you can simply use cpp tool, which is actually C preprocessor.
After this you will be able to use generated linker script to build your program (e.g. in Makefile).
Example
Here is how I solved this problem in my project:
Here is my linker script uses preprocessor (#include directive and CONFIG_TEXT_BASE constant). Excerpt:
#include <config.h>
. = CONFIG_TEXT_BASE;
Here is script to generate preprocessed linker script. Excerpt:
gcc -E -P -x c -Iinclude $cflags $in >>$out
Here is my Makefile, it's generating preprocessed linker script at $(LDS_GEN) target (line 53) and the this generated script is being used to build result binary (line 42). Excerpt:
$(LDS_GEN): $(LDS)
build/gen-lds.sh $(LDS) $(LDS_GEN) $(CFLAGS)
$(APP).bin: $(OBJS) $(LDS_GEN)
$(LD) $(OBJS) -T $(LDS_GEN) -o $(APP).elf
Small update after long time. This way of pre-processing works until the memory file does not contain lines that are fooling the pre-processor. E.g.:
"KEEP(*path/*.o(.rodata .rodata*))"
The "/*" after path is considered comment start (the line contains what is considered a C multi-line comment start and not a match pattern).
This line is valid for the linker but it is considered comment and the output from C pre-processor will remove everything till a supposed closing comment is found:
"KEEP(*path"
The resulting file is clearly invalid for the linker. I have no solution at the moment.
As a simplification of Sam's answer, I added the below to my makefile and away we go :)
PRE_LD_FILE = $(PROG_NAME).ld
LD_FILE = $(PROG_NAME)_generated.ld
$(LD_FILE) : $(PRE_LD_FILE)
cpp $(PRE_LD_FILE) | grep -v '^#' >>$(LD_FILE)

Where do we use .i files and how do we generate them?

I was going through the GCC man page, I found the following line:
file.i
C source code that should not be preprocessed.
I know that running gcc -E foo.c stops the compiler after preprocessing;
but what is the real world application of creating .i files.
Also is there a way of generating a .i files other than gcc foo.c -E > foo.i?
The .i files are also called as "Pure C files". In preprocessing stage
Header files will be included.
Macros will be replaced.
Comments are removed.
Used for conditional compilation.
If you look at the .i file you can see these things.
Command to generate .i file is-
gcc -E foo.c -o foo.i
A file.i file is:
C source code that should not be preprocessed.
Source: man gcc then press the / key to search, and search for "\.i".
Detailed Steps: man gcc, then press the / key to search, then type in \.i, then press the Enter key, then press the n key repeatedly until you find it.
What this means is that a .i file is preprocessed source code, so it has already been preprocessed. Therefeore, it already contains:
all header files included
macros replaced
and comments removed
...as stated by #Sathish in his answer.
You'll also notice a ton of special "comments" added by gcc that now begin with the # character, such as these:
# 1 "main.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.c"
# 44 "main.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 374 "/usr/include/features.h" 3 4
# 1 "/usr/include/x86_64-linux-gnu/sys/cdefs.h" 1 3 4
I don't know what those are nor what they do. Someone please tell me if you know.
Note that a simple program such as this:
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
Compiled with this:
gcc -Wall -std=c99 -O0 -save-temps=obj main.c -o ./bin/main
Will produce a main.i file that is about 682 lines long, with the main() function shown above being right at the very end.
How to generate all intermediate files, including the .i files:
My preference is to generate all intermediate files (.i, .o, .s, rather than just the .i file using -E) all at once in a local bin folder in the project by using the gcc -save-temps=obj option like this:
mkdir bin
gcc -save-temps=obj foo.c -o ./bin/foo
Now you have the following files in the "foo/bin" directory:
foo # compiled binary program (AKA: combined "object file",
# "executable", "binary", "program", or "machine code")
foo.i # intermediate, preprocessed C file
foo.o # individual object file
foo.s # assembly file
Run the program of course with:
./bin/foo
Notes about "object files" and "executables"
Note that the final output, the foo executable file, is called the "compiled binary program", "program", (combined) "object file", "executable", "binary", or just "machine code", or "ones and zeros" (10101010). It is an object file in object file format, as are the individual *.o object files which are combined into one by the linker to create it. The linker combines all *.o object files into one in order to make the final foo executable, or combined object file.
The GNU linker (ld) manual states it as follows. See section "3.1 Basic Linker Script Concepts": https://sourceware.org/binutils/docs/ld/Basic-Script-Concepts.html#Basic-Script-Concepts (emphasis added, as well as content in square brackets []):
3.1 Basic Linker Script Concepts
We need to define some basic concepts and vocabulary in order to describe the linker script language.
The linker combines input files [individual *.o object files] into a single output file. The output file and each input file are in a special data format known as an object file format. Each file is called an object file. The output file is often called an executable, but for our purposes we will also call it an object file. Each object file has, among other things, a list of sections. We sometimes refer to a section in an input file as an input section; similarly, a section in the output file is an output section.
For more info. on object files, you can also see two of my other answers here:
How do I find out at compile time how much of an STM32's Flash memory and dynamic memory (SRAM) is used up?
Convert binutils `size` output from "sysv" format (`size --format=sysv my_executable`) to "berkeley" format (`size --format=berkeley my_executable`)

How can I tell if a library was compiled with -g?

I have some compiled libraries on x86 Linux and I want to quickly determine whether they were compiled with debugging symbols.
If you're running on Linux, use objdump --debugging. There should be an entry for each object file in the library. For object files without debugging symbols, you'll see something like:
objdump --debugging libvoidincr.a
In archive libvoidincr.a:
voidincr.o: file format elf64-x86-64
If there are debugging symbols, the output will be much more verbose.
The suggested command
objdump --debugging libinspected.a
objdump --debugging libinspected.so
gives me always the same result at least on Ubuntu/Linaro 4.5.2:
libinspected.a: file format elf64-x86-64
libinspected.so: file format elf64-x86-64
no matter whether the archive/shared library was built with or without -g option
What really helped me to determine whether -g was used is readelf tool:
readelf --debug-dump=decodedline libinspected.so
or
readelf --debug-dump=line libinspected.so
This will print out set of lines consisting of source filename, line number and address if such debug info is included into library, otherwise it'll print nothing.
You may pass whatever value you'll find necessary for --debug-dump option instead of decodedline.
What helped is:
gdb mylib.so
It prints when debug symbols are not found:
Reading symbols from mylib.so...(no debugging symbols found)...done.
Or when found:
Reading symbols from mylib.so...done.
None of earlier answers were giving meaningful results for me: libs without debug symbols were giving lots of output, etc.
nm -a <lib> will print all symbols from library, including debug ones.
So you can compare the outputs of nm <lib> and nm -a <lib> - if they differ, your lib contains some debug symbols.
On OSX you can use dsymutil -s and dwarfdump.
Using dsymutil -s <lib_file> | more you will see source file paths in files that have debug symbols, but only the function names otherwise.
You can use objdump for this.
EDIT: From the man-page:
-W
--dwarf
Displays the contents of the DWARF debug sections in the file, if
any are present.
Answers suggesting the use of objdump --debugging or readelf --debug-dump=... don't work in the case that debug information is stored in a file separate from the binary, i.e. the binary contains a debug link section. Perhaps one could call that a bug in readelf.
The following code should handle this correctly:
# Test whether debug information is available for a given binary
has_debug_info() {
readelf -S "$1" | grep -q " \(.debug_info\)\|\(.gnu_debuglink\) "
}
See Separate Debug Files in the GDB manual for more information.
https://access.redhat.com/documentation/en-us/red_hat_enterprise_linux/6/html/developer_guide/debugging
The command readelf -wi file is a good verification of debuginfo, compiled within your program.

Resources