Wednesday, October 22, 2014

Advanced debugging tricks using GDB

Breaking on an application error

 You will fine lot of instances when an unknown application ( or an application which you are not much familiar ) fails while starting up, logs some error message on the terminal , and exits. Since it
doesn't crash or raise any kind of OS level software interrupt ( signals ) , its hard to guess the reason for the failure . Running it under a debugger also doesn't help much in this case. 

It would be helpful if we could break in the debugger , at the point the application is about to write on the terminal . From there , we can trace back callers to find the actual place which triggered the error.

There are ways in gdb to do exactly that , stop execution at the exact point when the application tries to write a particular error string to the stdout. It requires a little bit of knowledge of parameter passing  and calling conventions as defined in the ABI for the architecture/platform. The architecture we have followed is the x86/x86_64 , but this same stuff should be adapted to any other architecture or under any other debugger.

The way we do it , with gdb 7.0 and above , you can set conditional breakpoint on a syscall like write(), as below :

(gdb) catch syscall write
Catchpoint 1 (syscall 'write' [4])
(gdb) condition 1 $rdi==1 && strcmp((char*)($rsi), "The specified object is attached to another target") == 0

Couple of things to note here :
1. The write syscall has the below declaration
ssize_t write(int fd, const void *buf, size_t count);

Since we are writing to stdout , the fd parameter would be 1 and the string would be in the second parameter buf .

2. On the Intel x86_64 architecture , according to argument passing rules defined in the ABI , the first parameter is passed in RDI , the second parameter is passed in register RSI and the return value is passed in RAX. We can also additional use the return value in many cases if required.

On 32 bit x86 systems , its not that straight-forward since the parameters are passed on the stack , so we would need to cast the stack locations holding the arguments. I would show in some later examples.

3. gdb lets us call strcmp() function which we can use to compare it to the required string. Please note that the string might also have some extra characters , and might not exactly match sometimes. In that case we can use any of the other string functions , eg, strstr() etc .

Additional Examples :

1. We can also use the break command instead of the catch command :

(gdb) break foo if strcmp(baz,"hello") == 0
(gdb) break foo if ((int)strcmp(baz,"hello")) == 0

on some implementations, gdb might not know the return type of strcmp. That means you have to cast, otherwise it would always evaluate to true.

2. Difference between 32-bit and 64-bit

 x86 32-bit mode
(gdb) break write if 1 == *(int*)($esp + 4) && strcmp((char*)*(int*)($esp + 8), "your string") == 0

x86 64 bit mode
(gdb) break write if 1 == $rdi && strcmp((char*)($rsi), "your string") == 0

3. Break when opening certain file:

x86 32-bit mode
(gdb) break open
(gdb) condition 1 strcmp(((char**)$esp)[1], "bar") == 0

x86 64-bit mode
(gdb) condition 1 strcmp((char *)$rsi, "bar") == 0

Valgrind/GDB Integration

Using GDB with Valgrind

You can do this with the version of Valgrind (3.8.1) and above :

Start your executable activating the gdbserver at startup:

valgrind --vgdb-error=0 ....

Then in another window, connect a gdb to Valgrind (following the indications given by Valgrind). Then put a break-point at a relevant place (e.g. at the end of main) and use the gdb continue command till the breakpoint is reached. Then do a leak search from gdb:

gdb> monitor leak_check full reachable any

Then list the address(es) of the reachable blocks of the relevant loss record nr

gdb> monitor block_list

You can then use gdb features to examine the memory of the given address(es). Note also the potentially interesting command "who_points_at" if you are searching who has kept a pointer to this memory.

gdb> monitor leak_check

This gives you an summary, exactly as at the end of any Valgrind-run, but at precisely this point in the execution. You can add various options to the command to get more out of it, but since this is sufficient for the purpose of this blog, those are left as an excercise to the reader.

gdb> who_points_at

This will give you hints on from where this particular memory is referenced. Usually these are the places that are just overwritten, and the memory at gets lost.

Emulated hardware watchpoints

If you use GDB 7.4 together with Valgrind 3.7.0, then you have unlimited "emulated" hardware watchpoints.

