For a binary with embedded bitcode (i.e., compiled with -fembed-bitcode). How can i just extract that section such that I can use that bitcode file like any other bitcode file e.g, run opt or llvm-dis
As a testcase i have this hello-world program:
// hello.cpp
#include<iostream>
int main() {
std::cout << "hello world";
return 0;
}
compiled with: clang++ -O2 test.cpp -o test.o -fembed-bitcode -c
the objdump shows there is a __bitcode section in there:
objdump -h test.o
test.o: file format Mach-O 64-bit x86-64
Sections:
Idx Name Size Address Type
0 __text 000002eb 0000000000000000 TEXT
1 __gcc_except_tab 00000068 00000000000002ec DATA
2 __cstring 0000000c 0000000000000354 DATA
3 __bitcode 00002bc0 0000000000000360 DATA
4 __cmdline 00000046 0000000000002f20 DATA
5 __compact_unwind 00000060 0000000000002f68 DATA
6 __eh_frame 000000d0 0000000000002fc8 DATA
Now as per https://github.com/llvm/llvm-project/blob/master/llvm/test/tools/llvm-objcopy/MachO/dump-section.test, I'm trying to extract the __bitcode section in the following way:
# Take1
./bin/llvm-objcopy --dump-section=DATA,__bitcode=a.bc test.o
./bin/llvm-objcopy: error: 'test.o': section 'DATA,__bitcode' not found
# Take2
./bin/llvm-objcopy --dump-section=__bitcode=a.bc test.o
./bin/llvm-objcopy: error: 'test.o': section '__bitcode' not found
# Take3
./bin/llvm-objcopy --dump-section __DATA,__bitcode=a.bc test.o
./bin/llvm-objcopy: error: 'test.o': section '__DATA,__bitcode' not found
# Take4
./bin/llvm-objcopy --dump-section=__DATA,__bitcode=a.bc test.o
./bin/llvm-objcopy: error: 'test.o': section '__DATA,__bitcode' not found
What am I missing here?
Actually the __bitcode is in LLVM section. so the following commands worked.
llvm-objcopy --dump-section=__LLVM,__bitcode=a.bc test.o
segedit test.o -extract __LLVM __bitcode a.bc
Seems like a bug in objdump, it doesn't recognize the LLVM section.
Related
I'm trying to get gdb working with C++ programs on Ubuntu 20.04. What I need is to be able to set a breakpoint (for example, break main.cpp:3 gdb command) and then run until the breakpoint, but at the moment both start and run fail because they "Cannot insert breakpoint" and "Cannot access memory". For me gdb fails even with very simple examples. This is main.cpp content:
#include <iostream>
int main() {
std::cout << "Hello World!";
return 0;
}
I found somewhere that using -no-pie might help to get gdb working (with breakpoints), so I compile the program by running g++ -ggdb3 -no-pie -o main main.cpp (I also tried -g instead of -ggdb3, and -fno-PIE in addition to -no-pie). When I try to use gdb, it complains "Cannot insert breakpoint 1":
gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
Without -no-pie result is the same. Only thing that changes with or without -no-pie is the hexadecimal address, without -no-pie it is low like 0x1189 (as shown above), with -no-pie it can be 0x401176, but everything else exactly the same, I keep getting the "Cannot access memory at address" warning in both cases.
If I use starti instead of start, it works at first, but after a few nexti iterations it prints usual message "Cannot insteart breakpoint":
gdb -q main
Reading symbols from main...
(gdb) starti
Starting program: /tmp/main
Program stopped.
0x00007ffff7fd0100 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd0103 in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x4
0x00007ffff7fd0119 in ?? () from /lib64/ld-linux-x86-64.so.2
(gdb) nexti
0x00007ffff7fd011c in ?? () from /lib64/ld-linux-x86-64.so.2
...
(gdb) nexti
Warning:
Cannot insert breakpoint 0.
Cannot access memory at address 0x1c
0x000055555556ca22 in ?? ()
(gdb) nexti
[Detaching after fork from child process 3829827]
...
[Detaching after fork from child process 3829840]
Hello World![Inferior 1 (process 3819010) exited normally]
So I can use nexti, but cannot use next and obviously cannot insert breakpoints.
I tried -Wl,-no-pie (by running g++ -Wl,-no-pie -ggdb3 -o main main.cpp; adding -no-pie does not change anything) but this option causes a strange linker error:
/usr/bin/ld: cannot find -lgcc_s
/usr/bin/ld: cannot find -lgcc_s
collect2: error: ld returned 1 exit status
When I google the error, I only found advice to try -no-pie instead of -Wl,-no-pie, and no other solutions. Since debugging C++ programs is very common activity, I feel like I'm missing something obvious but I found no solution so far.
To make it easier to understand what exact commands I use and to make it clear I'm not mixing up directories and to show what versions of g++ and gdb I'm using, here is full terminal log:
$ ls
main.cpp
$ g++ --version | grep Ubuntu
g++ (Ubuntu 9.3.0-10ubuntu2) 9.3.0
$ g++ -ggdb3 -no-pie -o main main.cpp
$ ls
main main.cpp
$ gdb --version | grep Ubuntu
GNU gdb (Ubuntu 9.2-0ubuntu1~20.04) 9.2
$ readelf -h main | grep 'Type: .*EXEC'
Type: EXEC (Executable file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x401176: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x401176
For completeness, I tried the same without -no-pie:
$ rm main
$ g++ -ggdb3 -o main main.cpp
$ readelf -h main | grep 'Type: .*'
Type: DYN (Shared object file)
$ gdb -q main
Reading symbols from main...
(gdb) start
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
Starting program: /tmp/main/main
Warning:
Cannot insert breakpoint 1.
Cannot access memory at address 0x1189
As you can see the only difference with or without -no-pie is the memory address, but the issue and warnings are the same. Without -no-pie this may be expected, but I do not understand why this is happening if I compiled with -no-pie and what else I can try to solve the issue.
This:
g++ -ggdb3 -no-pie -o main main.cpp
should produce a non-PIE executable. You should be able to verify that it non-PIE by looking at readelf -h main | grep 'Type: .*EXEC' (PIE binaries have ET_DYN type).
This:
Temporary breakpoint 1 at 0x1189: file main.cpp, line 3.
is unambiguously a PIE binary (a non-PIE binary will not have any code below 0x40000 on x86_64 Linux).
Conclusion: you are either debugging the wrong binary (e.g. you are compiling main in a different directory from the one in which you are debugging), or you are not telling is the whole story.
I am using Cygwin 32-bit under Win7 in a 64-bit machine.
The following program
makefile:
runme: main.cpp asm.o
g++ main.cpp asm.o -o executable
asm.o: asm.asm
nasm -f elf asm.asm -o asm.o
asm.asm:
section .data
section .bss
section .text
global GetValueFromASM
GetValueFromASM:
mov eax, 9
ret
main.cpp:
#include <iostream>
using namespace std;
extern "C" int GetValueFromASM();
int main()
{
cout<<"GetValueFromASM() returned = "<<GetValueFromASM()<<endl;
return 0;
}
is giving me the following error:
$ make
nasm -f elf asm.asm -o asm.o
g++ main.cpp asm.o -o executable
/tmp/cc3F1pPh.o:main.cpp:(.text+0x26): undefined reference to `GetValueFromASM'
collect2: error: ld returned 1 exit status
make: *** [makefile:2: runme] Error 1
I am not understanding why this error is being generated.
How can I get rid of this issue?
You have to prefix your symbols with _, as is customary in Windows/Cygwin:
section .data
section .bss
section .text
global _GetValueFromASM
_GetValueFromASM:
mov eax, 9
ret
The rest of your code should work fine.
An alternative would be to compile with -fno-leading-underscore. However, this may break linking with other (Cygwin system) libraries. I suggest using the first option if portability to other platforms does not matter to you.
Quoting from the GNU Online Docs:
-fleading-underscore
This option and its counterpart, -fno-leading-underscore, forcibly change the way C symbols are represented in the object file. One use is to help link with legacy assembly code.
Warning: the -fleading-underscore switch causes GCC to generate code that is not binary compatible with code generated without that switch. Use it to conform to a non-default application binary interface. Not all targets provide complete support for this switch.
I always use gdb in Linux and it works ok, this is my first time use gdb in mac which is different with Linux.
(gdb) b main
Breakpoint 1 at 0x100000ec4
(gdb) r
Starting program: /Users/vinllen/code/tmp/lhm/homework
warning: Could not open OSO archive file "/BinaryCache/corecrypto/corecrypto-233.1.2~26/Symbols/BuiltProducts/libcorecrypto_static.a"
warning: `/BinaryCache/coreTLS/coreTLS-35.20.2~10/Objects/coretls.build/coretls.build/Objects-normal/x86_64/system_coretls_vers.o': can't open to read symbols: No such file or directory.
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_ciphersuites.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_handshake.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_record.a"
warning: Could not open OSO archive file "/BinaryCache/coreTLS/coreTLS-35.20.2~10/Symbols/BuiltProducts/libcoretls_stream_parser.a"
Breakpoint 1, 0x0000000100000ec4 in main ()
(gdb) l
No symbol table is loaded. Use the "file" command.
(gdb) n
Single stepping until exit from function main,
which has no line number information.
It looks like command l and n cannot be execute correctly, what's the problem ?
Here is my Makefile:
objects = main.o conversion.o slitemlist.o uims.o testdrivers.o
homework:$(objects)
g++ -o homework $(objects)
conversion.o: conversion.h base.h
slitemlist.o: slitemlist.h base.h
uims.o: conversion.h base.h conversion.h slitemlist.h
testdrivers.o: testdrivers.h
.PHONY: clean
clean:
rm homework $(objects)
Here is my Makefile:
You will not have a good time debugging this program on Linux either: you've compiled it without debug symbols (the -g flag).
Your real question is not "how do I use GDB on MacOS", but rather "how do I write Makefile such that I can debug".
You should add a lines like this to your Makefile:
CFLAGS = -g
CXFLAGS = -g # if building C++
I am trying to get a very simple program to compile while using functions from libpano13, but I am running into linking errors. I am on Ubuntu 10.04, and have done the following:
sudo apt-get install libpano13-dev
My sample program is as follows:
#include <cstring>
#include <pano13/PTcommon.h>
int main(int argc, char **argv) {
fullPath *outFile = new fullPath();
StringtoFullPath(outFile, (char *)"/tmp/randomImage.jpg");
return 0;
}
I am attempting to compile this with the following command (the above code is located in a file called panoTest.cpp):
$ g++ panoTest.cpp -o testApp -L/usr/lib -lpano13
When I run this command I get the following error:
$ g++ panoTest.cpp -o testApp -L/usr/lib -lpano13
/tmp/ccyIioEi.o: In function `main':
panoTest.cpp:(.text+0x87): undefined reference to `StringtoFullPath(fullPath*, char*)'
collect2: ld returned 1 exit status
make: *** [all] Error 1
Now, I've checked /usr/lib for libpano* and found the following files:
$ ls /usr/lib/libpano*
/usr/lib/libpano13.a /usr/lib/libpano13.so /usr/lib/libpano13.so.1
/usr/lib/libpano13.so.1.0.0
I've checked libpano13.so using nm and got the following output:
$ nm --demangle /usr/lib/libpano13.a | grep StringtoFullPath
U StringtoFullPath
U StringtoFullPath
00000000 T StringtoFullPath
$ nm --demangle /usr/lib/libpano13.so | grep StringtoFullPath
nm: /usr/lib/libpano13.so: no symbols
I also checked it using objdump:
$ objdump -T /usr/lib/libpano13.so | grep StringtoFullPath
00057fd0 g DF .text 0000004c Base StringtoFullPath
So, the following seems to be true:
libpano13 exists in /usr/lib,
libpano13 contains the symbols for StringtoFullPath,
I am using the correct library directory of /usr/lib,
I am using the correct library name of pano13, and
g++ is able to locate the library
But, for some reason, g++ is unable to find the symbol for StringtoFullPath.
Does anyone have any suggestions/ideas about why this is happening?
Any help would be greatly appreciated!
The
undefined reference to `StringtoFullPath(fullPath*, char*)'
worries me a bit: it contains the types of the parameters. Most Linux libraries are not C++, so there should be no types...
Try surrounding the #include for the header with an extern "C" { ... } block.
GNU gdb Fedora (6.8-37.el5)
Kernal 2.6.18-164.el5
I am trying to debug my application. However, everytime I pass the binary to the gdb it says:
(no debugging symbols found)
Here is the file output of the binary, and as you can see it is not stripped:
vid: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), for GNU/Linux 2.6.9, dynamically linked (uses shared libs), for GNU/Linux 2.6.9, not stripped
I am compiling with the following CFLAGS:
CFLAGS = -Wall -Wextra -ggdb -O0 -Wunreachable-code
Can anyone tell me if I am missing some simple here?
The most frequent cause of "no debugging symbols found" when -g is present is that there is some "stray" -s or -S argument somewhere on the link line.
From man ld:
-s
--strip-all
Omit all symbol information from the output file.
-S
--strip-debug
Omit debugger symbol information (but not all symbols) from the output file.
The application has to be both compiled and linked with -g option. I.e. you need to put -g in both CPPFLAGS and LDFLAGS.
Some Linux distributions don't use the gdb style debugging symbols. (IIRC they prefer dwarf2.)
In general, gcc and gdb will be in sync as to what kind of debugging symbols they use, and forcing a particular style will just cause problems; unless you know that you need something else, use just -g.
You should also try -ggdb instead of -g if you're compiling for Android!
Replace -ggdb with -g and make sure you aren't stripping the binary with the strip command.
I know this was answered a long time ago, but I've recently spent hours trying to solve a similar problem. The setup is local PC running Debian 8 using Eclipse CDT Neon.2, remote ARM7 board (Olimex) running Debian 7. Tool chain is Linaro 4.9 using gdbserver on the remote board and the Linaro GDB on the local PC. My issue was that the debug session would start and the program would execute, but breakpoints did not work and when manually paused "no source could be found" would result. My compile line options (Linaro gcc) included -ggdb -O0 as many have suggested but still the same problem. Ultimately I tried gdb proper on the remote board and it complained of no symbols. The curious thing was that 'file' reported debug not stripped on the target executable.
I ultimately solved the problem by adding -g to the linker options. I won't claim to fully understand why this helped, but I wanted to pass this on for others just in case it helps. In this case Linux did indeed need -g on the linker options.
Hope the sytem you compiled on and the system you are debugging on have the same architecture. I ran into an issue where debugging symbols of 32 bit binary refused to load up on my 64 bit machine. Switching to a 32 bit system worked for me.
Bazel can strip binaries by default without warning, if that's your build manager. I had to add --strip=never to my bazel build command to get gdb to work, --compilation_mode=dbg may also work.
$ bazel build -s :mithral_wrapped
...
#even with -s option, no '-s' was printed in gcc command
...
$ file bazel-bin/mithral_wrapped.so
../cpp/bazel-bin/mithral_wrapped.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=4528622fb089b579627507876ff14991179a1138, not stripped
$ objdump -h bazel-bin/mithral_wrapped.so | grep debug
$ bazel build -s :mithral_wrapped --strip=never
...
$ file bazel-bin/mithral_wrapped.so
bazel-bin/mithral_wrapped.so: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, BuildID[sha1]=28bd192b145477c2a7d9b058f1e722a29e92a545, not stripped
$ objdump -h bazel-bin/mithral_wrapped.so | grep debug
30 .debug_info 002c8e0e 0000000000000000 0000000000000000 0006b11e 2**0
31 .debug_abbrev 000030f6 0000000000000000 0000000000000000 00333f2c 2**0
32 .debug_loc 0013cfc3 0000000000000000 0000000000000000 00337022 2**0
33 .debug_aranges 00002950 0000000000000000 0000000000000000 00473fe5 2**0
34 .debug_ranges 00011c80 0000000000000000 0000000000000000 00476935 2**0
35 .debug_line 0001e523 0000000000000000 0000000000000000 004885b5 2**0
36 .debug_str 0033dd10 0000000000000000 0000000000000000 004a6ad8 2**0
For those that came here with this question and who are using Qt: in the release config there is a step where the binary is stripped as part of doing the make install. You can pass the configuration option CONFIG+=nostrip to tell it not to:
Instead of:
qmake <your options here, e.g. CONFIG=whatever>
you add CONFIG+=nostrip, so:
qmake <your options here, e.g. CONFIG=whatever> CONFIG+=nostrip
The solutions I've seen so far are good:
must compile with the -g debugging flag to tell the compiler to generate debugging symbols
make sure there is no stray -s in the compiler flags, which strips the output of all symbols.
Just adding on here, since the solution that worked for me wasn't listed anywhere. The order of the compiler flags matters. I was including multiple header files from many locations (-I/usr/local/include -Iutil -I. And I was compiling with all warnings on (-Wall).
The correct recipe for me was:
gcc -I/usr/local/include -Iutil -I -Wall -g -c main.c -o main.o
Notice:
include flags are at the beginning
-Wall is after include flags and before -g
-g is at the end
Any other ordering of the flags would cause no debug symbols to be generated.
I'm using gcc version 11.3.0 on Ubuntu 22.04 on WSL2.