Re: Newbie to Darwin linking issue I think?
Re: Newbie to Darwin linking issue I think?
- Subject: Re: Newbie to Darwin linking issue I think?
- From: Shantonu Sen <email@hidden>
- Date: Sat, 4 Jun 2005 18:43:49 -0700
On order to correctly override a function, the 32-bit linker requires
that all global symbols in the function's containing module be
overridden. For your case, this means you need to implement at most:
[shantonu@repl]$ nm -g "/usr/lib/libSystem.B.dylib(malloc.So)" | grep
-v " U "
/usr/lib/libSystem.B.dylib(malloc.So):
901200d0 T __malloc_fork_child
90032bc4 T __malloc_fork_parent
90032a58 T __malloc_fork_prepare
90008574 T _calloc
90005ccc T _free
90003424 T _malloc
a000425c D _malloc_check_counter
a0004258 D _malloc_check_each
a0004260 D _malloc_check_start
90043b4c T _malloc_create_zone
901201b8 T _malloc_debug
a0004264 D _malloc_debug_flags
90014f38 T _malloc_default_zone
901207f0 T _malloc_destroy_zone
9012009c T _malloc_error
9011fc7c T _malloc_get_all_zones
9011fa74 T _malloc_get_zone_name
90032f88 T _malloc_good_size
a0004268 D _malloc_logger
a0004270 D _malloc_num_zones
9011fa7c T _malloc_printf
900442c0 T _malloc_set_zone_name
90120168 T _malloc_singlethreaded
90048318 T _malloc_size
90120430 T _malloc_zone_batch_free
9012054c T _malloc_zone_batch_malloc
90014e7c T _malloc_zone_calloc
9011f860 T _malloc_zone_check
900137e4 T _malloc_zone_free
90052ef4 T _malloc_zone_from_ptr
9011ffcc T _malloc_zone_log
900039f8 T _malloc_zone_malloc
9011fe50 T _malloc_zone_print
9011fd90 T _malloc_zone_print_ptr_info
90033c4c T _malloc_zone_realloc
9011f910 T _malloc_zone_register
9011fef4 T _malloc_zone_statistics
9011fb5c T _malloc_zone_unregister
90120648 T _malloc_zone_valloc
a000426c D _malloc_zones
90120708 T _mstats
90017360 T _realloc
9002c0bc T _set_malloc_singlethreaded
9004a3a4 T _valloc
901206fc T _vfree
As a demonstration, here's an example using the devname(3) API, which
has devname() and devname_r() implemented in a single module in
libSystem:
[shantonu@repl]$ nm -g "/usr/lib/libSystem.B.dylib(devname.So)" |
grep -v " U "
/usr/lib/libSystem.B.dylib(devname.So):
900be638 T _devname
90062320 T _devname_r
In order to provide a dylib that replaces the implementation of one
of these functions (correctly), I need to implement both functions.
[shantonu@repl]$ cat test.c
#include <stdlib.h>
#include <stdio.h>
#include <sys/stat.h>
int main(int argc, char *argv[]) {
char dev[100], *dev2;
devname_r(234881027, S_IFBLK, dev, sizeof(dev));
printf("%s\n", dev);
dev2 = devname(234881027, S_IFBLK);
printf("%s\n", dev2);
return 0;
}
[shantonu@repl]$ cat devname.c
#include <sys/types.h>
#include <string.h>
#ifdef DO_DEVNAME
char *devname(dev_t dev, mode_t type)
{
return "something";
}
#endif
#ifdef DO_DEVNAME_R
char *devname_r(dev_t dev, mode_t type, char *buf, int len)
{
if(len < 10)
return NULL;
strcpy(buf, "something");
return buf;
}
#endif
If my dylib just implements devname(), I get this warning:
[shantonu@repl]$ cc -c devname.c -DDO_DEVNAME
[shantonu@repl]$ cc -dynamiclib -o libdevname.dylib devname.o -
install_name $PWD/libdevname.dylib
[shantonu@repl]$ cc -o test test.c -L. -ldevname
/usr/bin/ld: warning multiple definitions of symbol _devname
./libdevname.dylib(devname.o) definition of _devname
/usr/lib/gcc/powerpc-apple-darwin8/4.0.0/../../../libSystem.dylib
(devname.So) definition of _devname
[shantonu@repl]$ nm -mg test| grep devname
(undefined [lazy bound]) external _devname (from libdevname)
(undefined [lazy bound]) external _devname_r (from libSystem)
[shantonu@repl]$ ./test
disk0s5
something
Note here that devname() came from my dylib but devname_r() came from
libSystem. This is exactly the kind of behavior the linker is trying
to prevent. An analagous situation would be to using the system's
calloc() with your custom free(), with no guarantee that they are
compatible.
If you just implement devname_r(), you get a similar but different
warning (and behavior)
[shantonu@repl]$ cc -c devname.c -DDO_DEVNAME_R
[shantonu@repl]$ cc -dynamiclib -o libdevname.dylib devname.o -
install_name $PWD/libdevname.dylib
[shantonu@repl]$ cc -o test test.c -L. -ldevname
/usr/bin/ld: warning suggest use of -bind_at_load, as lazy binding
may result in errors or different symbols being used
symbol _devname_r used from dynamic library /usr/lib/gcc/powerpc-
apple-darwin8/4.0.0/../../../libSystem.dylib(devname.So) not from
earlier dynamic library /tmp/libdevname.dylib(devname.o)
[shantonu@repl]$ nm -mg test| grep devname
(undefined [lazy bound]) external _devname (from libSystem)
(undefined [lazy bound]) external _devname_r (from libSystem)
[shantonu@repl]$ ./test
disk0s5
disk0s5
In this case, because of the order in which the linker searched
libraries, the system version was used. Only if you override both
functions does the entire module get overridden:
[shantonu@repl]$ cc -c devname.c -DDO_DEVNAME -DDO_DEVNAME_R
[shantonu@repl]$ cc -dynamiclib -o libdevname.dylib devname.o -
install_name $PWD/libdevname.dylib
[shantonu@repl]$ cc -o test test.c -L. -ldevname
[shantonu@repl]$ nm -mg test| grep devname
(undefined [lazy bound]) external _devname (from libdevname)
(undefined [lazy bound]) external _devname_r (from libdevname)
[shantonu@repl]$ ./test
something
something
For your case, you might get away with just implementing on the order
of 20 functions and constants, based on what symbols are used
internally to libSystem and by clients. In the worst case, you'll
need to implement all 45 symbols so that nothing can cause
libSystem.B.dylib(malloc.So) to be accessed (and cause duplicate
symbol warnings with your dylib)
Shantonu
On Jun 4, 2005, at 4:55 PM, Damien Cooke wrote:
Thanks for the hint:
I am now linking like this
cc -dynamiclib -fPIC -o bin/liblpmalloc.so output/lpmalloc.o output/
global.o
But I now get:
ld: warning multiple definitions of symbol _malloc
output/lpmalloc.o definition of _malloc in section (__TEXT,__text)
/usr/lib/gcc/powerpc-apple-darwin8/4.0.0/../../../libSystem.dylib
(malloc.So) definition of _malloc
So how do I tell it I am building a replacement for malloc other
than re-implementing the System.dylib ? Is there a way of dropping
duplicate entries?
Damien
On 05/06/2005, at 8:51 AM, Shantonu Sen wrote:
Why are you using libtool(1) instead of the compiler driver cc(1)
to create your shared library?
Your problem is that you are not linking against libSystem.dylib
(via -lSystem). You're also missing a host of other libraries
automatically included when you link a dylib with cc(1). for example:
/usr/bin/libtool -dynamic -arch_only ppc -noall_load -
weak_reference_mismatches non-weak -v -o libfoo.dylib -L/usr/lib/
gcc/powerpc-apple-darwin8/4.0.0 -L/usr/lib/gcc/powerpc-apple-
darwin8/4.0.0 -L/usr/lib/gcc/powerpc-apple-darwin8/4.0.0/../../..
foo.o -lgcc -lgcc_eh -lSystemStubs -lmx -lSystem
You should use cc/gcc and the -dynamiclib option to build your
library. You probably also want to read the various man pages and
use the -install_name flag as well.
Shantonu
On Jun 4, 2005, at 4:06 PM, Damien Cooke wrote:
Sorry for the dumb question. I am porting my malloc to Darwin.
I have built it as a shared dynamic library on Solaris. However
I am having a large amount of problems with this on OS X 10.4.1
using XCode 2.0 and gcc 4.0
I build the two object files as such
gcc -g -fPIC -c source/lpmalloc.c -o output/lpmalloc.o
gcc -g -fPIC -c source/global.c -o output/global.o
Then I use Libtool as such libtool -dynamic -o bin/
liblpmalloc.so output/lpmalloc.o output/global.o
This is what I get:
ld: for architecture ppc
ld: Undefined symbols:
_printf
libtool: internal link edit command failed
I am probably doing something really dumb but any help would be
greatly appreciated.
Damien
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
40opendarwin.org
This email sent to email@hidden
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Darwin-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden