Monday, December 28, 2009

Conditional inclusion of header files

Ram (one of my peers, name changed) complained that he was unable to create an object of class (say clsX).

We have the practise of having our class declarations in header files. So the declaration of the class clsX was in X.h file.

To define an object of class clsX in a soure file, Ram had included the header file X.h in the source file. Despite that he was unable to define the object of class clsX. He got compiler error for the same.

Ram complained Ravi (one of my peers, name changed) that he was unable to create an object of class clsX. Ravi is the one who wrote the class clsX.

Ravi worked on it to provide the following report:
  1. I am not sure about why this problem is occurring, but it seems to be because of some issue with C++ compilers, as mentioned in these two posts I found for the error C2143 -
    1. http://sabbour.wordpress.com/2006/12/30/error-c2143-syntax-error-missing-before/
    2. http://www-subatech.in2p3.fr/~photons/subatech/soft/carnac/CPP-INC-1.shtml
  2. I tried moving the class declaration to the source file, and then removed the header file inclusion. The problem was resolved, which means the contents of the header file 'clsX.h' do not have any syntax error.
  3. I removed the inclusion of the header file 'clsX.h' and instead used a forward declaration as follows, and this solution worked fine.
  4. Please use a forward declaration for the class clsTable, as mentioned in point 3 above, to continue your analysis. I shall look into the problem further to ascertain the root cause.
I decided to have a hand on the problem under discussion. By seeing the compiler error, I got that the declaration of the class clsX didn't reach the source file despite the inclusion of header file X.h.

We use preprocessor directives to conditionally include a header file content into other source file. This is to avoid the duplication of declarations.

On checking the macro that is used along with the preprocessor directives in X.h, I found that the macro used is already defined in some other header file (say Y.h). The header file Y.h is already included in the source file in which X.h is also included. Because of which the macro defined in Y.h eliminated the inclusion of X.h contents.

I.e.

Y.h
 #ifndef _Y_H
 #define _Y_H
 ...
 ...
 #endif

X.h
 #ifndef _Y_H
 #define _Y_H
 declaration of class clsX
 #endif

Z.c
 #include "../Y/Y.h"
 #include "../X/X.h"
 define object of class clsX

Here you can see that the contents of header file X.h (I.e. declaration of class clsX), won't be included. This is because the contents of header file X.h would be included in file Z.c only if the macro _Y_H is not defined before. But macro _Y_H is already defined in Z.c by the inclusion of header file Y.h.

I pointed out the mistake of using the same macro for two header files which solved the problem.

Monday, November 30, 2009

Sharing files/folders to Windows clients from linux (Ubuntu)

Right click the folder that needs to be shared. Select the option 'Sharing Options'. The file manager window gets open.



Enable 'Share this folder'. On doing so, if the sharing service is not installed the following window will appear.



Press the button "Install service". It will install the SMB service.



After successful installation, it will ask to retsart your session.



Press the button "Restart session".

And now add a SMB user. To do so, open the terminal in Ubuntu and type the following command.

 sudo smbpasswd -a username

This will ask for the new SMB password for the username given. Provide the SMB password. After successful addition of SMB user, the shared folder can be accessed from the windows client using the username and password created.

End Of Line (EOL) in Linux and Windows

The end of a line of text is marked by the EOL character. The EOL character differs between Windows and Linux.

In Linux, the EOL character is line feed (LF) character '\n'. Whereas in Windows, the EOL character is carriage return (CR) character '\r' followed by the line feed (LF) character '\n'.

For example, create a text file containing the following in both Linux (LinuxSampleTxtDocument.txt) and Windows (WindowsSampleTxtDocument.txt).

 this is first line
 this is second line
 this is third line

And dump the contents of both the files.
sh-3.1$ hexdump -cb LinuxSampleTxtDocument.txt
0000000   t   h   i   s       i   s       f   i   r   s   t       l   i
0000000 164 150 151 163 040 151 163 040 146 151 162 163 164 040 154 151
0000010   n   e  \n   t   h   i   s       i   s       s   e   c   o   n
0000010 156 145 012 164 150 151 163 040 151 163 040 163 145 143 157 156
0000020   d       l   i   n   e  \n   t   h   i   s       i   s       t
0000020 144 040 154 151 156 145 012 164 150 151 163 040 151 163 040 164
0000030   h   i   r   d       l   i   n   e  \n
0000030 150 151 162 144 040 154 151 156 145 012
000003a

