Combining a lib and it's debug symbols to produce source-interleaved disassembly - glibc

I've both libc6 and libc6-dbg packages installed. What I want to do is to display the disassembly of ld.so with source interleaved. I also have the glibc source placed in a chroot, reachable at the exact location as displayed by DW_AT_comp_dir in debug symbols.
Could someone tell me--if it's possible--how to output the source-interleaved disassembly of ld.so library please? I know I could use objdump -S, but how would I point it to the separate debug symbol file available?

The best match I could find was to use GDB:
gdb /the/original/library
Use add-symbol-file command to locate the add the symbol file that was installed as part of -dbg package (use dpkg -L the-package-name-dbg to find all files installed as part of the package). This command would also need an address to load the symbols from. This address can be found out from readelf -a /the/original/library, and is most likely the load address of the text segment
Install package source with apt-get source the-package-name. This will download the source in the current working directory
Use dir command in GDB to locate the source downloaded above
Now use disas/m function_name so that GDB will display a the disassembly, ordered by source lines

Related

Inspect and get binary from ELF file on MAC

I have a ELF file and I want to get a hex or bin file of my code from it. In the terminal, if a do a file main, which is my file, it shows:
main: ELF 32-bit LSB executable, UCB RISC-V, version 1 (SYSV), statically linked, not stripped
As I learned, objdump on MAC is not working and with otool -l main I get the following error:
llvm-objdump: 'main': Object is not a Mach-O file type.
The ELF file was created using the command:
riscv-none-gcc/8.2.0-2.1-20190425-1021/bin/riscv-none-embed-gcc --specs=nosys.specs main.c -o main
So is there a way to do it?
Thanks a lot
For creating "raw binary files"
the program objcopy
can be used, as described here:
objcopy -O binary foo.elf foo.bin
The program objcopy is part of the MacPorts
package x86_64-elf-binutils,
and can be used as follows:
/opt/local/bin/x86_64-elf-objcopy -O binary foo.elf foo.bin
where foo.elf is an ELF file compiled on (or cross-compiled for) an x86_64
Linux. The MacPorts package x86_64-elf-binutils can be installed as follows:
port install x86_64-elf-binutils
The program objcopy is part of binutils.
For Mach-O, it can be installed on macOS via the package binutils
of MacPorts, as follows:
port install binutils
The MacPorts binutils package installs gobjcopy.
Versions of binutils on macOS for cross-development for other target systems,
too, are available
via MacPorts.
This post is motivated also by MacOSX: which dynamic libraries linked by binary?,
and is intended to be also informational.
Executables can be:
ELF on Linux
Mach-O on macOS
ldd
ldd is a script in Linux
that wraps ld. It is described as
print shared object dependencies
The GNU ld is unavailable on macOS. More fundamentally, that ldd calls ld
means that its operation is non-static, in contrast to tools like readelf,
objdump, and nm.
In that sense, even if certain information is obtainable using tools other
than ldd, the results are not equivalent, because the other tools do not
attempt to load the binary. Moreover, attempting to load a binary requires
being on a Linux, so ldd is
genuinely a Linux tool that cannot be emulated exactly by a program on macOS.
A relevant description.
There does exist a pure-Python implementation that approximates ldd without
loading binaries the way that ld does: lddcollect.
Using lddcollect is possible on a Linux system, where the required libraries
are present.
One reason to not use ldd is security: inspecting executables without
executing them.
ldd is an initialism for
"List Dynamic Dependencies".
ldd appears to be a bash script that is part of glibc, with source code at:
https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/ldd.bash.in;h=ba736464ac5e4a9390b1b6a39595035238250232;hb=271ec55d0ae795f03d92e3aa61bff69a31a19e3a
Relevant: What is the difference between ldd and objdump?
Relevant: cross compiler ldd
objdump
objdump shows information about
object files, and can disassemble them. It is part of binutils.
Programs that are called objdump on macOS:
/opt/local/bin/gobjdump by the MacPorts package binutils
/usr/bin/objdump by macOS (part of package com.apple.pkg.Essentials),
which is described as the
llvm object file dumper
The manual of ldd suggests calling objdump as an alternative, as follows:
objdump -p /path/to/program | grep NEEDED
Relevant: https://superuser.com/questions/206547/how-can-i-install-objdump-on-mac-os-x
readelf
readelf displays information about
ELF files by reading them (static, not loading them). It is part of binutils.
It does not disassemble files, like objdump can.
Variants available on macOS:
/opt/local/bin/greadelf from the MacPorts package binutils
/opt/local/bin/elftc-readelf from the MacPorts package elftoolchain
Example usage:
readelf -s elf_file
nm
/usr/bin/nm by macOS (part of package com.apple.pkg.Essentials)
/opt/local/bin/nm by the MacPorts package cctools,
which is a symbolic link: /opt/local/bin/nm -> llvm-nm-mp-10
/opt/local/bin/nm-classic by the MacPorts package cctools
/opt/local/bin/elftc-nm by the MacPorts package elftoolchain
/opt/local/bin/gnm by the MacPorts package binutils
Apparently, both /usr/bin/nm and /opt/local/bin/nm are versions of the
llvm symbol table dumper
and do work with ELF files.
otool (and variants)
otool is the the disassembler for MacOS's Mach-O format.
Variants of otool available on macOS:
/usr/bin/otool by macOS (part of package com.apple.pkg.Essentials)
/opt/local/bin/otool by the MacPorts package cctools,
which links to /opt/local/bin/llvm-otool by the MacPorts package cctools,
which is described as:
the otool-compatible command line parser for llvm-objdump
/opt/local/bin/otool-classic by the MacPorts package cctools
More details:
> which -a otool
/opt/local/bin/otool
/usr/bin/otool
> ls -lsa /opt/local/bin/otool
... /opt/local/bin/otool -> llvm-otool
> port provides /opt/local/bin/otool
/opt/local/bin/otool is provided by: cctools
> which -a llvm-otool
/opt/local/bin/llvm-otool
> port provides /opt/local/bin/llvm-otool
/opt/local/bin/llvm-otool is provided by: cctools
> ls -lsa /usr/bin/otool
... /usr/bin/otool
> pkgutil --file-info /usr/bin/otool
volume: /
path: /usr/bin/otool
pkgid: com.apple.pkg.Essentials
...
The MacPorts package cctools installs also /opt/local/bin/otool-classic,
which, as said in its documentation, is obsolete.
elfdump
elfdump is available on macOS via the MacPorts package elftoolchain,
and installed as the binary /opt/local/bin/elftc-elfdump.
strings
The program strings can be
useful for inspecting the symbols contained in an ELF file. It is a more
general tool, not designed specifically for ELF files, but usable nonetheless.
Variants of strings on macOS:
/usr/bin/strings by macOS (part of package com.apple.pkg.Essentials)
/opt/local/bin/strings from the MacPorts package cctools
/opt/local/bin/elftc-strings from the MacPorts package elftoolchain
/opt/local/bin/gstrings from the MacPorts package binutils
Example usage (piping to ag):
strings some_elf_file | ag GLIBC
elftc-strings appears to have fewer options and give fewer results than
the other strings implementations (which differ with each other, but seem
to print similar results).
elftoolchain
Available via MacPorts, elftoolchain
is a BSD-licensed library of tools like those in binutils. Tools from that
collection that are relevant to analyzing ELF files:
/opt/local/bin/elftc-elfdump
/opt/local/bin/elftc-nm
/opt/local/bin/elftc-readelf
/opt/local/bin/elftc-strings
There are also plans for
implementing objdump.
Confirming that a binary is from MacPorts
To find out whether a given file is part of MacPorts:
> port provides /opt/local/bin/otool
/opt/local/bin/otool is provided by: cctools
Discussed in this answer.
Confirming that a binary is from macOS
Also useful for finding out how each
of the tools discussed above was installed is pkgutil:
pkgutil --file-info /usr/bin/objdump
This can be useful to confirm that a binary was part of macOS itself, and not
installed by other means.
Confirming that an executable is an ELF
This text was motivated when I wanted to analyze an executable with the
following details:
> file filename
ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=..., for GNU/Linux 3.2.0, not stripped
As for other tools, there are multiple options for file on macOS:
/usr/bin/file by macOS (part of package com.apple.pkg.Essentials)
/opt/local/bin/file by the MacPorts package file
Other tools
Apparently, on some operating systems there are also elftools available.
For analyzing files for specific architectures, there are MacPorts packages
like arm-elf-binutils.
DWARF
There is also DWARF and dwarftool,
as well as dwarfdump (part of XCode).
Miscellanea
binutils can analyze Mach-O on Linux: https://stackoverflow.com/a/8714142/1959808
darling can be used on Linux to run
macOS software (Mach-O, dyld), it is analogous to wine