Start your program under Valgrind, giving the arguments --vgdb=full --vgdb-error=0 then use GDB to connect to it (target remote | vgdb). Then you can e.g. watch or awatch or rwatch a memory range by doing rwatch (char[100]) *0x5180040

link :

More GDB hacks

1. Here is how to make it stop when rawbuf has the value "FLUSH LOGS". At the (gdb prompt) enter the command:

(gdb) cond 14 strstr (rawbuf, "FLUSH LOGS")

Then type the command "c" and watch it run until breakpoint 14 is reached AND the rawbuf variable contains the [sub]string "FLUSH LOGS".

2. Make breakpoint 12 stop only if the variable opt->name matches the string "user":
(gdb) cond 14 strcmp (opt->name, "user") == 0

There might be an issue in the above form where strcmp needs to call malloc to allocate space for the "user" string every time it breaks
We can try to do it the below way too :
(gdb) set $str = "hello"
(gdb) cond 1 strcmp (s.whatever, $str) == 0

3. To set a break-point in a library when it's loaded you can set a break-point on the symbol _dl_open. This function is called when a new library is loaded. You can set your break-point after you see that
your library has been loaded.

4. set step-mode on
The set step-mode on command causes the step command to stop at the first instruction of a function which contains no debug line information rather than stepping over it.
This is useful in cases where you may be interested in inspecting the machine instructions of a function which has no symbolic info and do not want gdb to automatically skip over this function.

5. Attach to a process when its launched

$ gdb --waitfor=PROCNAME

Where PROCNAME is the process name to continuously poll for until it has been launched. Note that some instructions will have been executed before GDB attaches this way because polling is not exactly instant however close it might seem to be.

6. A very useful technique is to know how to redirect stdout (file descriptor 1) and/or stderr (file descriptor 2) after a program has started. We are going to exploit the fact that print can invoke system calls like dup2 and open in our case. After attaching to the process do the following:

(gdb) p (void) dup2((int) open("/tmp/out.txt", 0x201, 0640), 1)
(gdb) p (void) dup2((int) open("/tmp/err.txt", 0x201, 0640), 2)
(gdb) detach
(gdb) q

In short it will redirect stdout to "/tmp/stdout.txt" and stderr to "/tmp/stderr.txt". The system call open is used to open a file for writing in our case. The mode "0x201" actually means "write only and create file if nonexistent" since O_CREAT | O_WRONLY = 0x200 | 0x1 = 0x201 (see the fcntl.h header file for details). "0640" is the umask (user has RW and group has R). After opening a file and retrieving its FD we need to redirect the device in question to it (stdout and stderr in this case). This is achieved using dup2 that creates an alias to the FD, does redirection and closes the old FD.

Additionally, it's important to cast types to enforce GDB to behave correctly. If this is not the case it could argue giving the following error message:

    Unable to call function "open" at 0x7fff906e3fe4: no return type information available.
    To call this function anyway, you can cast the return type explicitly (e.g. 'print (float) fabs (3.0)')

Another scenario would be to completely turn off output to stdout/stderr:

(gdb) p (void) close(1)
(gdb) p (void) close(2)
(gdb) det
(gdb) q

Wednesday, March 20, 2013

Solaris SPARC ABI and register conventions

32 to 64 bit changes

The easiest way to determine which version is running on your system is to use the isainfo command. This new command prints information about the application environments supported on the system.

The following is an example of the isainfo command executed on an UltraSPARC™ system running the 64-bit operating system:

% isainfo -v
64-bit sparcv9 applications
32-bit sparc applications

One useful option of the isainfo(1) command is the -n option, which prints the native instruction set of the running platform:

% isainfo -n

The -b option prints the number of bits in the address space of the corresponding native applications environment:

% echo "Welcome to "`isainfo -b`"-bit Solaris"
Welcome to 64-bit Solaris

