seg fault when running arm-elf-gcc compiled code - macos

Using MacPorts i have just installed arm-elf-gcc on to my MacBook Pro. This worked flawlessly and all seems to run fine.
However, after compiling a simple hello world test program in C and C++ and trying to run either on the target board (an ARM9 based board running Debian Linux) they immediately seg fault.
I'm a bit stuck as how to go about debugging this, as the target board has limited tools available and no gdb. I have successfully built and run other code using a Linux hosted cross compiler so it should work.
Any ideas?
Following the suggestion I have built and run gdbserver, I get the following in gdb on the host:
Program received signal SIGSEGV, Segmentation fault.
0x00000000 in ?? ()
I thought it may be a problem with the standard c libs so I removed any calls and have just an empty main that return 0, it is compiled with -Wall -g hello-arm.cpp -static. As a test I compiled the same source with a Linux hosted cross compiler and it runs and exits fine. The only difference I can see is the that Linux compiled version is over twice the size and the difference in output from the file command:
arm-elf-gcc: ELF 32-bit LSB executable, ARM, version 1, statically linked, not stripped
arm-*-linux: ELF 32-bit LSB executable, ARM, version 1, statically linked, for GNU/Linux 2.4.18, not stripped

The usual method of debugging in this situation is to run gdbserver on the target board, and connect to it (via ethernet) with gdb running on a host computer.
Alternately, you could try comparing the assembly in a Mac-compiled "Hello World" program and a (working) Linux-compiled one to see what's different.

After digging around for a couple of days I am starting to understand a bit more about embedded compilers. I wasn't really sure of the difference between arm-elf-gcc installed via MacPorts and the arm-unknown-linux toolchain I had installed on my Linux box. I just came across a pdf titled "An introduction to the GNU compiler" which contains the following paragraph:
Important: Using the GNU Compiler to
create your executable is not quite
the same as using the GNU Linker,
arm-elf-ld, yourself. The reason is
that the GNU Compiler automatically
links a number of standard system
libraries into your executable. These
libraries allow your program to
interact with an operating system, to
use the standard C library functions,
to use certain language features and
operations (such as division), and so
on. If you wish to see exactly which
libraries are being linked into the
executable, you should pass the
verbose flag
-v to the compiler.
This has important implications for
embedded systems! Such systems do not
usually have an operating system.
This means that linking in the system
libraries is almost always
meaningless: if there is no operating
system, for example, then calling the
standard printf function does not make
much sense.
So when I get back to my dev machine later I will determine the libraries linked in with the Linux build and add them to the arm-elf-gcc build.
I'll update this when I have more information but I just want to document my findings in case any one else has these problems.

Related

how to run ELF 64-bit LSB executable, UCB RISC-V, version 1 (GNU/Linux), dynamically linked on Linux

I am trying to do profiling of the code written in C++ with the target Architecture RISC-V. The code has been cross-compiled using RISC-V GNU Toolchain. My executable is unit_tests "ELF 64-bit LSB executable, UCB RISC-V, version 1 (GNU/Linux), dynamically linked,nterpreter /lib/ld-linux-riscv64-lp64d.so.1, for GNU/Linux 4.15.0, with debug_info, not stripped" this information is retrieved using the file command.
What I am trying to do is the profiling of this using gprof. But to do the gprof gmon.out needs to be generated, to generate gmon.out the executable should be run first. I cannot run the binary elf of other architecture in some different architecture. I need a suggestion for this on which emulator or simulator does this for me or I can run on?
I have tried installing qemu using the follwing link:
https://www.google.com/url?q=https://risc-v-getting-started-guide.readthedocs.io/en/latest/linux-qemu.html&sa=D&source=hangouts&ust=1597422417473000&usg=AFQjCNERr6pHYmj0SU6an3WkBRGQI52aTw
but not able to successfully install it.
Also have tried with spike but got "bad synccall" error. Any leads how can I resolve this issue.
I solved this issue using qemu in user mode. Following the instructions in the below link:
Manual-qemu-user
Where I could run the binary elf generated for target RISC-V, which I could run on x86 Linux machine.

GCC error with -mcpu32 flag, CPU32 compiler needed