kgdb refused to be able to access symbols for just one certain driver, nor do those symbols appear in vmlinux

I'm trying to debug a driver.
gdb says...
(gdb) break i2c-hid.c:i2c_hid_suspend
No source file named i2c-hid.c.
Breakpoint 9 (i2c-hid.c:i2c_hid_suspend) pending.
nm vmlinux --- does not find any function names from within that file.
cat /proc/kallsyms --- shows all the functions names contained in that file.
I added this to the Makefile "EXTRA_CFLAGS += -DI2C-HID_DEBUG -g" to no avail.
Does anyone know what I need to do to make gdb able to see the symbols from this file?
I get symbol level debugging for plenty of other drivers.
It looks like i2c-hid.c is not part of vmlinux, which means it is outside of basic kernel. That is why nm vmlinux does not show symbols related to this file.
cat /proc/kallsyms will show those symbols because it shows all the kernel symbols inclunding drivers' symbols which are not part of vmlinux.
I am not sure whether you are using gdb or kgdb, but I think to debug drivers, you need to use kgdb, not gdb.
If you are already using kgdb, then use add-symbol-file command under it. It will help you load symbols which are outside vmlinux. Simple google search will give you lot of information of add-symbol-file.
When debugging Linux kernel, GDB does not automatically load symbols for kernel modules like it would do for user-mode shared libraries. Instead you need to load them manually using the following command:
add-symbol-file <kernel module>.o <core address> -s <sectionX> <addressX> -s <...>
You can find out the core address of the module (and the addresses of all sections) by setting a breakpoint in the do_init_module() function and examining the mod variable once the breakpoint is hit:
print mod->name
print mod->module_core
print *mod->sect_attrs->attrs#mod->sect_attrs->nsections
You can read more about loading kernel module symbols in the Linux kernel symbol overview.

