gcc - compile, generate assembly with inline source without calling objdump - gcc

I'm using gcc -save-temps to generate assembly and I added -fverbose-asm but that option does NOT generate what I want; it's some weird debug-ish comments.
To get the assembly + inline source, I'm doing gcc -g followed by objdump -S.
Since -save-temps generates the assembly anyway, is there a way to configure it to output the inline source that objdump -S produces?

The GNU C compiler (gcc) produces assembly output if you specify the option -S during compilation. Note that this output is not like the output of objdump -S in the source code is not interspersed with the assembly. To get such output, there is currently no way around creating an object file and then disassembling it. Consider filing a bug report if you would like to have such a feature.

Related

GCC flags to get LTO bitcode

I have been using LLVM/Clang and its Intermediate Representation(IR) for a while now.
I have recently started working with GCC. I want to dump IR bitcode to a file, similar to (-flto -save-temps flag) in LLVM.
I can get gimple IR using '-fdump-tree-cfg-raw' flag while building, but with multiple input files, this generates an a '.gimple' file for each source.
To get the view of the entire program, in LLVM, I used '-flto -Wl,-plugin-opt=save-temps' in LDFLAGS. What is the correct way of getting the same behavior in GCC.
I tried using 'gcc -fdump-tree-cfg-raw -flto -save-temps src1.c main.c', but I do not get the combined IR file. The outputs include .o,.s,.i files for each source and .cfg file for each.
You don't see the merged file because this pass was not executed by lto. All the passes executed by cc1 are not necessarily executed by lto. A solution could be to use fdump-tree-all option
gcc -flto -fdump-tree-all -o exec x.c y.c
you will get all the gimple files for the entire program. For each pass executed you will get exec.ltrans.xxxt.pass_name . Otherwise, if you don't want to use fdump-tree-all you must be sure that the pass you want to dump will be executed by the lto.

Getting assember output from GCC/Clang in LTO mode

Normally, one can get GCC's optimized assembler output from a source file using the -S flag in GCC and Clang, as in the following example.
gcc -O3 -S -c -o foo.s foo.c
But suppose I compile all of my source files using -O3 -flto to enable link-time whole-program optimizations and want to see the final compiler-generated optimized assembly for a function, and/or see where/how code gets inlined.
The result of compiling is a bunch of .o files which are really IR files disguised as object files, as expected. In linking an executable or shared library, these are then smushed together, optimized as a whole, and then compiled into the target binary.
But what if I want assembly output from this procedure? That is, the assembly source that results after link-time optimizations, during the compilation of IR to assembly, and before the actual assembly and linkage into the final executable.
I tried simply adding a -S flag to the link step, but that didn't really work.
I know disassembling the executable is possible, even interleaving with source, but sometimes it's nicer to look at actual compiler-generated assembly, especially with -fverbose-asm.
For GCC just add -save-temps to linker command:
$ gcc -flto -save-temps ... *.o -o bin/libsortcheck.so
$ ls -1
...
libsortcheck.so.ltrans0.s
For Clang the situation is more complicated. In case you use GNU ld (default or -fuse-ld=ld) or Gold linker (enabled via -fuse-ld=gold), you need to run with -Wl,-plugin-opt=emit-asm:
$ clang tmp.c -flto -Wl,-plugin-opt=emit-asm -o tmp.s
For newer (11+) versions of LLD linker (enabled via -fuse-ld=lld) you can generate asm with -Wl,--lto-emit-asm.

How is C++ compiled

