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__ = .;
LONG((__CTOR_END__ - __CTOR_LIST__) /
(__CTOR_LIST2__ - __CTOR_LIST__) - 2 )
__CTOR_LIST2__ = .;
KEEP(*(.ctors))
LONG(0)
__CTOR_END__ = .;
__DTOR_LIST__ = .;
LONG(( __DTOR_END__ - __DTOR_LIST__ )/
(__CTOR_LIST2__ - __CTOR_LIST__) - 2)
KEEP(*(.dtors))
LONG(0)
__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/kern.pre.mk) 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.

1 comments:

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.