GDB - read.c: No such file or directory [duplicate] - c

I wanted to debug printf function, so when I step inside the printf function (gdb debugger) it showed me this:
__printf (format=0x80484d0 " my name is Adam") at printf.c:28
28 printf.c: No such file or directory.
What is the meaning of this?
And when I again started step then there are a lot more statements like this.
Please help me to understand this.

I think it's pretty clear. There is a place where the gdb expects the source code to be, so download glibc's source code and put it there. I think the error message contains the full path.
If it's a linux distro it's fairly simple in fact because usually source packages are shipped too. Otherwise you need to find the source code yourself, note that it MUST be exactly the same that was used to compile the c library components, not just the same version because distributors often make changes to the sources.

Well, for the debugger to show you the code that was compiled into the binaries you're using, you need the original code somewhere.
You don't seem to have that, so your debugger can't find it.
Notice that you usually do not want to debug the source code of your std library functions, but only the way they are being called. For that, the usual "debug symbol" packages of your operating systems are optimal.

As others have answered, GDB was unable to find the source file.
For the C runtime libraries, Linux distributions may provide a debuginfo RPM that you can install, which may allow GDB to view the files. For example:
$ yum search glibc-debuginfo
...
glibc-debuginfo.x86_64 : Debug information for package glibc
glibc-debuginfo-common.x86_64 : Debug information for package glibc
...
The glibc package and the glibc-debuginfo are a matched pair. There is no explicit dependency, but glibc-debuginfo package won't work unless it is matched with the same version of glibc.
If you have the sources unpacked somewhere, but not where GDB is expecting them to be, you can attempt to use either the directory or the set substitute-path command to let GDB know where the sources are.
The directory command tells GDB to prepend a prefix ahead of any source file path it is attempting to find. For example, if the source tree is actually located under the /tmp, you could use:
(gdb) directory /tmp
The set substitute-path command is used to tell GDB to replace a matching prefix in a source file path with a different path prefix. For example, if the compiled source file was in /build/path/source.c, but in debugging the source file is actually in /usr/home/alice/release-1.1/source.c, then you could use:
(gdb) set substitute-path /build/path /usr/home/alice/release-1.1
The command assumes that you are only specifying a complete path names, so it won't perform the substitution on /build/pathological/source.c.

Related

How do I link a compiled ".so" library with Scons?