sh-3.1$ hexdump -cb WindowsSampleTxtDocument.txt
0000000   t   h   i   s       i   s       f   i   r   s   t       l   i
0000000 164 150 151 163 040 151 163 040 146 151 162 163 164 040 154 151
0000010   n   e      \r  \n   t   h   i   s       i   s       s   e   c
0000010 156 145 040 015 012 164 150 151 163 040 151 163 040 163 145 143
0000020   o   n   d       l   i   n   e  \r  \n   t   h   i   s       i
0000020 157 156 144 040 154 151 156 145 015 012 164 150 151 163 040 151
0000030   s       t   h   i   r   d       l   i   n   e
0000030 163 040 164 150 151 162 144 040 154 151 156 145
000003c

Sunday, November 29, 2009

Mounting external hard disk

Once my external hard disk is not properly removed after use from Windows OS. And when I tried to access the hard drive using Linux (Ubuntu) OS, I faced the problem of failure in mounting the drive. Following is the snapshot of the diagnostic I received on connecting the external hard disk to Linux (Ubuntu) OS.


To fix the problem I forced the mount of external hard disk manually. The manual mount of external hard disk is done using the following commands in terminal.

sudo mount -t ntfs-3g /dev/sdb1 /media/disk/ -o force

And unmounted the external hard disk using the following command:

sudo umount /media/disk/


The problem got fixed. On subsequent access I found that the external hard disk is mounted automatically by the Linux (Ubuntu) OS.

Monday, October 12, 2009

Large executables for GCC built on Windows (cygwin/MinGW) - how to reduce the size?

Yes, the large executables for GCC built on Windows (cygwin/MinGW) can be reduced.

First we see why such a large executable?

Generally the size of executables built on Windows (cygwin/MinGW) would be larger than 20 MB (this metric is derived by experimenting with the build of GCC compiler for IA64). This is because of the presence of symbol information for debugging.

If the executable built is not for debugging, then the symbol information shall be stripped-off from the executable.

Strip-off symbol information from executable

The symbol information can be stripped-off from the executable (built on either cygwin or MinGW) by any of the following ways:

  1. Strip utility from binutils
  2. Set the environment variable "CFLAGS" with '-s'

1. Strip utility of binutils

The strip utility of binutils removes symbols from object file. The symbol information from the executable can be stripped-off as follows:
strip cc1.exe

Note: Assume the executable from which the symbol information is to be removed is "cc1.exe".

2. Set the environment variable "CFLAGS" with '-s'

The environment variable "CFLAGS" should be set with '-s' before the build of executable on cygwin/MinGW.

I.e. The environment variable CFLAGS can be set in the shell as follows:
export CFLAGS="-s"

Note: To check whether the enovironment variable CFLAGS is set or not, use the shell command "env". The shell command "env" would list of environment variables.

After stripping off the symbol information, the size of the executable would be reduced to ~7 MB (this metric is derived by experimenting with the build of GCC compiler for IA64).

Executable Compression

The size of the executable can be reduced further by executable compression. Refer executable compression.

The executable compression can be done using the executable packer UPX. UPX is a free and open source executable packer. For details on UPX, refer upx.sourceforge.net.

The executable compression can be done as follows (in windows command prompt):
upx cc1.exe

Note: Assume the executable to be compressed is "cc1.exe".

After compressing the executable, the executable size would be reduced to ~2 MB (this metric is derived by experimenting with the build of GCC compiler for IA64).

Thursday, September 17, 2009

Default boot in dual boot systems

Most of us have dual boot on PCs/laptops. One for linux OS and the other for Windows OS.

The default boot would be linux OS. I.e. While the system is switched on and no selection on OS to boot is made, the boot done would be the linux OS.

And if anyone wants to work on Windows and he/she forgot to make the selection, the system might end-up in booting the linux OS.

Some people may mostly work on windows and they have linux for their least purpose. For them it would be better if the default boot is Windows.

So how to change it?

Simple! The dual boot is done by the GRUB (GRand Unified Bootloader). A change in GRUB is needed to employ this change. To do the change in GRUB first boot the linux OS on the system. Open the file "/boot/grub/menu.lst". At line 14 of file "/boot/grub/menu.lst", change the entry number of the "default" entry with the number corresponding to the entry for Windows OS. The entry list can be seen at the end of the file "/boot/grub/menu.lst".

An Example:

Before modification, the file "/boot/grub/menu.lst" was:

default 0
...
...
...
title Ubuntu 8.10, kernel 2.6.27-11-generic
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-11-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro quiet splash
initrd /initrd.img-2.6.27-11-generic
quiet

