I have dumped the RTL generated as intermediate using "-fdump-final-insns" flag in compilation of a C Program using gcc but i need the optimized version of it, i.e. the resultant RTL after optimization phase of compiler. How can i get it ?
Example -
Register Transfer Language (RTL)
(insn 14 12 15 (nil) (set (reg:CCZ 17
(compare:CCZ (mem/f:SI (plus:SI (reg/f:SI 54 virtual-stack-vars)
(const_int -4 [0xfffffffc])) [0 i+0 S4 A32])
(const_int 99 [0x63]))) -1 (nil)
(nil))
Optimized RTL -
(insn 14 12 15 (nil) (set (reg:CCZ 17 flags)
(compare:CCZ (reg/v:SI 61 [ i ])
(const_int 99 [0x63]))) -1 (nil)
(nil))
For this purpose, you can use flags:
gcc foo.c -da -dp -fdump-tree-all-raw-lineno
Where:
-da produce all RTL dumps
-dp annotate the assembler output with a comment indicating which
patterns and alternatives are used.
-fdump-tree-all-raw-lineno Enables showing line numbers for statements.
This will create about 167 files, each of them means different stages of GIMPLE and RTL passes, optimizations and so on.
Here is simple explanation is what's going on:
https://www.cse.iitb.ac.in/~uday/courses/cs715-09/gcc-rtl.pdf
Look at last two number 306 and 307, there is the final, optimized phase of compiler before parse it into assembler.
foo.c.306r.final
foo.c.307r.finish
You can also use flags -S with -dA
Where:
-S produces assembler output
-dA annotate the assembler output with miscellaneous debugging information
and in foo.s you can view a connection between RTL and assembler code.
Related
First time posting a question here, open to feedback.
I am trying to get an executable running in AWS lambda, however I am getting the error "cannot execute binary file" which is quite vague (more outputs below).
I am hoping to identify what could be wrong, and why.
As a disclaimer I am not very good at c or python.
Currently my process has been to write a hello world program in c:
#include <stdio.h>
int main() {
printf("Hello World");
return 0;
}
Create an AWS instance which matches the Python 3.8 lambda runtime (Amazon Linux 2)
(Tried on Amazon Linux 1 with the same results)
Install compiler tools
sudo yum install gcc
sudo yum install glibc-static
Compile the program to a static executable
gcc -static -static-libgcc -static-libstdc++ hello.c -o testings
Also tried with less flags with similar results.
gcc -static hello.c -o testings
Have also tried as a 32 bit binary using -m32 flag. Tried this as looking at the cpu information for the lambda runtime showed a 32 bit processor.
Verify it has compiled with static dependencies
file testings
with the results
testings: ELF 64-bit LSB executable, x86-64, version 1 (GNU/Linux), statically linked, for GNU/Linux 3.2.0, BuildID[sha1]=7167aa934c751be053864ee555be8f6a46e4d62e, not stripped
and
ldd testings
with the results
not a dynamic executable
I've copied it to my local machine, changed the file permissions to allow execution, zipped it and uploaded it to lambda.
Which contains two files.
testings (the compiled c program)
lambda_function.py which looks like
import json
from subprocess import run, call
def lambda_handler(event, context):
call(["ls -ll"], shell=True)
print("using run")
out = run(["./testings"], shell=True)
print("printing result")
print(out.returncode)
print("printing output")
print(out.stdout)
print("printing error")
print(out.stderr)
return {
'statusCode': 200,
'body': json.dumps('hello')
}
The output of running this function is:
Response:
{
"statusCode": 200,
"body": "\"hello\""
}
Request ID:
"fb640125-6698-4777-841a-47228d4da930"
Function Logs:
START RequestId: fb640125-6698-4777-841a-47228d4da930 Version: $LATEST
total 1092
-rwxrwxrwx 1 slicer 497 426 Jan 13 07:03 lambda_function.py
-rwxrwxrwx 1 slicer 497 1111526 Jan 13 06:32 testings
using run
/bin/sh: ./testings: cannot execute binary file
printing result
126
printing output
None
printing error
None
END RequestId: fb640125-6698-4777-841a-47228d4da930
REPORT RequestId: fb640125-6698-4777-841a-47228d4da930 Duration: 24.81 ms Billed Duration: 100 ms Memory Size: 512 MB Max Memory Used: 58 MB Init Duration: 113.42 ms
I can run the executable on the AWS instance where it was compiled and on my local machine (Ubuntu 18.04.3 LTS).
I have read quite a few similar questions (running executable in lambda) and am aware this is not a new question, however I haven't managed to find a solution that works for me ( I suspect I am misunderstanding something fundamental, as this is a very new domain for me.)
Additional Information:
using readelf to look at the binaries headers:
ELF Header:
Magic: 7f 45 4c 46 02 01 01 03 00 00 00 00 00 00 00 00
Class: ELF64
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - GNU
ABI Version: 0
Type: EXEC (Executable file)
Machine: Advanced Micro Devices X86-64
Version: 0x1
Entry point address: 0x400950
Start of program headers: 64 (bytes into file)
Start of section headers: 699480 (bytes into file)
Flags: 0x0
Size of this header: 64 (bytes)
Size of program headers: 56 (bytes)
Number of program headers: 6
Size of section headers: 64 (bytes)
Number of section headers: 33
Section header string table index: 32
I have the following piece of x86 assembly code:
1
2 .text
3
4 .data
5
6 # define an array of 3 dwords
7 array_word DW 1, 2, 3
8
9
10 .globl main
11
12main:
13 # nothing interesting ..
14
But when I compile this, I keep getting the following error:
$ gcc my_asm.s
my_asm.s: Assembler messages:
my_asm.s:7: Error: no such instruction: `array_word DW 1,2,3'
This is the gcc I use:
$ gcc --version
gcc (GCC) 4.4.7 20120313 (Red Hat 4.4.7-16)
Copyright (C) 2010 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Your syntax is wrong - gas (which is invoked by gcc for assembly files) uses a different syntax than other assemblers like NASM.
Use
array_word: .word 1, 2, 3
See also https://sourceware.org/binutils/docs/as/Word.html#Word
Note that the result of .word is target CPU specific - an alternative is .hword:
7.60 .hword expressions
This expects zero or more expressions, and emits a 16 bit number for
each.
This directive is a synonym for .short; depending on the target architecture, it may also be a synonym for .word.
By the way: you say # define an array of 3 dwords in your comment - but note that DW is Define Word which defines a 16 bit word. In NASM, you would use DD for 32 bit words.
The RFC from May 2015 Y. Nir et al, ChaCha20 and Poly1305 for IETF Protocols
(https://www.rfc-editor.org/rfc/rfc7539) contains a reference to the MIT/Public domain C library https://github.com/floodyberry/poly1305-donna.
I am just porting the C code to Pascal. The 8 bit code works OK (self-test, example, and RFC test vectors).
The port from poly1305-donna-16.h using 16->32 bit multiples and 32 bit additions failed. After some testing I compiled the original source with DJGPP GCC 4.7.3, MS VC 6.0 and BC 3.1 and all three failed too (poly1305 self-test).
Questions: Does this C version (build with -DPOLY1305_16BIT) fail for other compilers too? Is there a known fix available? (The blog of the author Andrew Moon at https://floodyberry.wordpress.com/ is inactive since 6 years)
I can confirm a build failure on a pretty vanilla Fedora 22 system:
% gcc poly1305-donna.c -c -DPOLY1305_16BIT
% gcc example-poly1305.c -o ex poly1305-donna.o -DPOLY1305_16BIT
% ./ex
poly1305 self test: failed
Notice that the test succeeds when I omit -DPOLY1305_16BIT.
Also notice:
% uname -rmp
4.0.8-300.fc22.x86_64 x86_64 x86_64
% gcc --version
gcc (GCC) 5.1.1 20150618 (Red Hat 5.1.1-4)
I suggest you submit a bug report. Andrew has been responsive in the past.
EDIT:
Compiling with clang version 3.5.0 yields the same results as the above gcc test.
I'm trying to compile a couple of programs for a little embedded device I own. It's a Little-endian MIPS (mipsel) processor. I retrieved this executable from it via telnet and the builtin ftp client:
root#debian-mipsel:/home/user/wansview/devel# readelf -h unzip1
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x401cc0
Start of program headers: 52 (bytes into file)
Start of section headers: 169960 (bytes into file)
Flags: 0x10001007, noreorder, pic, cpic, o32, mips2
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 6
Size of section headers: 40 (bytes)
Number of section headers: 24
Section header string table index: 23
root#debian-mipsel:/home/user/wansview/devel# file unzip1
unzip1: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked (uses shared libs), stripped
I then downloaded the MIPSEL version of Debian and I'm running it in QEMU. When I run the retrieved program above I get:
root#debian-mipsel:/home/user/wansview/devel# ./unzip1
-bash: ./unzip1: No such file or directory
Which I understand means it's not the right platform. Stubbornly I compiled a little hello world nonetheless to compare the ELF and file info. My hello world runs fine in Debian MIPSEL but also returns No such file or directory on the embedded device. It's readelf and file output is strikingly similar though:
root#debian-mipsel:/home/user/wansview/devel# readelf -h hello
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: EXEC (Executable file)
Machine: MIPS R3000
Version: 0x1
Entry point address: 0x400740
Start of program headers: 52 (bytes into file)
Start of section headers: 3652 (bytes into file)
Flags: 0x10001005, noreorder, cpic, o32, mips2
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 10
Size of section headers: 40 (bytes)
Number of section headers: 36
Section header string table index: 35
root#debian-mipsel:/home/user/wansview/devel# file hello
hello: ELF 32-bit LSB executable, MIPS, MIPS-II version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xeb3877062337a3dfd15cc09305691685ac0e8c57, with unknown capability 0xf41 = 0x756e6700, with unknown capability 0x70100 = 0x1040000, stripped
I'm trying to better understand how my two systems differ and why the executables won't run on both. Are there any flags I could add to gcc to successfully compile for the embedded device?
More info about the device
# cat /proc/cpuinfo
system type : Ralink SoC
processor : 0
cpu model : MIPS 24K V4.12
BogoMIPS : 239.10
wait instruction : yes
microsecond timers : yes
tlb_entries : 32
extra interrupt vector : yes
hardware watchpoint : yes
ASEs implemented : mips16 dsp
VCED exceptions : not available
VCEI exceptions : not available
More info about Debian MIPSEL
(Binaries compiled on debian-mipsel won't run on the target embedded device)
root#debian-mipsel:/home/user/wansview/devel# cat /proc/cpuinfo
system type : MIPS Malta
processor : 0
cpu model : MIPS 24Kc V0.0 FPU V0.0
BogoMIPS : 1038.33
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
ASEs implemented : mips16
shadow register sets : 1
kscratch registers : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
More info about Aboriginal Linux Mipsel
(Binaries compiled on Aboriginal Linux will run on the embedded device, and it can run binaries retrieved from the device. I'm not happy with it as it doesn't have make and other tools I need for compiling larger applications)
(mipsel:1) /home/wansview # cat /proc/cpuinfo
system type : MIPS Malta
machine : Unknown
processor : 0
cpu model : MIPS 24Kc V0.0 FPU V0.0
BogoMIPS : 1013.76
wait instruction : yes
microsecond timers : yes
tlb_entries : 16
extra interrupt vector : yes
hardware watchpoint : yes, count: 1, address/irw mask: [0x0ff8]
isa : mips1 mips2 mips32r1 mips32r2
ASEs implemented : mips16
shadow register sets : 1
kscratch registers : 0
core : 0
VCED exceptions : not available
VCEI exceptions : not available
LDD
Here's a screenshot with ldd ran against my hello world and against unzip1 on both aboriginal linux and debian mipsel. Aboriginal Linux runs applications retrieved from the device just fine, and if I compile under Aboriginal Linux I can run the resulting binary on the embedded device. The reason I'm not content with Aboriginal is that doesn't have GNU make and other useful tools for larger applications, and no easy way to get them there.
You clearly need a different toolchain. On your Debian-mipsel, your toolchain uses glibc while your target uses uClibc.
So, maybe you would like to generate it by yourself using Buildroot:
wget http://buildroot.uclibc.org/downloads/buildroot-2014.11.tar.gz
tar zxf http://buildroot.uclibc.org/downloads/buildroot-2014.11.tar.gz
cd buildroot-2014.11
A trick to preconfigure for mipsel, R1 without soft-float (my will, check yours):
cat <<_EOF > .config
BR2_HAVE_DOT_CONFIG=y
BR2_mipsel=y
BR2_ARCH="mipsel"
BR2_ENDIAN="LITTLE"
BR2_GCC_TARGET_ARCH="mips32"
BR2_GCC_TARGET_ABI="32"
BR2_ARCH_HAS_ATOMICS=y
BR2_mips_32=y
# BR2_MIPS_SOFT_FLOAT is not set
BR2_MIPS_OABI32=y
_EOF
Finish your choice in Buildroot menuconfig, but you can
also keep it like this with save and exit.
make menuconfig # tweak options at your will,
make -j8 # takes 8 minutes on my machine
Then, your compiler can be found in ./output/host/usr/bin
A real example:
echo '#include <stdio.h>
int main(int argc, char* argv[]) {
printf("Hello World.\n");
return 0;
}' > hello.c
And compile it with your brand-new uClibc GCC compiler
output/host/usr/bin/mipsel-buildroot-linux-uclibc-gcc -o hello hello.c
A glimpse into the hello program: (didn't had time to fix my ldd...)
$ file hello
hello: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
$ strings hello | grep "lib.*so*"
/lib/ld-uClibc.so.0
libgcc_s.so.1
libc.so.0
It's done with the toolchain and compile your program.
Now that you have time :-) see what Buildroot offers :
a complete distribution (in output/target/) for embedded systems in many architectures.
EDIT: Better chance to execute
You can statically link your program in order to maximize the chances to run your code on any target.
$ output/host/usr/bin/mipsel-linux-gcc -Wall -o hello -static hello.c
$ file ./hello
./hello: ELF 32-bit LSB executable, MIPS, MIPS32 version 1 (SYSV), dynamically linked (uses shared libs), not stripped
And now, as that static version doesn't depend anymore on any external lib (only uClibc, here), this MIPS executable can even run on my x86_64 machine (thanks to binfmt and Qemu) :
$ uname -mo
x86_64 GNU/Linux
$ ./hello
Hello World.
Cheers.
Maybe i'm wrong but a simple fix (but not elegant way) in such cases could be to link the missing files to the existing ones:
ln -s /lib/libc.so.6 /lib/libc.so.0
like in this situation:
https://dev.openwrt.org/ticket/3083
GDB is complaining that my source file is more recent than the executable, and it appears the debugging information is indeed related to an older version of the source file, because gdb is stopping on a blank line:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000000000 in ?? ()
(gdb) up
#1 0x00007ffff7ba2d88 in CBKeyPairGenerate (keyPair=0x602010) at library/src/CBHDKeys.c:246
warning: Source file is more recent than executable.
246
(gdb) list
241 if (versionBytes == CB_HD_KEY_VERSION_TEST_PUBLIC
242 || versionBytes == CB_HD_KEY_VERSION_TEST_PRIVATE)
243 return CB_NETWORK_TEST;
244
245 return CB_NETWORK_UNKNOWN;
246
247 }
248
249 uint8_t * CBHDKeyGetPrivateKey(CBHDKey * key) {
250
But the executable is more recent than the source file, see here:
$ ls -l library/src/CBHDKeys.c
-rw-r--r-- 1 matt matt 9249 Apr 29 22:40 library/src/CBHDKeys.c
$ ls -l bin/noLowerAddressGenerator
-rwxr-xr-x 1 matt matt 17845 Apr 30 15:52 bin/noLowerAddressGenerator
I tried rebuilding after make clean and ccache -C but the same problem occurs. When I updated the source file I only added whitespace, so the program logic remains equal.I feel that has something to do with it, but since I cleared the ccache and cleaned the build and bin directory with make clean I'm not sure what is going on.
Versions:
GNU Make 3.81
gcc (Debian 4.8.2-16) 4.8.2
GNU gdb (GDB) 7.6.2 (Debian 7.6.2-1)
ccache version 3.1.9
SolydXK - SMP Debian 3.13.5-1 (2014-03-04)
Perhaps you're not using the most recent compiled version of the code, if it's in a shared library. You could use ldd noLowerAddressGenerator to see the library dependencies of your program; I don't know if it's possible from within GDB to locate the relevant library, but there ought to be a way (please comment or edit if you know how).
If this is indeed the case, you might want to set environment LD_LIBRARY_PATH in GDB prior to running the program, to place your newly-built library ahead of any installed ones. You could look into setting the RPATH ELF variable when linking, but that's likely to be less help.
Another possibility is to run your debugger on a system where you know the library isn't installed. I've had good results using schroot to keep build/debug/install environments separated.