Bootloader issues due to GCC-4.7.0 - gcc

This is a weird problem. I am having a custom bootloader for MIPS 34Kc processor which was consistently booting my target. This was compiled with GCC-4.2.4. Recently we had moved to GCC-4.7.0 and the bootloader is failing to boot the target all the time.
The optimizations are as below:
W_OPTS = -Wimplicit -Wformat -Werror
CC_OPTS = -c -O -mips32r2 $(W_OPTS) -fomit-frame-pointer -fno-pic -nostdinc -mno-abicalls
CC_OPTS_16 = -c -O -mips16 $(W_OPTS) -fomit-frame-pointer -fno-pic -nostdinc -mno-abicalls
CC_OPTS_A = $(CC_OPTS) -D_ASSEMBLER_
Any pointers to debug this issue would be helpful.

Related

i686-elf-gcc not creating output file (kernel.o)

I was following the osdev barebones tutorial and successfully created boot.o and linker.ld, but ran into a problem when the i686-elf-gcc compiler didn't create the kernel.o file. It gave no errors. This is what I ran to compile it:
i686-elf-gcc -c kernel.c -o kernel.o -std=gnu99 -ffreestanding -O2 -Wall -Wextra
But no matter how many times I do it, there's still no kernel.o!

Stripping unused library functions / dead code from a static executable

I'm compiling code for an ARM Cortex-M0 mcu with GCC arm-none-eabi-g++ (4.8.3).
All is fine, but I noticed that when I include and use any function from cstdlib, all functions from that file are included as well. How to get rid of them?
I'm calling malloc() and free() only, but the resulting ELF has system() and isatty() machine code as well.
The mcu has only 32kB flash, so ~0.7kB ballast matters, especially if this keeps happening for other headers.
Right now I use -ffunction-sections -fdata-sections for compiling and -Wl,--gc-sections -Wl,--static while linking, as follows:
arm-none-eabi-g++ -c --std=c++11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -fno-exceptions -o main.o main.cpp
arm-none-eabi-gcc -c --std=c11 -Os -I. -Ilpc1xxx -Idrivers -Wall -mthumb \
-ffunction-sections -fdata-sections -fmessage-length=0 -mcpu=cortex-m0 \
-DTARGET=LPC11xx -fno-builtin -flto -o core_cm0.o lpc1xxx/nxp/core_cm0.c
arm-none-eabi-gcc -nostartfiles -mcpu=cortex-m0 -mthumb -Wl,--gc-sections -flto \
-Os -Wl,--static -T lpc1xxx/memory.ld -o firmware.elf main.o core_cm0.o \
libaeabi-cortexm0/libaeabi-cortexm0.a LPC11xx_handlers.o LPC1xxx_startup.o
Edit: Warning: The -flto flag in my example is wrong – somehow it discards interrupt routines.
The result is that when I do arm-none-eabi-objdump -t firmware.elf, I get among others:
00000fbc g F .text 0000002c _isatty
00001798 g F .text 00000018 fclose
00000e4c g F .text 00000030 _kill
00000e7c g F .text 00000018 _exit
00000fe8 g F .text 00000050 _system
These functions are clearly redundant (and quite useless on mcu at all), yet GCC keeps them in the executable. There are no calls to them, these symbols are not referenced anywhere. It's effectively dead code.
How to get rid of them? Some extra compiler/linker flags?
Edit:
Minimal code to reproduce my problem:
#include <cstdlib>
int main(){
[[gnu::unused]] volatile void * x = malloc(1);
return 0;
}
Command used to compile that:
arm-none-eabi-g++ --std=c++11 -Os -Wall -mthumb -ffunction-sections
-fdata-sections -fmessage-length=0 -mcpu=cortex-m0 -fno-builtin -flto
-fno-exceptions -Wl,--static -Wl,--gc-sections -o main.elf main.cpp
And the main.elf file still has all stdlib bloat.
Using -ffunction-sections is the right thing here, but the issue is that the object file that provides malloc and free is built without it (either LPC11xx_handlers.o, LPC1xxx_startup.o or some of the object files within libaeabi-cortexm0.a). In that case, the linker can only include the whole object file (or with -Wl,--gc-sections, the whole section) that contain functions you need.
The layout of functions in object files and sections is the only thing that actually matters, not which function is defined in the same header as another function.
So to fix your issue, rebuild your standard library files with -ffunction-sections -fdata-sections.

Negate previous -D[efine] flag for GCC

