Search This Blog

Thursday, September 03, 2009

Tracing ld

I was trying to do something with customized FreeBSD kernel which required constructors(.ctors) and destructor(.dtors) sections to be included in the final binary. So I used the normal gnu practice of including the following code into my linker script(/sys/conf/ldscript.i386).
.data.gcov :
__CTOR_LIST__ = .;
(__CTOR_LIST2__ - __CTOR_LIST__) - 2 )
__CTOR_LIST2__ = .;
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG(( __DTOR_END__ - __DTOR_LIST__ )/
(__CTOR_LIST2__ - __CTOR_LIST__) - 2)
__DTOR_END__ = .;
But when I tried to see the contents of of the linked kernel there were no constructors. Because
__CTOR_LIST__ and __CTOR_END__ are placed next to each other, from the linker script you can see the .ctors comes in between them.
$objdump -t kernel | grep __CTOR
c049cb8c g .data.gcov 00000000 __CTOR_LIST__
c049cb94 g .data.gcov 00000000 __CTOR_END__
c049cb90 g .data.gcov 00000000 __CTOR_LIST2__

$objdump -s -j .data.gcov kernel | head

kernel: file format elf32-i386-freebsd

Contents of section .data.gcov:
c049cb8c 00000000 00000000 00000000 00000000 ................
c049cb9c 5f090000 e7124ac0 e7124ac0 1b4a4ac0 _.....J...J..JJ.
c049cbac 1b4a4ac0 085c4ac0 085c4ac0 06234bc0 .JJ..\J..\J..#K.
c049cbbc 06234bc0 1f374bc0 1f374bc0 d43b4bc0 .#K..7K..7K..;K.
c049cbcc d43b4bc0 b1414bc0 b1414bc0 b2494bc0 .;K..AK..AK..IK.
c049cbdc b2494bc0 d77b4bc0 d77b4bc0 0e894bc0 .IK..{K..{K...K.
I tried to find what ld is doing by enabling --verbose option in SYSTEM_LD (/sys/conf/ but it did not help. Then I tried -Map option to ask ld to generate map file and it helped me.

In my environment the kernel is generated in step. First all system objects are partially linked(-r/-Ur option) to generate relocatable kernel. Then this relocatable kernel is linked with some other static modules to create the kernel. From the map files I could see the constructors are present in the relocatable kernel and dropped while creating the proper kernel. I guess it is a bug with ld. So I merged the two step process into one and it worked.

$objdump -t kernel | grep __CTOR
c049cf50 g .data.gcov 00000000 __CTOR_LIST__
c049f4e4 g .data.gcov 00000000 __CTOR_END__
c049cf54 g .data.gcov 00000000 __CTOR_LIST2__

$objdump -s -j .data.gcov kernel | head

kernel: file format elf32-i386-freebsd

Contents of section .data.gcov:
c049cf50 63090000 a7164ac0 a7164ac0 db4d4ac0 c.....J...J..MJ.
c049cf60 db4d4ac0 c85f4ac0 c85f4ac0 c6264bc0 .MJ.._J.._J..&K.
c049cf70 c6264bc0 df3a4bc0 df3a4bc0 943f4bc0 .&K..:K..:K..?K.
c049cf80 943f4bc0 71454bc0 71454bc0 724d4bc0 .?K.qEK.qEK.rMK.
c049cf90 724d4bc0 977f4bc0 977f4bc0 ce8c4bc0 rMK...K...K...K.
c049cfa0 ce8c4bc0 bbf74bc0 bbf74bc0 bb0a4cc0 ..K...K...K...L.


Prabhu said...

Sam dude!

You just helped me fix my putty window to reflect just the directory name when I swim in and out of directories...thanks a lot man! I was spending close to 2 hrs trying to get this done :)

The following addition to .bash_profile did the job:

export PS1='$PWD>^[]2;`basename $PWD`^G'

keep writing, will check your blog for other good stuff.