A related command, isalist(1), that is more suited for use in shell scripts, can be used to print the complete list of supported instruction sets on the platform. Some of the instruction set architectures listed by isalist are highly platform specific, while isainfo(1) describes only the attributes of the most portable application environments on the system. Both commands are built on the SI_ISALIST suboption of the sysinfo(2) system call. See isalist(5) for further details.

The following is an example of the isalist command executed on an UltraSPARC system running the 64-bit operating system:

% isalist
sparcv9+vis sparcv9 sparcv8plus+vis sparcv8plus sparcv8
sparcv8-fsmuld sparcv7 sparc

The basic calling convention is the same. The first six arguments of the caller are placed in the out registers %o0-%o5. The SPARC V9 ABI still uses a register window on a larger register file to make calling a function a "cheap" operation. Results are returned in %o0. Because all registers are now treated as 64-bit quantities, 64-bit values can now be passed in a single register, rather than a register pair.

The layout of the stack is different. Apart from the increase in the basic cell size from 32-bit to 64-bit, various "hidden" parameter words have been removed. The return address is still %o7 + 8.

%o6 is still referred to as the stack pointer register %sp, and %i6 is the frame pointer register %fp. However, the %sp and %fp registers are offset by a constant, known as the stack bias, from the actual memory location of the stack. The size of the stack bias is 2047 bits.

Instruction sizes are still 32 bits. Address constant generation therefore takes more instructions. The call instruction can no longer be used to branch anywhere in the address space, since it can only reach within plus or minus 2 gigabytes of %pc.

Integer multiply and divide functions are now implemented completely in hardware.

Structure passing and return are accomplished differently. Small data structures and some floating point arguments are now passed directly in registers.

User traps allow certain traps from non-privileged code to be handled by a user trap handler (instead of delivering a signal).

Solaris SPARC ABI Register Semantics

Solaris OS Patch Management

Please read the below notes to understand the different Solaris releases
( Marketing / Update / Maintenance ) :

To list all patches applied on a system , run
% showrev -p
% patchadd -p

To look for a specific patch , run
% showrev -p | grep 113964

uname prints the basic information about the system
% uname -a
SunOS dnagac08-3 5.10 Generic_138888-03 sun4v sparc SUNW,T5240

% cat /var/sadm/softinfo/INST_RELEASE

If you need to look-up a patch , you can do at . The below blog should be helpful :

For removing a specific patch , the patchrm command can be used passing the patch id.

To check for the Operating Environment / System updates , run
%cat /etc/release
Solaris 10 10/08 s10s_u6wos_07b SPARC
Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
Use is subject to license terms.
Assembled 27 October 2008 <== This also can be looked-up

The first line summarizes the release details ( broken up below ) :
Solaris 10 : Base OS Level
10/08 : Release Date
s10s_u6wos_07b : Solaris 10 sparc update 6 ...
SPARC : Hardware

SunoS --> Solaris
5.3 --> 2.3
5.4 --> 2.4
5.5 --> 2.5
5.5.1 --> 2.5.1
5.6 --> 2.6
5.7 --> 7
5.8 --> 8
5.9 --> 9
5.10 --> 10

Monday, February 14, 2011

Oracle Database on Mac OS X Snow Leopard

Its been sometime now since both the Database Client (+ Instant Client) and Database server have been available for Apple Mac OS X x86-64 . The lowest version supported was the Mac OS X Leopard 10.5.4 .

By the time Oracle released the Oracle DB , Snow Leopard was already out and adopted by the Mac community . If you happen to be on a SL box and trying to install Oracle , there is a know problem with the database crashing while installation . Many notable Oracle/Mac folks have worked through and found alternate solutions .

Check out the below links for information :

Link 1

I will try to list out the issues and workarounds for getting Oracle Databse installed . Some of the points may have been already mentioned in the links mentioned earlier .

1. JDK version on Snow Leopard

JDK 1.6 ( 64 bit ) is the default JDK version available on the platform . If we can install JDK 1.4.2 ( 32-bit ) on Snow Leopard , we will *NOT* require many of the other workarounds related to JDK version mentioned below .

Searching on the web , I found this link which says how to use the older Leopard version 1.4.2 ( & 1.5 ) JDK on Snow Leopard . *NOT* sure if its officially supported , I haven't tried it out myself , but this is a suggestion if someone wants to give it a try .

