Why do I see symbol linking error messages when the symbols are present? - dll

I have two object files, one with a couple of symbols defined and one in which those symbols are undefined:
nm ./src/freertos/freertos.o |grep pvPortMalloc
000000000000d045 T pvPortMalloc
...and...
nm ./src/clib/new_delete.o
U _GLOBAL_OFFSET_TABLE_
U _Z12pvPortMalloci
U _Z9vPortFreePv
0000000000000019 T _ZdlPv
0000000000000000 T _Znwm
When I attempt to link them together, I see this:
ld ./src/clib/new_delete.o ./src/freertos/freertos.o
ld: warning: cannot find entry symbol _start; defaulting to 0000000000401000
ld: ./src/clib/new_delete.o: in function `operator new(unsigned long)':
new_delete.cc:(.text+0x13): undefined reference to `pvPortMalloc(int)'
ld: ./src/clib/new_delete.o: in function `operator delete(void*)':
new_delete.cc:(.text+0x2d): undefined reference to `vPortFree(void*)'
Anyone have any ideas?

Your nm listings do not show there is any undefined symbol reported in ./src/clib/new_delete.o
that is defined in ./src/freertos/freertos.o.
There is a similarity between the
symbol pvPortMalloc defined in ./src/freertos/freertos.o and the undefined
symbol _Z12pvPortMalloci in ./src/clib/new_delete.o which I guess leads you to suppose that they are
the same, but the linker does not equate symbols on the basis of any similarity short of identity.
The symbol _Z12pvPortMalloci is the C++ mangled name of:
$ c++filt _Z12pvPortMalloci
pvPortMalloc(int)
showing that ./src/clib/new_delete.o was compiled with a C++ compiler. ./src/freertos/freertos.o,
on the other hand, was compiled with a C compiler, which does not do name-mangling.
If you want to tell your C++ compiler that the external name pvPortMalloc in
your source code is to have C linkage language, and therefore not to mangle it,
you must declare it extern "C".
Wrong
$ cat wrong.cpp
extern void * pvPortMalloc(int);
int main()
{
return pvPortMalloc(42) != nullptr;
}
$ g++ -Wall -c wrong.cpp
$ nm wrong.o
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U _Z12pvPortMalloci
Right
$ cat right.cpp
extern "C" {
void * pvPortMalloc(int);
// And any more...
}
int main()
{
return pvPortMalloc(42) != nullptr;
}
$ g++ -Wall -c right.cpp
$ nm right.o
U _GLOBAL_OFFSET_TABLE_
0000000000000000 T main
U pvPortMalloc

Related

objdump shows different function names

I have a cpp file that was compiled into an object file. For some reason, the functions inside the cpp file are named differently so one of the functions is "undefined". I don't know why g++ would label the functions differently.
Here are the relevant objdump output:
root#0b8da3d55c14:~/GF# g++ -g -Wall -o polynomial_arith.o -c polynomial_arith.cpp
root#0b8da3d55c14:~/GF# objdump -t polynomial_arith.o | grep Add
0000000000000219 g F .text 00000000000001fc _Z13polynomialAddPKxsS0_sPxsx
root#0b8da3d55c14:~/GF# objdump -t polynomial_arith.o | grep Sub
0000000000000462 l F .text 0000000000000019 _GLOBAL__sub_I__Z13polynomialSubPKxsS0_iPxsx
0000000000000000 g F .text 0000000000000219 _Z13polynomialSubPKxsS0_iPxsx
root#0b8da3d55c14:~/GF# objdump -t test.o | grep Add
0000000000000000 *UND* 0000000000000000 _Z13polynomialAddPKxsS0_sPxsx
root#0b8da3d55c14:~/GF# objdump -t test.o | grep Sub
0000000000000000 *UND* 0000000000000000 _Z13polynomialSubPKxsS0_sPxsx
You can see that polynomialAdd is _Z13polynomialAddPKxsS0_sPxsx in the object file while polynomialSub is _Z13polynomialSubPKxsS0_iPxsx. The test function (test.o) expects _Z13polynomialAddPKxsS0_sPxsx and _Z13polynomialSubPKxsS0_sPxsx. Thus polynomialSub is undefined because its name in polynomial_arith.o is _Z13polynomialSubPKxsS0_iPxsx, while polynomialAdd is just fine.
Are there special meaning to _iPxsx vs. SPxsx, and why they are generated differently?
$ demumble _Z13polynomialSubPKxsS0_iPxsx
polynomialSub(long long const*, short, long long const*, int, long long*, short, long long)
$ demumble _Z13polynomialSubPKxsS0_sPxsx
polynomialSub(long long const*, short, long long const*, short, long long*, short, long long)
They are different functions with different parameters.

