How can you extract the sizes of all C structures from an ELF object file with debugging symbols?
Individual struct sizes can be obtained from GDB using "print sizeof(some_struct)", but what I need is to get a listing of all structures.
I've looked at "nm" and "objdump", but I don't see options to do what I'm looking for. Is there a way to do this with standard Unix tools, or do I need to extract the debug symbol section from the ELF file and process it myself? I'm hoping it's not the latter.
Thanks in advance for any advice.
Ray
pahole shows this and other details about structs. Its git repo is at http://www.kernel.org/git/?p=linux/kernel/git/acme/pahole.git;a=summary.
You will have to dig in .debug_info section, objdump will dump it for you if you run it with --dwarf parameter.
You will see your structures there as *DW_TAG_structure_type* and *DW_AT_byte_size* attribute is equivalent to sizeof. Standard Unix tool should be enough to format this data into more readable list.
Install package dwarves, then you have the command "pahole".
Use the "pahole" command against a elf object file, you can get all the structure information, or you can use the "-C" parameter to specific a structure name, for example:
$ pahole vmlinux -C task_struct
Unless someone else known something, I think you will have to process the output of nm .
However, nm only gives you the start of each struct and knows nothing about its end so even that may not work unless each strut is immediately followed by some other symbol. Watch out for this issue!
Related
I am trying to print all the Undefined function calls from a shared object file along with file name.
I tried with "nm" command, It print all the undefined function calls .But could not get the file name.
Example:
bash$ nm -u my_test.so
:
U _ZNSs4_Rep20_S_empty_rep_storageE##GLIBCXX_3.4
:
Environment : Ubuntu 18.04 , X86 Arch (Intel processor)
Study in details the specification of the DWARF format (which is the format used by debugging information on Linux). So you could extract the information (but it is not exactly simple) by parsing the DWARF inside your ELF binary.
Consider looking inside the source code of Ian Taylor's libbacktrace. It is doing this extraction of file name from DWARF inside ELF.
Perhaps your real problem is getting precise backtrace information, and then that libbacktrace is exactly what you need!
You might also use gdb : it is extensible and scriptable in Python (or Guile) and you could write your own specialized script.
Perhaps you'll better solve your real problem with some GCC plugin working when you compile your code.
Read How to write shared libraries by Drepper and read more about ELF.
You could for example collect all the undefined symbols in your shared library using nm (or readelf). Then a second script will find the occurrences of these in your source code. It could be even a simple awk script (or some for shell loop using grep), or something as sophisticated as a GCC plugin.
Your example shows (probably) a mangled C++ name. You could use nm -C to get it unmangled. And later write a GCC plugin to find all the GIMPLE CALL instructions using it.
Writing a GCC plugin may take some time, in particular if you are not familiar with GCC internals.
I wanted to read the architecture information about object(.so) files example x86, x86_64, armeabi, armeabi-v7a, mips etc from the file and display these information. I know I can use "file" or other Linux commands to get this info, But I wanted to use the kernel structure to get above values.
I went through the ELF header file but not getting much help.
Can someone please suggest how to proceed for this?
A elf binary contains a elf-header at the beginning of the file. You can read this header by any elf-reader program, and here I will give you the example for readelf
readelf -h <binaryFile>
For more information, you could read the ELF Format Specification to learn about how elf binaries are loaded & executed.
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.
The requirement is to use GNU strip to discard the symbols from an object file, and save the symbols. Later on, if there are any core dumps of this object file, we have to include the symbols to check the core dumps. How can we accomplish this task? Thanks in advance!
The simple solution would be to keep a copy of the binary before you strip it. Then you can use the unstripped version to investigate the core dump as these binaries will be identical except for the stripped symbol information.
So, if you have a FOO binary, do something like:
cp FOO FOO.unstripped
strip FOO
then run FOO and when you investigate the coredump, use FOO.unstripped.
Different ways to get a "symbol file" are discussed here:
How to generate gcc debug symbol outside the build target?
Actually, the linked question is very similar to this one.
I'm looking for a convenient way (for use in a build testing script) to query individual symbols in an object file. Is there a tool that can answer the question (preferably by its exit status) "does symbol X exist in file Y?" or do I just need to parse the output of nm(1), e.g. with grep and an appropriate regex? Even better would be if such a tool could give detailed information on the symbol (size, type, value, ...).
For an executable/shared library, give readelf or Objdump a look over, they can dump a binaries symbols (mangled or unmangled), which you should be able to grep.
Their source is easily obtainable, so you could probably taloir them down into simpler tools for the task at hand or directly import their code base (not that you really need to, you could just load the binary with in question with dlopen and use dlsym to check if the symbol is there).
Objdump is geared towards binaries, nm and readelf will read elf object files.
You could use libbfd directly, but glancing through the API it isn't obvious how to get straight to the information you want.