2. Working around with the JDK 1.6 ( 64 bit ) on Snow Leopard

The next workaround is to configure the Snow Leopard system to use the default JDK 6 , but in 32-bit mode , since there is still not much support for 64 bit java ( some Oracle install related JNI libs are 32-bit ) . JDK 1.6 is pretty recent and there hasn't been much adoption though its slowly increasing .

This is *NOT* tested , but I assume this should also work out . Open "/Applications/Utilities/Java" and set JDK 6 32-bit by default .

The next workaround , is to make a symlink for JDK 1.4.2 point to the default JDK 1.6 . But since its 64 bit by default we need to do changes to some of Oracle's installation scripts .

i) We first need to invoke the runInstaller ( which install's Oracle ) with the "=J-d32" option so that it invokes Java in 32-bit mode , since in the default mode Java 6 is invoked in 64-bit mode .

ii) We also need to modify the $ORACLE_HOME/jdk/bin/java script and pass the "-d32" flag in the command-line . $ORACLE_HOME/jdk/bin/java is used to invoke all the different Oracle database configuration assistants ( netca, dbca etc ) .

3. Make Errors

During the install , we can still see the below issue :
Error in invoking target 'all_no_orcl ipc_g ihsodbc32' of makefile

Workaround : Comment out the HSODBC_LINKLINE in . Maybe ignoring should also work .

4. Configuration Assistants failures
We should fix the $ORACLE_HOME/jdk/bin/java script to invoke Java in 32-bit mode so that we don't see any failures while running the NETwork Configuration Assistant ( NETCA ) , DataBase Configuration Assistant ( DBCA ) etc ..

5. EE/SE install's with DB creation Snow Leopard

Any of the EE/SE installs on Snow Leopard have a known problem . They fail with the below error message while running the DBCA :

ORA-03113: end-of-file on communication channel appeared.
( dbca : ORA-3113 with CloneRmanRestore )

Looking through the logs , we can see the below error messages :
ORA-07445: exception encountered: core dump [joxnfy_()+2763] [SIGSEGV] [Address not mapped to object] [0x277B8AEB8] [] []

This happens when dbca is invoked to create the database in the EE/SE installs ( not in the software only installs ) . The workarounds suggested on the previously mentioned links is to copy the old Oracle binary to overwrite the new binary .

During Oracle Installation , the Oracle binary is relinked/regenerated on the platform . Even though there shouldn't have been anything which would prevent Oracle to run smoothly on Snow Leopard , unfortunately we see the above issue when the Oracle binary is recompiled on Snow Leopard ( with the rest of the libraries oracle uses being the same old ones).

There seems to have been some changes that have gone into the Snow Leopard . Even though there were no major changes , as the naming convention of Apple would suggest ( Leopard -> Snow Leopard ) , there are still some subtle differences .

One of the changes which is linked to the Oracle Installation crash , most likely seems to be related to changes as described below ( found from a wiki ) :

With the introduction of Apple's Mac OS X 10.6 platform the Mach-O file has undergone a significant modification that causes binaries compiled on a 10.6 computer to be by default only able to run on a 10.6 computer. The difference stems from load commands that Mac OS X's linker (dyld) can not understand on previous Mac OS X versions. Another significant change to the Mach-O format is the change in how the Link Edit tables (found in the __LINKEDIT section) function. In 10.6 these new Link Edit tables are compressed by removing unused and unneeded bits of information, however Mac OS X 10.5 and earlier cannot read this new Link Edit table format. To resolve this issue, the linker flag "-mmacosx-version-min=" is heavily used and depended on. Apple, current maintainer of the Mach-O format, recommends that all developers now use this flag along with the appropriate SDK headers when creating an application/binary.

Below is the dyld ( Dynamic Loader ) release notes of Mac OS X 10.6 ( Snow Leopard )
DYLD release notes for Mac OS X 10.6 ( Snow Leopard )