I am working on some (very) low level programming but not everything is completely clear to me. I start by creating a .cpp (or .c) file which is run through gcc to create an elf or object file but what is an object file? I get object files when I use the "as" compiler but how are these used and what is the purpose of having an object file when we could have a straight binary?
There is a very clear explanation of this question on the this site. I pasted it down below as well. But I strongly suggest you take a look at the diagram on the website. That will give you a much better high-level understanding of what is going on.
Compiling a source code file in C++ is a four-step process. For example, if you have a C++ source code file named prog1.cpp and you execute the compile command
g++ -Wall -ansi -o prog1 prog1.cpp
the compilation process looks like this:
The C++ preprocessor copies the contents of the included header files into the source code file, generates macro code, and replaces symbolic constants defined using #define with their values.
The expanded source code file produced by the C++ preprocessor is compiled into the assembly language for the platform.
The assembler code generated by the compiler is assembled into the object code for the platform.
The object code file generated by the assembler is linked together with the object code files for any library functions used to produce an executable file.
By using appropriate compiler options, we can stop this process at any stage.
To stop the process after the preprocessor step, you can use the -E option:
g++ -E prog1.cpp
The expanded source code file will be printed on standard output (the screen by default); you can redirect the output to a file if you wish. Note that the expanded source code file is often incredibly large - a 20 line source code file can easily produce an expanded file of 20,000 lines or more, depending on which header files were included.
To stop the process after the compile step, you can use the -S option:
g++ -Wall -ansi -S prog1.cpp
By default, the assembler code for a source file named filename.cpp will be placed in a file named filename.s.
To stop the process after the assembly step, you can use the -c option:
g++ -Wall -ansi -c prog1.cpp
By default, the assembler code for a source file named filename.cpp will be placed in a file named filename.o

How to generate symbol table with arm gcc

I would like to create a symbol definition table to be used in a separate application during linking. ARM's armlink linker has the following flag but I'm using arm-eabi:
--symdefs=filename
The GNU objcopy utility has an option --extract-symbol that may do what you want. It generates an object file with only symbol data - no actual code or data.
It is specifically intended to generate a .sym file for use in the VxWorks RTOS which has a command shell and dynamic linker/loader that uses this information. It is also used by the VxWorks host shell and source-level debugger.
The binutils nm utility on the other hand generates output very similar to armlink's --symdefs which you might easily post-process into exactly the form you need.
-Wl,-Map -Wl,mapfile -Wl,--cref
added to the final gcc (link) command line should do the trick.
This the correct answer from arm gnu launchpad:
Do you intend to load the symdef file with the GNU toolchain or with armcc one? If the former I think using nm on the object file and then linking with -R <filename> would work. So you would do arm-none-eabi-nm -D ./prog > ./prog.defsym after linking prog and then arm-none-eabi-gcc -Wl,-R,./prog.defsym when you want to use this.

gnu arm assembler command line macro fails with "Invalid identifier for .ifdef"

My toolchain is a recent version of arm-gcc.
I have a piece of code in an assembly file which must be conditionally included/assembled.
.ifdef MACRO_FROM_CMDLINE
Assembly instr1
Assembly instr2
.endif
Encapsulated code is a recent addition.
I have tried both:
gcc -x assembler-with-cpp --defsym MACRO_FROM_CMDLINE=1 <along with other necessary options>
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 <along with other necessary options>
The -D results in "Invalid identifier for .ifdef " and ".endif without .if" errors.
The --defsym results in "MACRO_FROM_CMDLINE=1 : No such file or directory", "unrecognized option --defsym" errors.
The gcc binary drives the compilation process by invoking a number of other programs in sequence to actually perform the various stages of work (compiling, assembling, linking).
When you say:
gcc -x assembler-with-cpp -D MACRO_FROM_CMDLINE=1 ...
you are asking it to run the source through the C preprocessor, and then run the result through the assembler.
The C preprocessor step will turn:
.ifdef MACRO_FROM_CMDLINE
into:
.ifdef 1
before passing it to the assembler, which then can't make sense of it. This is why you get the "invalid identifier" error. It also explains why using C preprocessor #ifdef fixes the problem.
--defsym doesn't work because it's an option to the assembler, not the gcc driver program. (The gcc driver does understand and pass through some options to some of the programs it invokes, but not all.)
You can, however, pass arbitrary options through to the assembler using the
-Wa,option[,option...]
syntax, which tells the gcc driver to pass those option(s) through to the assembler (as a list of space-separated options).
For example:
gcc -x assembler-with-cpp -Wa,--defsym,MACRO_FROM_CMDLINE=1 ...
adds
--defsym MACRO_FROM_CMDLINE=1
to the list of options passed to as when gcc invokes it, and that's how to make your original .ifdef example work.
You can see the individual programs invoked by gcc, and the options it actually passes to them, by adding the -v option.
In this case, you should see something called cc1 (the actual GCC C compiler binary) invoked with the -E flag (preprocess only) to preprocess the input to a temporary file, and then as invoked on the temporary file to assemble it.
Strange, but it it turns out I needed to use the C syntax in the assembly file.
#ifdef MACRO
Assembly Instruction
Assembly Instruction
#endif
And the macro had to be passed using the -D option.

Resources