error when calling subroutine from module in fortran [duplicate]

I am trying to compile some really old code (1986 and before). This code references an external function. Today's compilers ask for far more code to make this work. And I keep failing.
I now created a small hello world program, which demonstrates the problem.
hello.for
PROGRAM hello
USE func
PRINT *, "Hello World!"
PRINT *, f ()
END PROGRAM hello
func.for
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
f='Hello Func'
END FUNCTION
END MODULE
This has not only one, but two problems:
How do I define the return type? Docs tell <type> FUNCTION <function> or FUNCTION <function> () <type>::<something> , but neither works.
How do I make the linker find the function?
gfortran -c func.for works (if I use the default return type real) and creates a mod file but linking does not work
$ gfortran hello.for
/tmp/ccHNzcXA.o: In function `MAIN__':
hello.for:(.text+0xa4): undefined reference to `__func_MOD_f'
collect2: error: ld returned 1 exit status
__func_MOD_f is not contained in the mod file, but in the o file there is func.for__func_MOD_f.
Any idea?
thanks
You have two issues, the delcaration of f and properly linking the module.
First, compiling the module yields the error:
% gfortran -c func.f
func.f:5:8:
f='Hello Func'
1
Error: Can't convert CHARACTER(1) to REAL(4) at (1)
This error is due to implicit typing of f and an incompatible assignment. Fixing this is simple, declare f explicitly as a character instead of an implicit type. Add:
character(len=30) :: f
to the function and now your module compiles. Here is the modified module:
MODULE func
PUBLIC f
CONTAINS
FUNCTION f ()
character(len=30) :: f
f='Hello Func'
END FUNCTION
END MODULE
Your second problem is linking. Your command:
gfortran hello.for
fails because you did not specify the module object. If you already compiled the module you would specify:
gfortran hello.for func.o
if you were compiling them both at the same time you would do:
gfortran -o hworld func.for hello.for
if you are compiling everything individually:
gfortran -c func.for
gfortran -c hello.for
gfortran -o hworld hello.o func.o
Any of these will compile and run:
% ./hworld
Hello World!
Hello Func
If you are modernizing your code, it would also be worth adding implicit none to avoid any implicit typing and declaring explicit variables for everything. e.g.:
module func
implicit none
contains
function f
implicit none
character(len=30) :: f
f='Hello Func'
end function f
end module func
and
program hello
use func
implicit none
print *, "Hello World!"
print *, f ()
end program hello

Error cross compiling Tensorflow using contrib/makefile while linking the host proto_text