title Ubuntu 8.10, kernel 2.6.27-11-generic (recovery mode)
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-11-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro single
initrd /initrd.img-2.6.27-11-generic

title Ubuntu 8.10, kernel 2.6.27-7-generic
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-7-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro quiet splash
initrd /initrd.img-2.6.27-7-generic
quiet

title Ubuntu 8.10, kernel 2.6.27-7-generic (recovery mode)
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-7-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro single
initrd /initrd.img-2.6.27-7-generic

title Ubuntu 8.10, memtest86+
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /memtest86+.bin
quiet

### END DEBIAN AUTOMAGIC KERNELS LIST

# This entry automatically added by the Debian installer for a non-linux OS
# on /dev/sda1
title Microsoft Windows XP Professional
root (hd0,0)
savedefault
makeactive
chainloader +1

Here the entry number of "default" entry is '0'. The entry number '0' corresponds to first entry (i.e. Ubuntu 8.10, kernel 2.6.27-11-generic) of the OS list at the bottom of the file "/boot/grub/menu.lst". So by default the linux OS Ubuntu will get booted.

Now to change the default boot to Windows OS, the entry number of "default" entry should be changed to '5'. The entry number '5' corresponds to the fifth entry (i.e. Microsoft Windows XP Professional") of the OS list at the bottom of the file "/boot/grub/menu.lst".

After modification, the file "/boot/grub/menu.lst" is as follows:

default 5
...
...
...
title Ubuntu 8.10, kernel 2.6.27-11-generic
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-11-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro quiet splash
initrd /initrd.img-2.6.27-11-generic
quiet

title Ubuntu 8.10, kernel 2.6.27-11-generic (recovery mode)
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-11-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro single
initrd /initrd.img-2.6.27-11-generic

title Ubuntu 8.10, kernel 2.6.27-7-generic
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-7-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro quiet splash
initrd /initrd.img-2.6.27-7-generic
quiet

title Ubuntu 8.10, kernel 2.6.27-7-generic (recovery mode)
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /vmlinuz-2.6.27-7-generic root=UUID=7d85ba3f-2c1d-4f1e-b30d-6d1df00ac7a3 ro single
initrd /initrd.img-2.6.27-7-generic

title Ubuntu 8.10, memtest86+
uuid 17d035fe-5a14-49b6-887e-1a3ccd553e32
kernel /memtest86+.bin
quiet

### END DEBIAN AUTOMAGIC KERNELS LIST

# This entry automatically added by the Debian installer for a non-linux OS
# on /dev/sda1
title Microsoft Windows XP Professional
root (hd0,0)
savedefault
makeactive
chainloader +1

Now the default boot is Windows OS.

GCC build on Windows

GCC relies on POSIX (Portable Operating System Interface) functionality which is not available in Windows natively. Hence for building GCC on windows, a linux-like environment for Windows is used. The linux-like environment for windows is brought via:

  1. cygwin (or)
  2. MinGW (Minimalist GNU for Windows)

Both cygwin and MinGW output windows executable ('.exe' file). But the executable built on cygwin has the cygwin DLL dependency (I.e. The GCC compiler executable to run, the required cygwin DLLs should be made available to the executable). Whereas the executable built on MinGW has no such dependency.

Thursday, August 27, 2009

DLLs used by the cygwin built executables

For Windows executable that are built in cygwin to run, the executable depends on some DLLs of cygwin. Hence the executable cannot run on a PC with Windows that sans those DLLs of cygwin.

For such executable to run on PCs with Windows, the dependent DLLs should also be used along with the executable.

Ok, how to find out on what DLLs a executable that built on cygwin depends? Simple, to list out the DLLs use
  • objdump -p executable.exe | grep "DLL Name"

For example, I listed the DLLs used by executable 'cc1.exe'. 'cc1.exe' is generated in cygwin. 'cc1.exe' is a compiler generated using GCC.

D:\GCC>objdump -p cc1.exe | grep "DLL Name"
DLL Name: cygwin1.dll
DLL Name: cygiconv-2.dll
DLL Name: cygintl-8.dll
DLL Name: KERNEL32.dll

Wednesday, August 26, 2009

Enumeration constant in Macro definition

We use symbolic constants to get rid off magic numbers - hard coded values in programs. There three ways to define symbolic constants. They are
  1. Macros
  2. enumeration constants
  3. const objects
Among the above three, the standard coding practice suggests to use the enumeration constant for programming.

Refer symbolic constants for the details on the above three methods.

The above is just a pre-requisite for further reading.

For porting GCC (GNU Compiler Collection - a compiler generation framework) to a new architecture, we require to feed in the information of the new architecture into the GCC. This information on new architecture is feed into GCC in the form of machine description. The machine descriptions include macros and LISP like languages for defining the new architecture.

There are macros that would define the information on new architecture registers. Each such macro is defined with the corresponding register number.

For example,

#define FIRST_PSEUDO_REGISTER 32

The macro FIRST_PSEUDO_REGISTER defines the register number that can be given to the first pseudo (scratch) register. The register numbers for the pseudo registers should start from the number next to the last actual register (as in architecture) number. Consider there are 32 actual registers in the architecture. Then the actual registers are with numbers from 0 to 31. So, from the number (32) next to the last actual register (31), shall be assigned to the pseudo registers.

Hence the macro FIRST_PSEUDO_REGISTER is defined with the total number of registers.

Then there is another macro,

#define STACK_POINTER_REGNUM 30

The macro STACK_POINTER_REGNUM defines the register number that would be used as stack pointer.

Similarly there are other macros. Here we are to use such numbers of registers for defining the macros. What we thought of is, instead of magic numbers of registers why can't we have a enumeration that defines the constants for the registers in an architecture. If that is so, we can just use the enumeration constant names in place of the numbers.

And we did as follows:

#define FIRST_PSEUDO_REGISTER eTOTAL_REGISTERS_KNOWN_TO_COMPILER

#define STACK_POINTER_REGNUM eR7


And do you think this is safe? Could you see there could be some problems in doing so?

Yes, it is true we didn't see anything while doing so. But we ended-up in failure while building the compiler.

One thing we didn't think about the macros. That is, preprocessor plays some part with the numbers defined by the macros. The macros are used in the preprocessor statements. In such case, the numbers should be visible at the time of preprocessing. If we use the enumeration constant names as shown above, the preprocessor cannot see that as a number.

For example consider the below code with preprocessor statements:

#if FIRST_PSEUDO_REGISTER
// do something
#endif

for defining the macro 'FIRST_PSEUDO_REGISTER' with enum constant 'eTOTAL_REGISTERS_KNOWN_TO_COMPILER', the preprocessor would check as follows:

#if eTOTAL_REGISTERS_KNOWN_TO_COMPILER
// do something
#endif

#IF ... #ENDIF preprocessor directive conditionally includes source code at compile-time. The preprocessor expects for a numeric expression whereas here it gets a string 'eTOTAL_REGISTERS_KNOWN_TO_COMPILER'. And hence the source code inside #IF ... #ENDIF is not included for compilation. This is the cause for the problem during build.

Wednesday, August 19, 2009

OSS - explained

I was on the board of flight "Madurai to Mumbai" (within India). I got into conversation with a person sitting next to me. We introduced ourselves and discussed about eachother's profession. On hearing I am working on open source software (GCC) he asked what is a open source software and if it is for free how you people are making business out of it.

Not him, but many would be having these questions in their mind unanswered. How business is made out of open source softwares (here-in-after referred as OSS)?

OSS are softwares that should be freely distributed along with it's source code. Anyone must be allowed to modify the source code which can be redistributed further. Also it's license should not exclude the OSS to interfere with the operation of other softwares.

Some examples of OSS.
  1. GNU/Linux operating system
  2. GNU Compiler Collection(GCC)
  3. Apache HTTP Server
  4. Mozilla Firefox internet browser
  5. OpenOffice
  6. Perl language
  7. PHP language
  8. Python language
OSS is gaining popularity because OSS is free. I.e. OSS can be used, bought, sold, given, received, and modified. In fact, anything can be done with OSS except take ownership of it or restrict anyone else from having the same rights to it that one have.

OSS is freely available to provide the freedom for the following:
  1. to run the program for any purpose
  2. to study how the program works and adapt the same for own use
  3. to redistribute copies
  4. to improve the program and release your improvements to the public, so that the whole community benefits.
A common concern for end-users who wish to use open source software is the lack of a warranty and technical support. Companies gains by providing support to OSS users. I.e. They can act as consultants. They have access to source code, and hence they can provide better support.

For example, Red Hat created the "Official Red Hat Linux" and is able to sell this normally "free" software. The main value that Red Hat adds to the package is a warranty and technical support. For most businesses, the assurance of technical support has been a key factor in the decision to buy Linux instead of simply downloading it for free. In addition to Red Hat, there are several other companies that have packaged Linux, usually with additional software, for resale.