Warnings when running GDB installed from Macports/Brew

I have been trying to install GDB on my new Macbook Pro running Mountain Lion. I have installed using both Macports and Brew, I have successfully code signed the binaries, but in both cases when I try to debug a simple "Hello World" application I receive a whole load of warnings similar to:
warning: `/Users/gkhanna/build/x86_64-apple-darwin13.0.0/libgfortran/.libs/_abs_c10.o': can't open to read symbols: No such file or directory.
warning: `/Users/gkhanna/build/x86_64-apple-darwin13.0.0/libgfortran/.libs/_abs_c16.o': can't open to read symbols: No such file or directory.
warning: `/Users/gkhanna/build/x86_64-apple-darwin13.0.0/libgfortran/.libs/_abs_c4.o': can't open to read symbols: No such file or directory.
warning: `/Users/gkhanna/build/x86_64-apple-darwin13.0.0/libgfortran/.libs/_abs_c8.o': can't open to read symbols: No such file or directory.
Now, my username is not gkhanna and there are no users registered on the laptop by that name. The versions of gdb I have installed are 7.6.0 and 7.6.1. Could anybody explain what has happened here and how to point GDB to the correct path?
To quiet the warnings, you can strip the debugging symbols that can't be read (since they point to files not on your machine and really shouldn't have been left in there in the first place.)
First, figure out which libgfortran dylib your gcc is using with otool -L a.out, then strip the debug symbols from that libgfortran dylib with strip -x path_to_libgfortran_dylib.

How to specify non-default shared-library path in GCC Linux? Getting "error while loading shared libraries" when running