I have made a short script to cross compile tensorflow and am getting linker errors during linking of proto_text on the host side, however I have checked and I am linking the appropriate library and it appears to contain the correct symbols (see below).
version: tensorflow # tags/v1.4.0-rc1
Here is my script to cross-compile (I could not get the default compile_nsync.sh script working for my case)
unset CC CXX AS AR
pushd tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc
CC=gcc AR=ar CXX=g++ AS=as make clean VERBOSE=1
CC=gcc AR=ar CXX=g++ AS=as make depend VERBOSE=1
CC=gcc AR=ar CXX=g++ AS=as make VERBOSE=1
HOST_NSYNC_LIB="$(pwd)/nsync.a"
popd
export CXX=arm-linux-gnueabihf-g++-6
export CC=arm-linux-gnueabihf-gcc-6
export AR=arm-linux-gnueabihf-ar
export AS=arm-linux-gnueabihf-as
pushd tensorflow/contrib/makefile/downloads/nsync/tools
rm -rf ../builds/arm.linux.arm-linux-gnueabihf-gcc-6
sh mkmakefile.sh -arch arm -os linux -cc arm-linux-gnueabihf-gcc-6
popd
pushd tensorflow/contrib/makefile/downloads/nsync/builds/arm.linux.arm-linux-gnueabihf-gcc-6
make clean VERBOSE=1
#make depend VERBOSE=1
make VERBOSE=1
TARGET_NSYNC_LIB="$(pwd)/nsync.a"
popd
export HOST_NSYNC_LIB TARGET_NSYNC_LIB
echo "HOST nsync: $HOST_NSYNC_LIB"
echo "TARGET nsync: $TARGET_NSYNC_LIB"
make -j -f tensorflow/contrib/makefile/Makefile \
TARGET=LINUX CC_PREFIX="${CC_PREFIX}" \
HOST_CC=gcc HOST_CXX=g++ \
CXX=arm-linux-gnueabihf-g++-6 CC=arm-linux-gnueabihf-gcc-6 \
CXX_FLAGS="-mfpu=neon-vfpv4 -ftree-vectorize" \
HOST_NSYNC_LIB="$HOST_NSYNC_LIB" TARGET_NSYNC_LIB="$TARGET_NSYNC_LIB" \
SUB_MAKEFILES="${SUB_MAKEFILES}" ${EXTRA_MAKE_ARGS[#]}
the halting error
.... /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/grappler/costs/op_performance_data.pb.o -L/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/protobuf-host/lib -L/usr/local/lib /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc/nsync.a -lstdc++ -lprotobuf -lpthread -lm -lz -ldl -lpthread
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::mutex()':
env.cc:(.text._ZN10tensorflow5mutexC2Ev[_ZN10tensorflow5mutexC5Ev]+0x14): undefined reference to `nsync::nsync_mu_init(nsync::nsync_mu_s_*)'
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::lock()':
env.cc:(.text._ZN10tensorflow5mutex4lockEv[_ZN10tensorflow5mutex4lockEv]+0x14): undefined reference to `nsync::nsync_mu_lock(nsync::nsync_mu_s_*)'
/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_obj/tensorflow/core/platform/env.o: In function `tensorflow::mutex::unlock()':
env.cc:(.text._ZN10tensorflow5mutex6unlockEv[_ZN10tensorflow5mutex6unlockEv]+0x14): undefined reference to `nsync::nsync_mu_unlock(nsync::nsync_mu_s_*)'
collect2: error: ld returned 1 exit status
tensorflow/contrib/makefile/Makefile:631: recipe for target '/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_bin/proto_text' failed
make: *** [/work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/gen/host_bin/proto_text] Error 1
Note the nsync library is supplied and no error is thrown saying it cannot be found (quoting above: /work/opt/cortex-a7-myplatform/tensorflow/tensorflow/tensorflow/contrib/makefile/downloads/nsync/builds/x86_64.linux.gcc/nsync.a)
Inspecting the library there it appears to have the symbols. All three missing methods have both "T" & "U" entries...
$nm nsync.a | grep nsync_mu
U nsync_mu_semaphore_init
U nsync_mu_lock
U nsync_mu_semaphore_v
U nsync_mu_unlock
U nsync_mu_lock
U nsync_mu_lock_slow_
U nsync_mu_rlock
U nsync_mu_runlock
U nsync_mu_semaphore_v
U nsync_mu_unlock
0000000000000611 T nsync_mu_debug_state
0000000000000683 T nsync_mu_debug_state_and_waiters
00000000000006f5 T nsync_mu_debugger
00000000000009aa T nsync_mu_assert_held
0000000000000021 T nsync_mu_init
00000000000009e9 T nsync_mu_is_reader
0000000000000213 T nsync_mu_lock
0000000000000031 T nsync_mu_lock_slow_
00000000000009c8 T nsync_mu_rassert_held
00000000000002e3 T nsync_mu_rlock
0000000000000294 T nsync_mu_rtrylock
000000000000090a T nsync_mu_runlock
U nsync_mu_semaphore_p
U nsync_mu_semaphore_v
00000000000001c1 T nsync_mu_trylock
000000000000087d T nsync_mu_unlock
000000000000046c T nsync_mu_unlock_slow_
U nsync_mu_lock_slow_
U nsync_mu_unlock_slow_
000000000000041a T nsync_mu_unlock_without_wakeup
00000000000003e6 T nsync_mu_wait
0000000000000000 T nsync_mu_wait_with_deadline
U nsync_mu_lock
U nsync_mu_semaphore_v
U nsync_mu_trylock
U nsync_mu_unlock
U nsync_mu_wait
U nsync_mu_lock
U nsync_mu_unlock
U nsync_mu_lock
U nsync_mu_semaphore_p_with_deadline
U nsync_mu_unlock
U nsync_mu_semaphore_p_with_deadline
0000000000000000 T nsync_mu_semaphore_init
0000000000000007 T nsync_mu_semaphore_p
000000000000008e T nsync_mu_semaphore_p_with_deadline
00000000000001c7 T nsync_mu_semaphore_v
What am I missing here? Thanks for reading this far.
Classic case of not reading carefully enough.
The missing linker errors say they are looking for methods of the form
nsync::nsync_mu_init(nsync::nsync_mu_s_*).
The nm output specifies C-style functions.
The error can be resolved by compiling and linking against a C++ version of nsync instead of a C-version.

How to compile libgit2 without HTTPS

I'm trying to compile a no or limited libgit2 static build but haven't yet succeeded into compiling it without openssl.
So far, my best attempt has been following this suite of commands:
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_PREFIX=/opt/ -DBUILD_SHARED_LIBS=OFF -DCMAKE_DISABLE_FIND_PACKAGE_OpenSSL=TRUE
make
But I obtain the following:
[ 11%] Building C object CMakeFiles/git2.dir/src/openssl_stream.c.o
/Users/raphael/src/github.com/libgit2/libgit2/src/openssl_stream.c:369:41: warning: unused parameter 'out' [-Wunused-parameter]
int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
^
/Users/raphael/src/github.com/libgit2/libgit2/src/openssl_stream.c:369:58: warning: unused parameter 'host' [-Wunused-parameter]
int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
^
/Users/raphael/src/github.com/libgit2/libgit2/src/openssl_stream.c:369:76: warning: unused parameter 'port' [-Wunused-parameter]
int git_openssl_stream_new(git_stream **out, const char *host, const char *port)
Then:
[ 23%] Building C object CMakeFiles/git2.dir/src/hash/hash_generic.c.o
In file included from /Users/raphael/src/github.com/libgit2/libgit2/src/hash/hash_generic.c:10:
/Users/raphael/src/github.com/libgit2/libgit2/src/hash/hash_generic.h:13:8: error: redefinition of 'git_hash_ctx'
struct git_hash_ctx {
^
/Users/raphael/src/github.com/libgit2/libgit2/src/hash/hash_common_crypto.h:15:8: note: previous definition is here
struct git_hash_ctx {
^
And many others obviously following.
Environment details:
I'm on MacOS X Yosemite, using either Clang or GCC 4.9 and I'm building statically, I tried with tag v0.22.1 and master from Jan 24, 2015.
I'm looking for a process that would be portable to Linux / FreeBSD as well.
The warnings about the openssl stream are irrelevant; the constructor simply returns an error, so it doesn't use any of the parameters passed. It'd be nice to clean the up, but they don't do anything.
As for the redefinition issue, you can find a workaround in PR 2820.

Import class-dump info into GDB

Is there a way to import the output from class-dump into GDB?
Example code:
$ cat > test.m
#include <stdio.h>
#import <Foundation/Foundation.h>
#interface TestClass : NSObject
+ (int)randomNum;
#end
#implementation TestClass
+ (int)randomNum {
return 4; // chosen by fair dice roll.
// guaranteed to be random.
}
#end
int main(void) {
printf("num: %d\n", [TestClass randomNum]);
return 0;
}
^D
$ gcc test.m -lobjc -o test
$ ./test
num: 4
$ gdb test
...
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000e5c
(gdb) ^D
$ strip test
$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) ^D
$ class-dump -A test
...
#interface TestClass : NSObject
{
}
+ (int)randomNum; // IMP=0x0000000100000e50
#end
I know I can now use b *0x0000000100000e50 in gdb, but is there a way of modifying GDB's symbol table to make it accept b +[TestClass randomNum]?
Edit: It would be preferably if it would work with GDB v6 and not only GDB v7, as GDB v6 is the latest version with Apple's patches.
It’s possible to load a symbol file in gdb with the add-symbol-file command. The hardest part is to produce this symbol file.
With the help of libMachObjC (which is part of class-dump), it’s very easy to dump all addresses and their corresponding Objective-C methods. I have written a small tool, objc-symbols which does exactly this.
Let’s use Calendar.app as an example. If you try to list the symbols with the nm tool, you will notice that the Calendar app has been stripped:
$ nm -U /Applications/Calendar.app/Contents/MacOS/Calendar
0000000100000000 T __mh_execute_header
0000000005614542 - 00 0000 OPT radr://5614542
But with objc-symbols you can easily retrieve the addresses of all the missing Objective-C methods:
$ objc-symbols /Applications/Calendar.app
00000001000c774c +[CALCanvasAttributedText textWithPosition:size:text:]
00000001000c8936 -[CALCanvasAttributedText createTextureIfNeeded]
00000001000c8886 -[CALCanvasAttributedText bounds]
00000001000c883b -[CALCanvasAttributedText updateBezierRepresentation]
...
00000001000309eb -[CALApplication applicationDidFinishLaunching:]
...
Then, with SymTabCreator you can create a symbol file, which is just actually an empty dylib with all the symbols.
Using objc-symbols and SymTabCreator together is straightforward:
$ objc-symbols /Applications/Calendar.app | SymTabCreator -o Calendar.stabs
You can check that Calendar.stabs contains all the symbols:
$ nm Calendar.stabs
000000010014a58b T +[APLCALSource printingCachedTextSize]
000000010013e7c5 T +[APLColorSource alternateGenerator]
000000010013e780 T +[APLColorSource defaultColorSource]
000000010013e7bd T +[APLColorSource defaultGenerator]
000000010011eb12 T +[APLConstraint constraintOfClass:withProperties:]
...
00000001000309eb T -[CALApplication applicationDidFinishLaunching:]
...
Now let’s see what happens in gdb:
$ gdb --silent /Applications/Calendar.app
Reading symbols for shared libraries ................................. done
Without the symbol file:
(gdb) b -[CALApplication applicationDidFinishLaunching:]
Function "-[CALApplication applicationDidFinishLaunching:]" not defined.
Make breakpoint pending on future shared library load? (y or [n]) n
And after loading the symbol file:
(gdb) add-symbol-file Calendar.stabs
add symbol table from file "Calendar.stabs"? (y or n) y
Reading symbols from /Users/0xced/Calendar.stabs...done.
(gdb) b -[CALApplication applicationDidFinishLaunching:]
Breakpoint 1 at 0x1000309f2
You will notice that the breakpoint address does not exactly match the symbol address (0x1000309f2 vs 0x1000309eb, 7 bytes of difference), this is because gdb automatically recognizes the function prologue and sets the breakpoint just after.
GDB script
You can use this GDB script to automate this, given that the stripped executable is the current target.
Add the script from below to your .gdbinit, target the stripped executable and run the command objc_symbols in gdb:
$ gdb test
...
(gdb) b +[TestClass randomNum]
Function "+[TestClass randomNum]" not defined.
(gdb) objc_symbols
(gdb) b +[TestClass randomNum]
Breakpoint 1 at 0x100000ee1
(gdb) ^D
define objc_symbols
shell rm -f /tmp/gdb-objc_symbols
set logging redirect on
set logging file /tmp/gdb-objc_symbols
set logging on
info target
set logging off
shell target="$(head -1 /tmp/gdb-objc_symbols | head -1 | awk -F '"' '{ print $2 }')"; objc-symbols "$target" | SymTabCreator -o /tmp/gdb-symtab
set logging on
add-symbol-file /tmp/gdb-symtab
set logging off
end
There is no direct way to do this (that I know of), but it seems like a great idea.
And now there is a way to do it... nice answer, 0xced!
The DWARF file format is well documented, IIRC, and, as the lldb source is available, you have a working example of a parser.
Since the source to class-dump is also available, it shouldn't be too hard to modify it to spew DWARF output that could then be loaded into the debugger.
Obviously, you wouldn't be able to dump symbols with full fidelity, but this would probably be quite useful.
You can use DSYMCreator.
With DSYMCreator, you can create a symbol file from an iOS executable binary.
It's a toolchain, so you can use it like this.
$ ./main.py --only-objc /path/to/binary/xxx
Then a file /path/to/binary/xxx.symbol will be created, which is a DWARF format symbol. you can import it to lldb by yourself.
Apart from that, DSYMCreator also supports to export symbols from IDA Pro, you can use it like this.
$ ./main.py /path/to/binary/xxx
YES, just ignore --only-objc flag. Then the IDA Pro will run automatically, and then a file /path/to/binary/xxx.symbol will be created, which is the symbol file.
Thanks 0xced for creating objc-symbols, which is a part of DSYMCreator toolchain.
BTW, https://github.com/tobefuturer/restore-symbol is another choice.