I have a setup like this:
GDB from "GNU Arm Embedded Toolchain" 10.3-2021.10
GDB server from "Segger JLink" 7.54d
JLink Ultra+ connected to my PC and my embedded device
Arm Compiler 6.15
I'm having problems stepping into a certain function from a C module (let's call it "F1"). When trying, I get the error message
Single stepping until exit from function "F1", which has no line number information.
If I use Segger Ozone, with the same .elf file, stepping into "F1" works fine.
I've tried to narrow down the problem and have the following observations:
A single line of code from the C module holding "F1" makes the difference. If I remove this line, it works. This line is a simple incrementation (++) of a static uint32_t variable and it is in a separate function (i.e. not "F1").
If I don't link with "--inline" option, it stops working - even with the "fix" in (1)
All source files (a mix of C and C++ files) are compiled with -g option.
I may try to reproduce it in a much smaller context which I could share here but until then, I'm hoping for some hints.
Anything is appreciated.
[Update 2021-11-10] Tried with older/newer versions of "GNU Arm Embedded Toolchain" as well as "Segger JLink". Same problem.
[Update 2021-11-10] Compiler/linker command used:
armclang -g --target=arm-arm-none-eabi -mcpu=cortex-m33 -mfloat-abi=soft -MMD -Werror -D__STDC_LIMIT_MACROS -I<my_include_paths>
armlink --inline --info=sizes --info=veneers --info=unused --info=totals --map --symbols --scatter=<my_scatter_file> --list=list.txt
Related
Erlang Run-Time System (ERTS) have a few drivers written in C language that used to interact with the OS or to access low-level resources, In my knowledge the ERTS compile these drivers at boot time to get ready for loading from Erlang code, the driver inet_drv.c is one of these drivers and it's used to handle networking tasks like creating sockets and listening or accepting new incoming connections.
I wanted to test this driver manually to get a general view of the default behaviour of the ERTS and to know how to implement drivers efficiently in the future, I tracked the Erlang Manual Reference to implement drivers that said: first write and compile the driver by an OS C Language Compiler, second load the driver from erlang code using erl_ddll module, finally link to the driver by a spawned Erlang process, so this is very simple and easy.
So I tried these steps with the driver inet_drv.c, I searched for it and tried to compile it with Clang Compiler which is the Default C Compiler of FreeBSD System :
cc inet_drv.c
after that there was an error saying that the file erl_driver.h is not defined, this header file is used in the driver's code as an included file (#include<erl_driver.h>) so I searched for it and add it's directory path to the cc command using the -I option to get the compiler search for the included file in this directory and I recompile it :
cc inet_drv.c -I/usr/ports....
after that, there was be another undefined file so I did the same thing for 5 or 6 times and finally, I add all needed paths for included files and the result is this command :
cc inet_drv.c
-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/beam
-I/usr/local/lib/erlang/usr/include
-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/sys/unix
-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/include/internal
-I/usr/ports/lang/erlang/work/otp-OTP-21.3.8.18/erts/emulator/sys/common
-I/usr/ports/lang/erlang/work/stage/usr/local/lib/erlang/erts-10.3.5.14/include/internal
I was surprised by the result:13 errors and 7 warnings, the shell output and errors and warnings description are in the links below.
My question is : why these errors occurs ? What is the wrong in what I did ?
Since this driver works perfectly in response to the ERTS networking tasks, then it's compiled by the ERTS without errors and the ERTS should use an OS C Language Compiler which is Clang by default and should add included headers files as I did, so why this did not work when I tried to do ?
https://ibb.co/bbtFHZ7
https://ibb.co/sF8QsDx
https://ibb.co/Lh9cDCH
https://ibb.co/W5Gcj7g
First things first:
In my knowledge the ERTS compile these drivers at boot time
No, ERTS doesn't compile the drivers. inet_drv.c is compiled as part of Erlang/OTP and linked into the beam.smp binary.
inet_drv is not a typical driver. Quoting the How to Implement a Driver section of the documentation:
A driver can be dynamically loaded, as a shared library (known as a DLL on Windows), or statically loaded, linked with the emulator when it is compiled and linked. Only dynamically loaded drivers are described here, statically linked drivers are beyond the scope of this section.
inet_drv is a statically loaded driver, and as such doesn't need to be loaded with erl_ddll.
On to the compilation errors. All the compiler parameters are automatically added for you when you run make, so if you need to call the compiler manually, better just check the command line that make generated and start from that. Let's look at the build log for the Debian Erlang package. Searching for inet_drv we get this command line (line breaks added):
x86_64-linux-gnu-gcc -Werror=undef -Werror=implicit -Werror=return-type -fno-common \
-g -O2 -fno-strict-aliasing -I/<<PKGBUILDDIR>>/erts/x86_64-pc-linux-gnu -D_GNU_SOURCE \
-DHAVE_CONFIG_H -Wall -Wstrict-prototypes -Wpointer-arith -Wmissing-prototypes \
-Wdeclaration-after-statement -DUSE_THREADS -D_THREAD_SAFE -D_REENTRANT -DPOSIX_THREADS \
-D_POSIX_THREAD_SAFE_FUNCTIONS -DBEAMASM=1 -DLIBSCTP=libsctp.so.1 \
-Ix86_64-pc-linux-gnu/opt/jit -Ibeam -Isys/unix -Isys/common -Ix86_64-pc-linux-gnu \
-Ipcre -I../include -I../include/x86_64-pc-linux-gnu -I../include/internal \
-I../include/internal/x86_64-pc-linux-gnu -Ibeam/jit -Ibeam/jit/x86 -Idrivers/common \
-Idrivers/unix -c \
drivers/common/inet_drv.c -o obj/x86_64-pc-linux-gnu/opt/jit/inet_drv.o
Some of it will be different since you're building on FreeBSD, but the principle stands - most of the time you'll want to just run make instead of invoking the compiler directly, but if you need to invoke the compiler, it will be much easier to start with the command line that make generated for you.
I have recently been trying to compile dropbear for 64bit arch android devices. I got the program to compile and run, but when I log in to the server it kicks me off with an error.
I configured & compiled like so:
cp ../config.guess ../config.sub .
./configure --build=x86_64-windows --host=arm-linux-androideabi \
--disable-zlib --disable-largefile --disable-loginfunc \
--disable-shadow --disable-utmp --disable-utmpx --disable-wtmp \
--disable-wtmpx --disable-pututline --disable-pututxline --disable-lastlog \
CFLAGS='-Os -W -Wall -fPIE' LDFLAGS='-fPIE -pie'
make dropbear
The error:
CANNOT LINK EXECUTABLE: "/system/lib/libc++.so" is 32-bit instead of 64-bit
page record for 0x7f800b8010 was not found (block_size=32)
I believe the error is caused by dropbear linking sh and other executables to the library in wrong location.
The device has two locations for libc++
#1 /system/lib/libc++.so
#2 /system/lib64/libc++.so
How can I tell/force the compiled binary to use the lib(s) in
/sytem/lib64
If giving an example please show me exactly what needs to be added, so I can apply the information correctly. I'm almost sure the fix is simple but I'm not a programmer. I do this stuff when I'm desperate.
Turns out there was a hard link in srv-chansession.c that needed to be modified
From:
addnewvar("LD_LIBRARY_PATH", "/system/lib");
To:
addnewvar("LD_LIBRARY_PATH", "/system/lib64");
It may actually be better to comment out that line and let androids linkers take care of it.
Now I have working a working dropbear ssh server on my 64 bit android device.
Does the gcc output of the object file (C language) vary between compilations? There is no time-specific information, no change in compilation options or the source code. No change in linked libraries, environmental variables either. This is a VxWorks MIPS64 cross compiler, if that helps. I personally think it shouldn't change. But I observe that sometimes randomly, the instructions generated changes. I don't know what's the reason. Can anyone throw some light on this?
How is this built? For example, if I built the very same Linux kernel, it includes a counter that is incremented each build. GCC has options to use profiler information to guide code generation, if the profiling information changes, so will the code.
What did you analyze? The generated assembly, an objdump of object files or the executable? How did you compare the different versions? Are you sure you looked at executable code, not compiler/assembler/linker timestamps?
Did anything change in the environment? New libraries (and header files/declarations/macro definitions!)? New compiler, linker? New kernel (yes, some header files originate with the kernel source and are shipped with it)?
Any changes in environment variables (another user doing the compiling, different machine, different hookup to the net gives a different IP address that makes it's way into the build)?
I'd try tracing the build process in detail (run a build and capture the output in a file, and do so again; compare those).
Completely mystified...
I had a similar problem with g++. Pre 4.3 versions produced exactly the same object files each time. With 4.3 (and later?) some of the mangled symbol names are different for each run - even without -g or other recordings. Perhaps the use a time stamp or random number (I hope not). Obviously some of those symbols make it into the .o symbol table and you get a difference.
Stripping the object file(s) makes them equal again (wrt. binary comparison).
g++ -c file.C ; strip file.o; cmp file.o origfile.o
Why should it vary? It is the same result always. Try this:
for i in `seq 1000`; do gcc 1.c; md5sum a.out; done | sort | uniq | wc -l
The answer is always 1. Replace 1.c and a.out to suit your needs.
The above counts how many different executables are generated by gcc when compiling the same source for 1000 times.
I've found that in at least some environments, the same source may yield a different executable if the source tree for the subsequent build is located in a different directory. Example:
Checkout a pristine copy of your project to dir1. Do a full rebuild from scratch.
Then, with the same user on the same machine, checkout the same exact copy of your source code to dir2 (dir1 != dir2). Do another full rebuild from scratch.
These builds are minutes apart, with no change in the toolchain or any 3rd party libs or code. Binary comparison of source code is the same. However, the executable in dir1 has different md5sum than the executable in dir2.
If I compare the different executables in BeyondCompare's hex editor, the difference is not just some tiny section that could plausibly be a timestamp.
I do get the same executable if I build in dir1, then rebuild again in dir1. Same if I keep building the same source over and over from dir2.
My only guess is that some sort of absolute paths of the include hierarchy are embedded in the executable.
My gcc sometimes produces different code for exactly the same Input. The output object files differ in exactly one byte.
Sometimes this causes linker Errors, because one possible object file is invalid. Recompiling another version usually fixes the linker error.
The gcc Version is 4.3.4 on Suse Linux Enterprise.
The gcc Parameters are:
cc -std=c++0x -Wall -fno-builtin -march=native -g -I<path1> -I<path2> -I<path3> -o obj/file.o -c file.cpp
If someone experiences the same effect, then please let me know.
I am calling fortran 90 code from a c code. There is a main() (in c) that calls a wrapper function in the same file, that calls a fortran subroutine (actually in a liblibrary.a). I am working on linux. Now, I'm using gdb to debug the executable, but it cannot find the main.c file. I added the working directory using
directory /my/working/directory
but still it says there is no file named main.c
If I type list inside gdb it shows me a piece of fortran code. If I type show language, it says The current source language is auto; currently c.
If I run the executable and then I interrupt it and look to the stack it will show me the c-functions I am calling, but it will not state the source file, that instead will state for the fortran subroutine and function.
I am trying to investigate if I am passing the variables correctly from c to fortran and backwards, I suspect I am not.
The same thing happens in idb, more or less. when I try to put a break in main.c, it says not found. I compiled the fortran code with these flags:
-g -O0 -check bounds -warn all -traceback -align all -align rec8byte
and the c-code with:
-g -O0 -Wall
All suggestions are welcome.
Hello you need additional flag to put debug info into your executable.
Here is manual for intel compiler:
http://cache-www.intel.com/cd/00/00/34/75/347599_347599.pdf
Please try -debug full as on page 35 written.
I am writing a C language program on Linux and compiling it using GCC.
I also use a Make file.
I want to debug my program. I don't want to debug a single file, I want to debug the whole program.
How can I do it?
Compile your code with the -g flag, and then use the gdb debugger. Documentation for gdb is here, but in essence:
gcc -g -o prog myfile.c another.c
and then:
gdb prog
If you want a user-friendly GUI for gdb, take a look at DDD or Insight.
I guess that you are building from the command line.
You might want to consider an IDE (Integrated Development Environment), such as KDevelop or Eclipse, etc (hint - Eclipse ... ECLPISE ... E C L I PS E).
Use an IDE to edit your code, refactor your code, examine your code - class tree, click a variable, class or function to jump to declaration, etc, etc
And - of course - to debug:
run your code in the IDE
set breakpoints to stop at particular lines
or just step through, a line at a time
examine the call stack to see how you go there
examine the current values of variables, to understand your problem
change the values of those variables and run to see what happens
and more, more, more
p.s as wasatz mentioned- DDD is great - for visualizing the contents of arrays/matrices, and - imo - especially if you have linked lists
You can use gdb-based simple and useful GUI "Nemiver". It can debug your whole module comprising many source files.
Try cgdb
cgdb is a lightweight curses (terminal-based) interface to the GNU Debugger (GDB). In addition to the standard gdb console, cgdb provides a split screen view that displays the source code as it executes. The keyboard interface is modeled after vim, so vim users should feel at home using cgdb.
github repository