I am patching code into my car's ECU. This has a Motorola MC68376 processor, so I'm using the appropriate CPU32 instruction set.
I want to continue to write in assembly code so that I can explicitly manage control registers, RAM access and allocation, as well as copying code structures which are already in use.
My first patch was successfully compiled in EASy68k, but that program does not support the full instruction set for the CPU32. For example, the DIVS.L command is not supported, so I cannot take a quotient of a 32-bit value.
Thus, before writing my own compiler out of sheer incompetence with available tools, I'm looking for an easier path. I read that gcc has the capability to compile code for the CPU32, but I have failed to get it to work.
I'm using MinGW's gcc (6.3.0) and Eclipse (2020-03). I added the '-mcpu32' or '-march=cpu32' flags to the compiler call, according to:
https://gcc.gnu.org/onlinedocs/gcc/M680x0-Options.html
Unfortunately this returns an error:
gcc: error: unrecognized command line option '-mcpu32'; did you mean '-mcpu='?
or
error: bad value (cpu32) for -march= switch
May I please have some advice for making this work? Does anyone know of a better CPU32 compiler that works with Eclipse?
I did not understand that gcc is conventionally distributed as binary files that are compiled with different functionality to suit the needs of a given user.
There seem to be two paths forward:
1) compile my own cross-compiler version of GCC
2) download a pre-compiled cross-compiler version of GCC
I chose to follow route 2).
I began the process of installing the 'Windows Subsystem for Linux' and Ubuntu 20.04 Focal Fossa, because I found a pre-made compiler that should be capable of performing cross compilation for the m68k processor: "gobjc-10-m68k-linux-gnu"
https://ubuntu.pkgs.org/20.04/ubuntu-universe-i386/gobjc-10-m68k-linux-gnu_10-20200411-0ubuntu1cross1_i386.deb.html
While I was installing that, I also found an m68k-elf gcc toolchain that is pre-compiled for windows 10:
https://gnutoolchains.com/m68k-elf/
I played with the latter for much of today. Although I was unable to get the toolchain integrated well with Eclipse, it works from the command line to compile a *.s assembly code file. This includes compatibility with the '-mcpu32' flag that I wanted at the outset.
There is still a lot for me to figure out, even after floundering through learning gcc's assembler directives (https://www.eecs.umich.edu/courses/eecs373/readings/Assembler.pdf) and the differences in gcc's assembly syntax compared to the MC68k reference manual (https://www.nxp.com/files-static/archives/doc/ref_manual/M68000PRM.pdf).
I can even convert the code section of the output file to be a proper s-record by using objcopy with the '-O srec' and '--only-section=.text' flags. This helps me patch the code into my ECU.
Thus I've answered my original question.

Cross-compiling for a specific platform -- linking libc

I have to compile a simple binary for a very old Linux system. I have no gcc/build libs available on the target machine but I do have access to the machine.
I am having trouble compiling the code on my machine and having it execute on target machine.
I am copying libc.so to my local machine and trying to compile and link the program so that it will execute on the target machine.
I have copied the libc from the target machine to mine and tried compiling it with my target executable.
this has gotten closes to a successful execution:
gcc -nostdlib ./libc-[version].so myFile.c -emain -o outfile.out
upon execution a very simple PoC test program runs, and then seg faults upon exit. the actual program simply seg faults.
It seems I have somewhat of a lack of understanding of linking. Any help?
It seems I have somewhat of a lack of understanding of linking.
You do. A "normal" user-level program doesn't start executing at main, it starts at _start.
The _start symbol typically comes from crt0.o file (part of libc), and knows how to "interface" between the way the kernel supplies arguments, and the way main expects to find them. It also initializes various data that must be initialized before main runs (e.g. stdio streams).
What you want to do then is:
Find out the actual link command that gcc main.o performs. You can do so by adding the -v flag.
Replicate such command, providing crt0.o and other input files, appropriate for your version of target libc.
It might be easier to spin up a VM with the OS matching your target (and with old tools that target it), and build your program inside of that VM.
Otherwise you'll likely have to set up a full cross-compiler environment (which includes libc and all other libraries you need). This is not a trivial proposition, and is certainly not accomplished by copying libc.so from the target machine. But it is well-documented and is certainly doable (with some skill).

Compiling tsocks-1.8 in Solaris 10 SPARC

I have a ORACLE/Sun SPARC server with Solaris 10 SPARC OS installed
I am attempting to install tsocks-1.8beta4.tar.gz into Solaris
However in my PuTTY terminal is the following error....
ld: fatal: library -lc not found
This error is being generated by the saveme.c file within the tsocks directory. It contains the following line I believe is causing the fault
unlink("/etc/ld.so.preload")
I dont have the file ld.so.preload inside my Solaris 10 SPARC OS
What shall I do next?
tsocks makes many, many Linux-specific assumptions, such as /etc/ld.so.preload being used, and attempting to statically link portions of the tsocks package.
Solaris 10 does not have a static libc.a. You can not statically link any executable on Solaris 10 and later against system libraries such as libc and libm.
See Static Linking - where did it go?:
With Solaris 10 you can no longer build a static executable. It's not that ld(1) doesn't allow static linking, or using archives, it's just that libc.a, the archive version of libc.so.1, is no longer provided. This library provides the interfaces between user land and the kernel, and without this library it is rather hard to create any form of application.
We've been warning users against static linking for some time now, and linking against libc.a has been especially problematic. Every solaris release, or update (even some patches) has resulted in some application that was built against libc.a, failing. The problem is that libc is supposed to isolate an application from the user/kernel boundary, a boundary which can undergo changes from release to release.
If an application is built against libc.a, then any kernel interface it references is extracted from the archive and becomes a part of the application. Thus, this application can only run on a kernel that is in-sync with the kernel interfaces used. Should these interfaces change, the application is treading on shaky ground.
...

Cross-compiling baremetal Rust for Raspberry Pi 3 B from Windows

I'm trying to follow this blog but on Windows and with the latest Rust. It seems to me that the correct way of doing things like this is changing very frequently with Rust, so I'm hoping for an up-to-date Windows adaptation.
What I've tried so far:
I installed gcc-arm-embedded.
I had unverified partial success manually cross-compiling libcore, but then I switched to use the recommended xargo, the functionality of which (I read) is on its way to being included in Cargo eventually. While I don't understand any of it very well, I'm hoping to get to the part where I can write/run the code and then maybe I can back into understanding the compilation better.
With japaric's awesome help, I was able to get the "aarch64" targeted build working to generate the .o file (as of this particular commit).
And this part seems to verify:
$ file target/aarch64-raspi3-none-elf/release/deps/rust_rasp-ed0c2377e0a7df81.o
target/aarch64-raspi3-none-elf/release/deps/rust_rasp-ed0c2377e0a7df81.o: ELF 64-bit LSB relocatable, ARM aarch64, version 1 (SYSV), not stripped
When I try to use the GNU Arm Embedded Toolchain linker, I get:
$ arm-none-eabi-gcc -O0 -mfpu=vfp -mfloat-abi=hard -march=armv6zk -mtune=arm1176jzf-s -nostartfiles target/aarch64-raspi3-none-elf/release/deps/rust_rasp-ed0c2377e0a7df81.o -o kernel.elf target/aarch64-raspi3-none-elf/release/deps/rust_rasp-ed0c2377e0a7df81.o: file not recognized: File format not recognized
collect2.exe: error: ld returned 1 exit status
And #rust IRC chatroom helpfuls told me that rpi3 is aarch64, not arm, so I need to find an aarch64 linker ...
I think it's working! Things I learned:
xargo is good
rpi3 is different enough from rpi2 to cause my problems in tool selection
xargo doesn't care what toolchain rustup defaults to because I'm not asking it to link for me and it does its own toolchain selection
I needed to target aarch64, not arm. For this I used the linaro aarch64 mingw32 download, unpacked, added its bin folder to my PATH. Then the aarch64 tools were easy to adapt from the blog.
For people who want to do this themselves, see https://github.com/JasonKleban/rust-rasp . Not so complicated!
I aim to blink the onboard activity led as confirmation that we do really have control, but looks like that will be kinda complicated on the rpi3 (see my readme, if still applicable)

Resources