There is a laptop on which I have no root privilege.
onto the machine I have a library installed using configure --prefix=$HOME/.usr .
after that, I got these files in ~/.usr/lib :
libXX.so.16.0.0
libXX.so.16
libXX.so
libXX.la
libXX.a
when I compile a program that invokes one of function provided by the library with this command :
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX
xxx.out was generated without warning, but when I run it error like this was thrown:
./xxx.out: error while loading shared libraries: libXX.so.16: cannot open shared object file: No such file or directory , though libXX.so.16 resides there.
my clue-less assumption is that ~/.usr/lib wasn't searched when xxx.out is invoked.
but what can I do to specify path of .so , in order that xxx.out can look there for .so file?
An addition is when I feed -static to gcc, another error happens like this:
undefined reference to `function_proviced_by_the_very_librar'
It seems .so does not matter even though -L and -l are given to gcc.
what should I do to build a usable exe with that library?
For other people who has the same question as I did
I found a useful article at tldp about this.
It introduces static/shared/dynamic loaded library, as well as some example code to use them.
There are two ways to achieve that:
Use -rpath linker option:
gcc XXX.c -o xxx.out -L$HOME/.usr/lib -lXX -Wl,-rpath=/home/user/.usr/lib
Use LD_LIBRARY_PATH environment variable - put this line in your ~/.bashrc file:
export LD_LIBRARY_PATH=/home/user/.usr/lib
This will work even for a pre-generated binaries, so you can for example download some packages from the debian.org, unpack the binaries and shared libraries into your home directory, and launch them without recompiling.
For a quick test, you can also do (in bash at least):
LD_LIBRARY_PATH=/home/user/.usr/lib ./xxx.out
which has the advantage of not changing your library path for everything else.
Should it be LIBRARY_PATH instead of LD_LIBRARY_PATH.
gcc checks for LIBRARY_PATH which can be seen with -v option

How do I tell gcc (or ld) to link against debug versions of the standard c and c++ libraries

I have debug versions of libstdc++ and libc, among others, and would like to link against them. They live in /usr/lib/debug as opposed to /usr/lib. Any ideas?
I believe the accepted answer is misleading in that the libraries in /usr/lib/debug is not a debug compiled (-g -O0 ...) version of libraries in /lib,/usr/lib but simply debug symbols stripped from the corresponding library in /lib,/usr/lib. See the explanation the accepted answers to How to use debug version of libc and for How to link against debug versions of libc and libstdc++ in GCC? more details.
Quotes:
The libraries in /usr/lib/debug are not real libraries. Rather, the contain only debug info, but do not contain .text nor .data sections of the real libc.so.6
and
On many Linux installations the debug libraries do not contain real code; they only contain the debug info. The two are separated so that you can choose not to install them if you don't need them and you are short of disk space, but the debug libraries are no good on their own.
Check yourself with:
objdump -h /usr/lib/debug/lib/x86_64-linux-gnu/libc-2.19.so | grep -C1 text
11 .text 001488a3 000000000001f520 000000000001f520 000002b4 2**4
ALLOC, READONLY, CODE
The .text segment is ALLOC but without CONTENTS. Compare with the corresponding library in /lib/x86_64-linux-gnu/libc-2.19.so:
$ objdump -h /lib/x86_64-linux-gnu/libc-2.19.so | grep -C1 text
11 .text 001488a3 000000000001f520 000000000001f520 0001f520 2**4
CONTENTS, ALLOC, LOAD, READONLY, CODE
Assuming Linux,
Static libraries: add a -L/usr/lib/debug to your linker command line. gcc/ld will look there before default system directories. Use ldd command to verify that correct library versions were linked against (shared libraries only).
Shared libraries: set LD_LIBRARY_PATH=usr/lib/debug, and your application will pick up libraries from there even without step 1, as long as there is a version of a library, which is very likely if you are installing with distribution's package manager.
It's a good idea to do both, though, as some libraries may be only in static form.
Use linker flags. ld/gcc -L<LIBRARY_PATH> is important for link time only, regardless shared or static, you cannot link against library, if linker can't find it.
For shared libraries environment variable LD_LIBRARY_PATH is important for start up time. Dynamic libraries loader ld.so and ld-linux.so will look up there when you start your application.

Resources