Researching based on the above data , made me stumble upon a couple of new compiler/linker flags which can help control the generation of the __LINKEDIT section format ( traditional relocation format or the new compressed format ) .

-mmacosx-version-min=version ( Apple GCC Flag )
The earliest version of MacOS X that this executable will run on is version. Typical values of version include 10.1, 10.2, and 10.3.9 .

-macosx_version_min version ( LD Flag )
This is set to indicate the oldest Mac OS X version that that the output is to be used on. Specifying a later version enables the linker to assumes features of that OS in the output file. The format of version is a Mac OS X version number such as 10.4 or 10.5.

Please note the difference between hyphen ("-") vs the underscore ("_") and also the names of the flags for GCC and LD respectively .

-no_compact_linkedit ( LD Flag )
Normally when targeting Mac OS X 10.6, the linker will generate compact information in the __LINKEDIT segment. This option causes the linker to instead produce traditional relocation information.

The "-no_compact_linkedit" linker flag is used / makes sense / allowed only in conjunction with the -mmacosx-version-min=version ( Apple GCC Flag ). You can also use the -macosx_version_min version ( LD Flag ) instead of the GCC flag if you want.

Now , passing the -mmacosx-version-min=version ( Apple GCC Flag ) & "-no_compact_linkedit" linker flag to the Oracle link-line generates a Oracle which is compatible with the older format and also works fine on the Snow Leopard version.

Below is the modification we need to make , to change the Oracle Link-link manually in the Makefile :

$ diff
< ORACLE_LINKER=gcc -flat_namespace -mmacosx-version-min=10.5 -Wl,-no_compact_linkedit $(OLAPPRELINKOPTS) $(LDFLAGS) $(COMPSOBJS)

With this generated binary , DBCA should proceed through cleanly and so also the Oracle Database install on the Mac OS X Snow Leopard.

HP-UX software ( patch ) Information and query

Software and patch management in HP-UX is done using HP Software Distributor called SD-UX. The software in SD-UX is organized in a hierarchy of components or objects. These components are filesets, subproducts, products and bundles. The place where these components are stored is called a software depot.

Few Common Terms in SD-UX :

Filesets: It is a collection of files and some control scripts. It is the basic entity in the SD-UX hierarchy. One file set can belong to only on product. But it can be included in a number of sub-products and bundles.

Here is an example: Keyshell.KEYS-END-A-MAN B.11.30

1st field is the fileset name
2nd field is the fileset version

Sub-products: If a file set contains several filesets, it is better to combine logically related filesets in to subproducts.

Here is an example:
X11.MessagesByLang X11 Localized Messages

This sub-product contains the filesets for X11 messages in several languages.

It is nothing but a set of filesets. In another words, it is a superset of filesets / subproducts.

Here is an example ,
X11 B.11.30 HP-UX X Windows Software

X11 is the product name
B.11.30 is the product version
third field is the product description

Bundles: Bundles are usually packaged by HP-UX for the distribution of software. The bundle may contain filesets that may belong to different products.

Here is an example,
OnlineDiag B.11.20.06 HP-UX 11.0 Support Tools Bundle

Patch Commands
swconfig - configure software / patches
swlist - display software / patch information
swinstall - installs software / patches
swremove - removes software / patches

Patch Logs / Listing
/var/adm/sw/swagent.log --> contains entries from swagent daemon
/var/adm/sw/swinstall.log --> entries/errors from swinstall

Gather Patch Install/State data
swlist -l fileset -a state PH* > /tmp/swlist.txt
swlist product PH* > /tmp/swlist.txt ( $ swlist -l product 'PH??_*' )

Other patch Commands
check_patches --> Checks for common problems and issues ie. Patch attributes, missing patch filesets, etc.
/usr/contrib/bin/show_patches ---> displays only active patches on system

How to tell what patches are loaded using the swlist command (10.x)?
Patches are named PHxx_nnnn, where xx can be KL, NE, CO, or SS.
nnnn refers to the patch number, which is always unique no matter what PHxx category is specified.

If a patch has been loaded on a 10.x system, the patch should be listed in the output of swlist . All patches named PHKL*, and some patches named PHNE*, are kernel patches.