I have an existing .so library (libgit2), and I would like to use this within a C program (the build system is Scons). I read through the entirety of the Scons documentation for "Chapter 4. Building and Linking with Libraries", but there is no mention of how to use an existing .so library. The only mention of .so in the entirety of chapter 4 is on the first page, and it is only about Scons using a .so file for output. How do I use an existing compiled .so library in Scons?
If you are using an sconscript then you should add a LIBS= arguments and a LIBS_PATH=.
if you want to directly add it to the build line, use -L for lib path and -l to link a lib.
You can find further information here: https://scons.org/doc/0.97/HTML/scons-user/x628.html
With help from the SCons Discord server and other places, I've gotten farther than when I first posted this question. I haven't solved my specific problem of using .so libraries with GDNative, but I think I've figured out the SCons side.
As of me posting this question, the SConstruct file was able to compile working code if I didn't use libgit2 and instead just printed out the text. With only the header included, my test call to git_libgit2_version compiled but didn't run, as Godot said undefined symbol: git_libgit2_version.
First of all, you need to add the named parameter for LIBS to your env.SharedLibrary or env.Program line. The lib prefix and .so suffix seem to be added automatically, I still haven't figured out how to make it point to libgit2.so.1.0.1 (so for now I have the library copied and named as libgit2.so, but I would like to have it point to libgit2.so.1.0.1 eventually instead). Also, the SCons team suggested adding LIBPATH, but this doesn't seem to actually do anything.
library = env.SharedLibrary(target=env["target_path"] + env["target_name"] , source=sources, LIBS=['git2'])
Then, the SConstruct file needs to have this magic line:
env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1
With the above code, ldd will report not found, and Godot will say Error: libgit2.so.1.0: cannot open shared object file: No such file or directory (I have no idea why it's asking for .so.1.0 instead of the .so or .so.1.0.1 file, and yes I tried copying and naming as libgit2.so.1.0 and that doesn't change anything either).
I also added this, which was suggested by another GDNative user.
env.Append(LINKFLAGS=[
'-Wl,-rpath,addons/git_for_godot/gdnative/linuxbsd'
])
With all of the above code, this seems to allow ldd and Godot to find the library just fine with a relative path (when running ldd you have to be cd'd into the project folder). I can run the project fine without any errors, but the project crashes immediately after opening, with no error messages printed. If I comment out the call to git_libgit2_version but keep the header included, the file does compile and run. Any time I try to call anything from libgit2 it causes Godot to crash without printing any errors. At this point I'm stuck and I don't know what I'm doing wrong.
I did try adding libgit2 to the Dependencies section of the .gdnlib file, but this doesn't seem to affect anything. Another thing I tried which didn't work is this line (+ variants on the extension) which append to the sources list passed as the named source parameter. I'll post it here for completeness, but for the moment I have this line commented out because it doesn't work:
sources.append(File("project/addons/git_for_godot/gdnative/linuxbsd/libgit2.so"))

How to debug standard c library functions like printf?

I wanted to debug printf function, so when I step inside the printf function (gdb debugger) it showed me this:
__printf (format=0x80484d0 " my name is Adam") at printf.c:28
28 printf.c: No such file or directory.
What is the meaning of this?
And when I again started step then there are a lot more statements like this.
Please help me to understand this.
I think it's pretty clear. There is a place where the gdb expects the source code to be, so download glibc's source code and put it there. I think the error message contains the full path.
If it's a linux distro it's fairly simple in fact because usually source packages are shipped too. Otherwise you need to find the source code yourself, note that it MUST be exactly the same that was used to compile the c library components, not just the same version because distributors often make changes to the sources.
Well, for the debugger to show you the code that was compiled into the binaries you're using, you need the original code somewhere.
You don't seem to have that, so your debugger can't find it.
Notice that you usually do not want to debug the source code of your std library functions, but only the way they are being called. For that, the usual "debug symbol" packages of your operating systems are optimal.
As others have answered, GDB was unable to find the source file.
For the C runtime libraries, Linux distributions may provide a debuginfo RPM that you can install, which may allow GDB to view the files. For example:
$ yum search glibc-debuginfo
...
glibc-debuginfo.x86_64 : Debug information for package glibc
glibc-debuginfo-common.x86_64 : Debug information for package glibc
...
The glibc package and the glibc-debuginfo are a matched pair. There is no explicit dependency, but glibc-debuginfo package won't work unless it is matched with the same version of glibc.
If you have the sources unpacked somewhere, but not where GDB is expecting them to be, you can attempt to use either the directory or the set substitute-path command to let GDB know where the sources are.
The directory command tells GDB to prepend a prefix ahead of any source file path it is attempting to find. For example, if the source tree is actually located under the /tmp, you could use:
(gdb) directory /tmp
The set substitute-path command is used to tell GDB to replace a matching prefix in a source file path with a different path prefix. For example, if the compiled source file was in /build/path/source.c, but in debugging the source file is actually in /usr/home/alice/release-1.1/source.c, then you could use:
(gdb) set substitute-path /build/path /usr/home/alice/release-1.1
The command assumes that you are only specifying a complete path names, so it won't perform the substitution on /build/pathological/source.c.

Issue Observed while using GDB

I am trying to debug my application which use one static builded library.
I want to set break points in my library so i tried to set it using below command :
break TS.cpp:600(FIle name:line no)
but it says
No source file named TS.cpp.
Make breakpoint pending on future shared library load?(y or [n])
so I presses y here (I came to know after browsing internet) but after pressing y gdb is not stopping at my break point and it completed executing program.
Why GDB is not stopped at my break point??
Any input is highly appreciated.
No source file named TS.cpp
This means one of two things:
either the file TS.cpp was not compiled with -g (or equivalently TS.o has been stripped), or
the file TS.o was not linked into the application.
Since you are seeing prints from that source, it's a safe bet that #1 is the actual root cause.
info sources command shows only my application.c and not the files of my library
That is another confirmation that #1 is the root cause.
The problem in your case is with source mapping. It normally happens when application is compiled at some other machine and you are debugging it on some other machine where source location is different.
You can specify source path using directory command of gdb. e.g. if your sources are in /home/taimoor/testApp/src, you can do following:
(gdb) directory /home/taimoor/testApp/src

How to read, understand, analyze, and debug a Linux kernel panic?

Consider the following Linux kernel dump stack trace; e.g., you can trigger a panic from the kernel source code by calling panic("debugging a Linux kernel panic");:
[<001360ac>] (unwind_backtrace+0x0/0xf8) from [<00147b7c>] (warn_slowpath_common+0x50/0x60)
[<00147b7c>] (warn_slowpath_common+0x50/0x60) from [<00147c40>] (warn_slowpath_null+0x1c/0x24)
[<00147c40>] (warn_slowpath_null+0x1c/0x24) from [<0014de44>] (local_bh_enable_ip+0xa0/0xac)
[<0014de44>] (local_bh_enable_ip+0xa0/0xac) from [<0019594c>] (bdi_register+0xec/0x150)
In unwind_backtrace+0x0/0xf8 what does +0x0/0xf8 stand for?
How can I see the C code of unwind_backtrace+0x0/0xf8?
How to interpret the panic's content?
It's just an ordinary backtrace, those functions are called in reverse order (first one called was called by the previous one and so on):
unwind_backtrace+0x0/0xf8
warn_slowpath_common+0x50/0x60
warn_slowpath_null+0x1c/0x24
ocal_bh_enable_ip+0xa0/0xac
bdi_register+0xec/0x150
The bdi_register+0xec/0x150 is the symbol + the offset/length there's more information about that in Understanding a Kernel Oops and how you can debug a kernel oops. Also there's this excellent tutorial on Debugging the Kernel
Note: as suggested below by Eugene, you may want to try addr2line first, it still needs an image with debugging symbols though, for example
addr2line -e vmlinux_with_debug_info 0019594c(+offset)
Here are two alternatives for addr2line. Assuming you have the proper target's toolchain, you can do one of the following:
Use objdump:
locate your vmlinux or the .ko file under the kernel root directory, then disassemble the object file :
objdump -dS vmlinux > /tmp/kernel.s
Open the generated assembly file, /tmp/kernel.s. with a text editor such as vim. Go to
unwind_backtrace+0x0/0xf8, i.e. search for the address of unwind_backtrace + the offset. Finally, you have located the problematic part in your source code.
Use gdb:
IMO, an even more elegant option is to use the one and only gdb. Assuming you have the suitable toolchain on your host machine:
Run gdb <path-to-vmlinux>.
Execute in gdb's prompt: list *(unwind_backtrace+0x10).
For additional information, you may checkout the following resources:
Kernel Debugging Tricks.
Debugging The Linux Kernel Using Gdb
In unwind_backtrace+0x0/0xf8 what the +0x0/0xf8 stands for?
The first number (+0x0) is the offset from the beginning of the function (unwind_backtrace in this case). The second number (0xf8) is the total length of the function. Given these two pieces of information, if you already have a hunch about where the fault occurred this might be enough to confirm your suspicion (you can tell (roughly) how far along in the function you were).
To get the exact source line of the corresponding instruction (generally better than hunches), use addr2line or the other methods in other answers.

Installing a new library in Linux, and accessing it from my C code

I am working on a project which requires me to download and use this. Inside the downloaded folder, when extracted I am presented with three things:
A folder called "include"
A folder called "src"
A file called "Makefile"
After some research, I found out that I have to navigate to the directory which contains these files, and just type in the command make.
It seemed to install the library in my system. So I tried a sample bit of code which should use the library:
csp_conn_t * conn;
csp_packet_t * packet;
csp_socket_t * socket = csp_socket(0);
csp_bind(socket, PORT_4);
csp_listen(socket, MAX_CONNS_IN_Q);
while(1) {
conn = csp_accept(socket, TIMEOUT_MAX);
packet = csp_read(conn, TIMEOUT_NONE);
printf(ā€œ%S\r\nā€, packet->data);
csp_buffer_free(packet);
csp_close(conn);
}
That's all that was given for the sample server end of the code. So I decided to add these to the top:
#include <csp.h>
#include <csp_buffer.h>
#include <csp_config.h>
#include <csp_endian.h>
#include <csp_interface.h>
#include <csp_platorm.h>
Thinking I was on the right track, I tried to compile the code with gcc, but I was given this error:
csptest_server.c:1: fatal error: csp.h: No such file or directory
compilation terminated.
I thought I may not have installed the library correctly after all, but to make sure, I found out I could check by running this command, and getting this result:
find /usr -iname csp.h
/usr/src/linux-headers-2.6.35-28-generic/include/config/snd/sb16/csp.h
/usr/src/linux-headers-2.6.35-22-generic/include/config/snd/sb16/csp.h
So it seems like the csp.h is installed, maybe I am referencing it incorrectly in the header include line? Any insight? Thanks a lot.
The make command is probably only building the library, but not installing it. You could try sudo make install. This is the "common" method, but I recommend you to check the library's documentation, if any.
The sudo command is only necessary if you have no permissions to write the system's include and library directories, which may be your case.
Another possibility (instead of installing the library) is telling GCC the location of the library's source code and generated binaries (by means of the -I and -L options of the gcc command.
That Makefile will not install anything, just translate the source into a binary format.
The csp.h in the Linux kernel has nothing to do with your project, it's just a naming collision, likely to happen with three letter names.
In your case, I would presume you need to add the include directory to the compilation flags for your server, like gcc -I/path/to/csp/include/csp csptest_server.c.
(Next, you'll run into linker errors because you'll also want to specify -L/path/to/csp -lcsp so that the linker can find the binary code to link to.)

Resources