Under GNUStep on Arch Linux, I'm running into an interesting error on a fresh install.
Using my build system I run
gcc `gnustep-config --debug-flags` [other command line args]
in order to build up the command line per the operating system's necessary flags.
This works fine under Ubuntu, but on Arch Linux I'm getting a rather random error:
/usr/include/features.h:328:4: error: #warning _FORTIFY_SOURCE requires compiling with optimization (-O) [-Werror=cpp]
Well, gnustep-config --debug-flags spits out the following:
-MMD -MP -D_FORTIFY_SOURCE=2 -DGNUSTEP -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGNUSTEP_BASE_LIBRARY=1 -fno-strict-aliasing -pthread -fPIC -g -DDEBUG -fno-omit-frame-pointer -Wall -DGSWARN -DGSDIAGNOSE -Wno-import -march=x86-64 -mtune=generic -pipe -fstack-protector-strong --param=ssp-buffer-size=4 -fgnu-runtime -fconstant-string-class=NSConstantString -fexec-charset=UTF-8 -I. -I/home/qix/GNUstep/Library/Headers -I/usr/include -D_FORTIFY_SOURCE=2 -I/usr/include -I/usr/include -I/usr/include -I/usr/lib/libffi-3.1/include/ -I/usr/lib/libffi-3.1/include -I/usr/include/libxml2 -I/usr/include/p11-kit-1
As well, I wish not to have optimizations on my debug builds (and later on I even override GNUStep's -g parameter to -g2).
Is there a way to explicitly undefine -D_FORTIFY_SOURCE later on in the command line, after the call to gnustep-config?
For example, something like
gcc `gnustep-config --debug-flags` -U_FORTIFY_SOURCE ...
where the -U undefines the previously defined macro?
Something to mention; I have -Werror enabled on purpose, and I'd like to keep it.
For now, using sed to work around this works. It appears this is a known issue with _FORTIFY_SOURCE causing issues, and there isn't a straightforward fix.
`gnustep-config --debug-flags | sed 's/-D_FORTIFY_SOURCE=2//g'`

About -ffunction-sections -fdata-sections and --gc-sections options

In my ARM project, I use following to build os-less application binary:
arm-linux-gcc -Os -ffunction-sections -fdata-sections -o boot.o boot.S
arm-linux-gcc -Os -ffunction-sections -fdata-sections -o main.o main.c
arm-linux-ld -T link.lds --gc-sections -o target.bin boot.o main.o
These works fine. Because If I remove "-ffunction-sections", "-fdata-sections" and "--gc-sections" options, the target.bin file size will increase nearly twice..
But on the x86 platform, same method, I found that:
If I don't use those gcc and ld options, the output is normal, but the output file will be 0 byte if I use those options as arm platform.
-Os -ffunction-sections -fdata-sections and --gc-sections should work on x86 system. Are you sure your program and your linker script are suitable for x86 ? As your program is meant for bare-metal ARM, it probably does not have entry points for your x86 OS, and if there is no entry point, everything is garbaged by --gc-sections option.
BTW, your "question" actually enclose no question.

Compile Linux Kernel Modules into LLVM .bc bitcode

Background
I'm trying to compile certain drivers within the Linux kernel: drm (drivers/gpu/drm/drm_drv.o) and radeon (drivers/gpu/drm/radeon/) gpu drivers. I'm using LLVM for the purposes of static analysis (tracking the arguments used in copy_to/from_user() invocations).
So far, I'm able to compile the actual modules using the Makefile as shown below:
make CC=clang CFLAGS=-emit-llvm drivers/gpu/drm/radeon/
But this does not actually emit any llvm bitcode -- I need the .bc files to run my pass with opt.
I only know how to generate .bc files when using clang directly (like below), but not with Makefiles...
clang -emit-llvm hello.c -c -o hello.bc
Since that worked, I grabbed the verbose output of the GNU make operation, changed gcc to clang, and ran it to create the .bc file, which also worked:
clang -emit-llvm [[tons of CFLAGS]] -c -o drm_drv.bc drivers/gpu/drm/drm_drv.c
The only problem with that is I can only process a single C file in the kernel module at a time. Also it's very tedious to do this approach...
Main Problem
Which brings me to my main question: How would you go about emitting llvm .bc bitcode files using the kernel's Makefiles?
Or, if .bc bitcode creation must be done on a per-file basis, then how would I link them all together at the end so that I can run an LLVM opt pass on the aggregate of all the .bc files in a kernel module?
The best way to get LLVM IR in bitcode form out of Clang is to do LTO with the -flto command line flag.
If you have multiple translation units you can combine them together using the llvm-lto tool to "link" the bitcode files. Typically it generates code, but you can get it to drop the merged LLVM IR module with the -save-merged-module flag.
But none of this is really a supported interface. If this is a significantly useful workflow, you should talk to the LLVM developers about supporting something more akin to ld's -r.
I used clang to instrument ext2 module. There are 3 things that you want to do:
1) convert .c into .bc
2) run your optimiser on .bc file, and create an ext2-opt.o file
3) create ext2-instrumented.ko file from the ext2-opt.o file.
along with this, you also require a linux version compiled with clang. I could get linux 4.17 compiled with clang version 3.8.1 after disabling few modules. you can get it here
now, lets move to step 1 - as you said, run Make in verbose mode
make V=1 M=fs/ext2
and grab all options that are spit out by Makefile. the default compiler will be gcc. replace gcc with clang, add --emit-llvm command, and replace .o with .bc. the resultant compilataion command on my machine looks like so:
cd ../../ && clang -emit-llvm -Wp,-MD,fs/ext2/.all.o.d -nostdinc -isystem /usr/local/bin/../lib/clang/3.8.1/include -I./arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -Iinclude -I./arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -Qunused-arguments -Wno-unknown-warning-option -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -no-integrated-as -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -O2 -Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-variable -Wno-format-invalid-specifier -Wno-gnu -Wno-asm-operand-widths -Wno-initializer-overrides -fno-builtin -Wno-tautological-compare -mno-global-merge -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -Wno-initializer-overrides -Wno-unused-value -Wno-format -Wno-unknown-warning-option -Wno-sign-compare -Wno-format-zero-length -Wno-uninitialized -DMODULE -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(all)" -D"KBUILD_MODNAME=KBUILD_STR(ext2)" -mcmodel=kernel -c -o fs/ext2_instrumented/all.bc fs/ext2/all.c && cd -
this will create a .bc file for you. note that I have changed the resultant .bc codes directory to ext2_instrumented, i.e. my bc file is not created in fs/ext2 but in another folder called fs/ext2_instrumented. this is my work folder. I want this folder to not have any .c files, only .bc files. I need this because the default KBuild system looks for .c files in a folder. More on this later.
Step 2: Run all optimisation passes on your resultant ext2-instrumented.bc file using opt command like so:
opt -load $(DIR)/build/FSlice.so -constprop -sccp -mergereturn -sink -licm -reg2mem all.bc -o all.inst.bc
llvm-link -o all.inst2.bc $(DIR)/build/libFSlice.bc all.inst.bc
clang -mcmodel=kernel -c all.inst2.bc -o all.o
this will result into a .o file, which we will now compile into a .ko file in the next step:
Step 3:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) ext2instrumented.ko
Kbuild system is tough to understand, and even tougher to make modifications on. I would recommend use this 2 folder hack (1st folder to create .bc file and second folder to create .o and .ko files). To summarise, here is my resultant makefile in ext2_instrumented folder:
DIR=/home/fslice/fslice
obj-m += ext2instrumented.o
ext2instrumented-objs := all.o
all:
cd ../../ && clang -emit-llvm -Wp,-MD,fs/ext2/.all.o.d -nostdinc -isystem /usr/local/bin/../lib/clang/3.8.1/include -I./arch/x86/include -Iarch/x86/include/generated/uapi -Iarch/x86/include/generated -Iinclude -I./arch/x86/include/uapi -Iarch/x86/include/generated/uapi -I./include/uapi -Iinclude/generated/uapi -include ./include/linux/kconfig.h -D__KERNEL__ -Qunused-arguments -Wno-unknown-warning-option -Wall -Wundef -Wstrict-prototypes -Wno-trigraphs -fno-strict-aliasing -fno-common -Werror-implicit-function-declaration -Wno-format-security -std=gnu89 -no-integrated-as -mno-sse -mno-mmx -mno-sse2 -mno-3dnow -mno-avx -m64 -mtune=generic -mno-red-zone -mcmodel=kernel -funit-at-a-time -DCONFIG_X86_X32_ABI -DCONFIG_AS_CFI=1 -DCONFIG_AS_CFI_SIGNAL_FRAME=1 -DCONFIG_AS_CFI_SECTIONS=1 -DCONFIG_AS_FXSAVEQ=1 -DCONFIG_AS_SSSE3=1 -DCONFIG_AS_CRC32=1 -DCONFIG_AS_AVX=1 -DCONFIG_AS_AVX2=1 -DCONFIG_AS_SHA1_NI=1 -DCONFIG_AS_SHA256_NI=1 -pipe -Wno-sign-compare -fno-asynchronous-unwind-tables -O2 -Wframe-larger-than=1024 -fno-stack-protector -Wno-unused-variable -Wno-format-invalid-specifier -Wno-gnu -Wno-asm-operand-widths -Wno-initializer-overrides -fno-builtin -Wno-tautological-compare -mno-global-merge -fno-omit-frame-pointer -fno-optimize-sibling-calls -g -Wdeclaration-after-statement -Wno-pointer-sign -fno-strict-overflow -Werror=implicit-int -Werror=strict-prototypes -Werror=date-time -Wno-initializer-overrides -Wno-unused-value -Wno-format -Wno-unknown-warning-option -Wno-sign-compare -Wno-format-zero-length -Wno-uninitialized -DMODULE -D"KBUILD_STR(s)=#s" -D"KBUILD_BASENAME=KBUILD_STR(all)" -D"KBUILD_MODNAME=KBUILD_STR(ext2)" -mcmodel=kernel -c -o fs/ext2_instrumented/all.bc fs/ext2/all.c && cd -
opt -load $(DIR)/build/FSlice.so -constprop -sccp -mergereturn -sink -licm -reg2mem all.bc -o all.inst.bc
llvm-link -o all.inst2.bc $(DIR)/build/libFSlice.bc all.inst.bc
clang -mcmodel=kernel -c all.inst2.bc -o all.o
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) ext2instrumented.ko
clean:
make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
rm -rf *.bc

Resources