A patch name consists of the characters "PH" (Patch HP-UX), followed by a two-character type-identifier, followed by an underscore, followed by a four or five-digit number.

The currently defined patch types are:

CO - COmmands & libraries
KL - KerneL
NE - NEtworking
SS - SubSystems

Kernel patches always require a system reboot, so that the newly updated kernel can be loaded. Many Networking patches (PHNE*) also make modifications to the kernel, and hence require a reboot.

Note that the numerical portion of any given patch name is unique, among ALL patches. So there would never be a patch named "PHCO_23507", in addition to a patch named "PHKL_23507." This lends itself nicely to grepping for a particular patch (ie - to see if "PHKL_23507" is installed, one could use "swlist -l product | grep 23507" .

QPK = Quality Pack - which is a bundle of patches that HP provides twice yearly for each version of HP-UX.

HP-UX 11i v2
# swlist -l bundle BUNDLE11i HWEnable11i FEATURE11i QPKBASE QPKAPPS

HP-UX 11i v3
# swlist -l bundle BUNDLE11i HWEnable11i FEATURE11i QPKBASE

Contrast the installed patches against the latest available on

Examples :
To list the installed bundles :
# swlist -l bundle

To list the installed products :
# swlist -l product

To list the installed subproducts :

# swlist -l subproduct

To list the installed filesets alone :
# swlist -l fileset
# swlist -l fileset openssl

To list all the files belonging to the product X11 or fileset openssl :
# swlist -l file X11
# swlist -l file openssl

To open swlist in GUI mode :
# swlist -i

To view the readme file for a product :
# swlist -a readme OS-Core

To find out Which Operating Environment Currently installed
# swlist -l bundle | grep HPUX11i

To generate a comprehensive listing that includes all filesets for the product NETWORKING
# swlist -v -l fileset NETWORKING

To find out which product a file belongs to 1st way, its slow:
# swlist -l file |grep /bin/ls

2nd way much quicker, as root:
# find /var/adm/sw/products -name INFO -exec grep -l /bin/ls {} +

Thursday, July 9, 2009

Determining if your kernel and hardware is 32bit or 64bit on Unix environments


This technote explains how to establish if an HP-UX® 11.x kernel is 32-bit or 64-bit capable.

Run getconf KERNEL_BITS on the system in question. The output, either "32" or "64", corresponds to 32-bit or 64-bit kernels, respectively.

# getconf KERNEL_BITS

Check the vmunix file for the following entries:

# file /stand/vmunix
/stand/vmunix: PA-RISC1.1 executable ---> 32-bit
/stand/vmunix: ELF-64 executable object file ---> 64-bit

This will tell you if your currently running kernel is 64 bits or 32 bits.It returns the number of bits used by the kernel for pointer and long data types.

# getconf KERNEL_BITS

Returns which kernel is supported on the hardware.

# getconf HW_32_64_CAPABLE

This will show you if the CPU’s are capable of running 32, 64, or 32/64 bit kernels.

# getconf HW_CPU_SUPP_BITS


The easiest way to determine which version is running on your system is to use the isainfo command. This new command prints information about the application environments supported on the system.

The following is an example of the isainfo command executed on an UltraSPARC™ system running the 64-bit operating system:

% isainfo -v
64-bit sparcv9 applications
32-bit sparc applications

One useful option of the isainfo(1) command is the -n option, which prints the native instruction set of the running platform:

% isainfo -n

The -b option prints the number of bits in the address space ( cpu’s bit size capabilities ) of the corresponding native applications environment :

% isainfo -b

% echo "Welcome to "`isainfo -b`"-bit Solaris"
Welcome to 64-bit Solaris

A related command, isalist(1), that is more suited for use in shell scripts, can be used to print the complete list of supported instruction sets on the platform. Some of the instruction set architectures listed by isalist are highly platform specific, while isainfo(1) describes only the attributes of the most portable application environments on the system. Both commands are built on the SI_ISALIST suboption of the sysinfo(2) system call. See isalist(5) for further details.

The following is an example of the isalist command executed on an UltraSPARC system running the 64-bit operating system:

% isalist
sparcv9+vis sparcv9 sparcv8plus+vis sparcv8plus sparcv8
sparcv8-fsmuld sparcv7 sparc


For AIX, we will use the bootinfo command . The below command's shows if the hardware is 32 bit or 64 capable.

# bootinfo -y


# prtconf -c
CPU Type: 64-bit

Below commands show the running kernel’s bit size :

# bootinfo -K

# prtconf -k
Kernel Type: 64-bit



For linux, we will look at the cpuinfo from /proc. Here, we are mainly interested in the “flags” for the CPU’s:

# cat /proc/cpuinfo | grep -i flags
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx lm constant_tsc arch_perfmon pebs bts rep_good pni dtes64 monitor ds_cpl est tm2 ssse3 cx16 xtpr pdcm sse4_1 lahf_lm

We are interested in three values in the output, as they indicate the bit size capabilities of the CPU:

16 Bit = rm (Real Mode)
32 Bit = tm (Transparent Mode)
64 Bit = lm (Long Mode)

This doesn’t necessarily mean the Motherboard is capable of 64 bit.

To determine the bit size of your running kernel, you can also use getconf, similar to HPUX, to find this info:

# getconf LONG_BIT

This shows that my kernel is running 64 bit.

Tuesday, April 14, 2009

Create shared library on Unix

We will see how we can build dynamic libraries on different Unix flavours.

Apple Mac OS X

$ gcc -arch x86_64 -fno-common -c source.c
$ gcc -arch x86_64 -fno-common -c code.c
$ gcc -dynamiclib -flat_namespace -undefined suppress -install_name /usr/local/lib/libfoo.2.dylib
-o libfoo.2.4.5.dylib source.o code.o

When passed this option, GCC will produce a dynamic library instead of an executable when linking,
using the Darwin libtool command.

-arch arch
Compile for the specified target architecture arch. The allowable values are i386,x86_64,ppc and ppc64.

Use a single level address space for name resolution and done for al Unixes.

-undefined suppress
Supress undefined symbols.It will get resolved later from dependent libraries.

GNU Linux

gcc -m64 -fPIC -g -c -Wall a.c
gcc -m64 -fPIC -g -c -Wall b.c
gcc -m64 -shared -Wl,-soname, -o a.o b.o -lc

Generate position-independent code ( PIC ) suitable for use in a shared library.

Produce a shared object which can then be linked with other objects to form an executable.

Generate code for 32-bit or 64-bit environments


cc +DD64 -Aa -c +Z length.c volume.c mass.c ( 64-bit )
ld -b -o length.o volume.o mass.o

Specify the compilation standard to be used by the compiler.
Compile under ANSI mode

Both of these options cause the compiler to generate position independent code (PIC) in 32/64-bit respectively.

Recommended option for compiling in 64-bit mode on either Itanium-based or PA-RISC 2.0 architecture. The macros __LP64__ and (on PA platforms) _PA_RISC2_0 are #defined.

Compiles in 32-bit mode and on PA systems creates code compatible with PA-RISC 1.1 architectures. (Same as +DA1.1 and +DAportable.)

Compiles in 64-bit mode for the PA-RISC 2.0 architecture. The macros __LP64__ and _PA_RISC2_0 are #defined.

Compiles in 32-bit mode (narrow mode) for the PA-RISC 2.0 architecture. The macro _PA_RISC2_0 is #defined. +DA options are not supported on Itanium-based platforms.


cc -xarch=v9 -Kpic -c a.c
cc -xarch=v9 -Kpic -c b.c
ld -G -o a.o b.o

Generate position-independent code for use in shared libs.

Produce a shared object rather than a dynamically linked executable.

Specifies compiling for a 64-bit Solaris OS on SPARC platform.

Specifies compilation for the 64-bit AMD instruction set.The C compiler from studio 10 onwards predefines __amd64 and __x86_64 when you specify -xarch=amd64.

Using static and shared libraries across platforms

Shared Libraries (HP-UX)