TipsAndTricks/PrelinkSomePointersAndWorkarounds

From Yocto Project
Revision as of 20:42, 20 September 2016 by Bavery (talk | contribs) (→‎The Ugly)
Jump to navigationJump to search

Prelink, What it does and how you can deal with it

Prelink is run across all the binaries and libraries as part of creating an image, by default. Because we prelink the libraries into the binaries, the binaries can no longer be binarily compared using standard tools like cmp.

The Good

This reduces startup time by "prelinking" the shared libs into the executable by relocating Wikpedia page on prelink. In my brief experiments, I found a ~15% speedup in boot time alone for instance.

The Bad

  • Prelink adds a timestamp in the files it modifies. I believe but have not verified that these timestamps are used to speed up subsequent runs of prelinking by allowing prelink to skip libraries that have not changed (based on time) since it's last run. This isn't really bad, I guess, though I'd like to be able to disable this feature in some cases. Unfortunately, since timestamps tend to be monotonically increasing, this also prevents the use of cmp to compare 2 binaries that are effectively the same.

The Ugly

  • We run prelink with the -R flag which chooses a random base for libraries. This means that even if you run prelink two times on the same binary or library, they will be different due to the random library placement. This is done as a security enhancement. This prelink call is located in meta/classes/image-prelink.bbclass :
         ${STAGING_SBINDIR_NATIVE}/prelink --root ${IMAGE_ROOTFS} -amR -N 
 -c ${sysconfdir}/prelink.conf --dynamic-linker $dynamic_loader 

So, How DO I Compare my Prelinked Binaries?

Once they are prelinked, you need to use the prelink tool itself to do the comparison. In theory this can be done using

 prelink -y --verify which "Verify file consistency by undoing and redoing  prelink and printing original to standard output" 

from the host environment. Getting prelink to run successfully from the host side is complicated by the fact that it needs a number of arguments to be happy. My example will be for qemux86 and core-image-minimal. Paths will need to be adjusted for other combinations. Note that the dynamic linker and the target are relative to the -root arg.
This will print out the md5 sum of the binary:

 ./tmp/sysroots/x86_64-linux/usr/sbin/prelink  --root ./tmp/work/qemux86-poky-linux/core-image-minimal/1.0-r0/rootfs   --dynamic-linker /lib/ld-linux.so.2 --verify --md5 /bin/busybox.nosuid       

This will let you dump the original unprelinked binary for comparison:

  ./tmp/sysroots/x86_64-linux/usr/sbin/prelink  --root ./tmp/work/qemux86-poky-linux/core-image-minimal/1.0-r0/rootfs   --dynamic-linker /lib/ld-linux.so.2 -y --verify  /bin/busybox.nosuid >   busybox.nosuid.unmodded 

How do I turn off Prelink if I find this too Cumbersome?

in conf/local.conf override the default value of USER_CLASSES . This defaults to:

 USER_CLASSES ?= "buildstats image-mklibs image-prelink"  

and change it to

 USER_CLASSES = "buildstats image-mklibs "  

This will result in your binaries not being prelinked, which means they will be slower to start up but easier if you need binary comparisons.

What If I Want to be Able to Run Prelink on my Target

You can add IMAGE_INSTALL_append = " prelink" (note the space) to you conf/local.conf file. For qemux86 this worked fine for me. For x86-64 there was an issue and the workaround is documented in this bug: [1].