Stefano Zacchiroli: h-index spoofing
| [1] | Ike Antkare. Ike
Antkare one of the great stars in the scientific
firmament. April, 2010. http://membres-lig.imag.fr/labbe/Publi/IkeAntkareSub.pdf, retrieved November 25th, 2010. |
| [1] | Ike Antkare. Ike
Antkare one of the great stars in the scientific
firmament. April, 2010. http://membres-lig.imag.fr/labbe/Publi/IkeAntkareSub.pdf, retrieved November 25th, 2010. |
Heya Sergio
Your blog doesn t allow comments :-( so I reply here. First off, thanks for being one of the first Debian developers in trying out my modified installer with ZFS support, you guys made my day!
Some quick notes on the bugs you found:
The missing //@ prefix bug is #600578, fixed in upstream, in sid and in squeeze. Thanks :-)
The boot partition stays in /target/boot in final install bug is not in BTS. It was present in a preliminar version of partman-zfs which was never uploaded. The version currently in the archive correctly uses altroot option to fix this.
The /lib/modules is needed for boot problem was reported as #600568, but I haven t been able to persuade the kFreeBSD maintainers that this is necessary. It s not critical anyway.
Glad you finally got a working setup.
Colin Watson is not a high-profile Debian figure, you rarely see him on mailing lists but he cares a lot about Debian and you will see him on Debconf videos sharing many thoughtful comments. I have the pleasure to work with him on dpkg as he maintains the package in Ubuntu, but he does a lot of more interesting things. I also took the opportunity to ask some Ubuntu specific questions since he s worked for Canonical since the start. Read on.
My questions are in bold, the rest is by Colin.
Who are you?
Hi. I m 32 years old, grew up in Belfast in Northern Ireland, but have been living in Cambridge, England, since I was 18. I m married with a stepson and a daughter.
I became interested in Debian due to the critical mass of Debian work happening in Cambridge at the time (and perhaps more immediately because my roommate was running Debian: hey, what s that? ), started doing random bits of development in 2000, and joined as a developer in 2001 (a really exciting time, with lots of new people joining who became integral parts of the project). I d only really been intending to do QA work and various bits of packaging around the edges, and maybe some work on the BTS, but then Fabrizio Polacco died and I took over man-db from him, and it sort of snowballed from there.
I graduated from university shortly before becoming a Debian developer. I worked for a web server company (Zeus), then a hardware cryptography company (nCipher), before moving to work for Canonical in 2004, since when I ve been working full-time on Ubuntu. By this point, I suspect that going back to work in an office every day would be pretty tough.
What s your biggest achievement within Debian or Ubuntu?
One thing I should say: I rarely start projects. Firstly I don t think I m very good at it, and secondly I much prefer coming on to an existing project and worrying away at all the broken bits, often after other people have got bored and wandered off to the next new and shiny thing. That s probably why I ended up in the GNU/Linux distribution world in the first place, rather than doing lots of upstream development from the start I like being able to polish things into a finished product that we can give to end users.
So, I ve had my fingers in a lot of pies over the years, doing ongoing maintenance and fixing lots of bugs. I think the single project I m most proud of would have to be my work on the Debian installer. I joined that team in early 2004 (a few months before Canonical started up) partly because I was a release assistant at the time and it was an obvious hot-spot, and partly because I thought it d be a good idea to make sure it worked well on the shiny new G4 PowerBook I d just treated myself to. I ended up as one of the powerpc d-i port maintainers for a while (no longer, as that machine is dead), but I ve done a lot of core work as well: much of the work to put progress bars in front of absolutely everything that used to have piles of text output, rescue mode, the current kernel selection framework, a good deal of udev support, several significant debconf extensions, lots of os-prober work, and I think I can claim to be one of the few people who understands the partitioner almost top to bottom. 11 comments Liked this article? Click here. My blog is Flattr-enabled.
Just over a month ago I bought a Wikireader [1] from Officeworks (an Australian chain of stores that sell all manner of office supplies). It cost only $99, thanks to Brianna for informing me about this [2]. When I purchased my Wikireader an Officeworks employee had to get one from the back office and told me that I was the first person to buy one. I suggested to him that when a product isn t mentioned in their advertising and isn t put on the shelves it s unlikely to sell in quantity and that they shouldn t rely on bloggers to promote what is possibly one of the most desirable products that they stock.The Wikireader stores a copy of the text of the English language version of Wikipedia on a micro-SD card. They have a service whereby you can get two updates posted to you every year for $29, which would make it pretty close to free once postage and the cost of the micro-SD cards is taken into account. Also you can download new content. I have no immediate plans for updating my Wikireader as the content is more than good enough to answer idle questions while waiting for a bus but as it s lacking external links due to no net access and images it can t be used for serious Wiki reading IMHO.Brianna has documented the process of updating a Wikireader to add more content [3], she added the Chinese version and discovered that inter-wiki links are preserved! I have no immediate plans to add extra content (I don t know any other language well enough to read an encyclopaedia). Also an 8GB MicroSD card (which is the minimum requirement to use multiple languages) costs $35 and is a significant portion of the original purchase price.In terms of functionality the device is pretty good. The screen is not back-lit, but if it was then the two AA batteries wouldn t last anywhere near a year. The screen is not high resolution and the touch functionality isn t particularly accurate or sensitive but I guess that s a necessary trade-off to get the $99 price. The Wikipedia content seems quite complete, so far the only page which I found to be missing was the bio of an Australian architect, I m not sure if his page was removed from the Wikireader to save space or whether my device has a snapshot that predates the addition of the page.The Wikipedia page about downloading the database is interesting [4], it s 6GB of compressed data for the text of the English pages (not including history or talk pages) and for years they haven t even tried to provide a dump of the images. So I guess that a Wikireader that displays pictures is out of the question.The Wikireader has a parental filter, in my quick tests the only page that has been blocked is Sexual Intercourse , I could read all about safe-sex, infidelity, and lots of other related adult topics without being asked for a password. It also shows pages about goatse and other related things without asking for a password NB if you don t know what goatse is then you probably don t want to learn, trust me that it s something that most people won t want their children to learn about. The filter is so bad that I think they shouldn t include it, it will just give people false confidence. It s OK to sell a cheap device that is designed to give a detailed description of goatse etc on request to anyone, but IMHO it s not OK to sell such a device with a claim that it is kid safe and has parental controls . Note that holding down the History button will allow you to clear your history this is useful if you have just verified that goatse isn t blocked and you want to give the device to a young child.There is a button to give a random page, I believe that this would be more useful if it had some metric to make it more often return pages that might be interesting. It could weight the randomness by the length of the page (usually a longer page is more interesting to more people and has more links to other pages) or by some other metric that indicates the potential popularity. Random links often get me pages about obscure country towns and other things that probably aren t of interest to people who don t live near them.But overall this is a great product, $99 is not much to pay, and I recommend getting one!
For the Freaky Wall I have installed a Debian GNU/kFreeBSD system
using the installer with ZFS support announced on:
http://robertmh.wordpress.com/2010/09/06/debian-installer-with-zfs/
I used the mini.iso found on:
http://people.debian.org/~rmh/zfs/kfreebsd-amd64/monolithic/mini.iso
the 12th of October of 2010; as I had some problems and reported them to
Robert is possible that the current image solves part of them.
Installation plan
I did a standard installation on a machine with two hard disks, but only used
the first one from the installer.
The plan was to use ZFS with RAID-1, but current versions of grub do not
support booting from a ZFS + RAID file system, so I had to use the same
technique used for Linux for a long time; three partitions: a swap partition,
a small /boot partition and a big partition for /; / and /boot were
formated to use ZFS.
First reboot
After the installation the system failed to boot because of a bug when
building the /boot/grub/grub.cfg (some routes were missing a //@ prefix);
to be able to boot Iwe edited the config on the grub prompt and later fixed
the file:
--- grub.cfg.orig 2010-10-13 16:40:39.000000000 +0200
+++ grub.cfg 2010-10-13 18:38:47.535436766 +0200
@@ -64,7 +64,7 @@
set root='(hd0,1)'
search --no-floppy --fs-uuid --set a371979bb836d1fe
echo 'Loading kernel of FreeBSD 8.1-1-amd64 ...'
- kfreebsd /kfreebsd-8.1-1-amd64.gz
+ kfreebsd //@/kfreebsd-8.1-1-amd64.gz
insmod part_msdos
insmod zfs
set root='(hd0,3)'
@@ -75,7 +75,7 @@
insmod zfs
set root='(hd0,1)'
search --no-floppy --fs-uuid --set a371979bb836d1fe
- kfreebsd_module /zfs/zpool.cache type=/boot/zfs/zpool.cache
+ kfreebsd_module //@/zfs/zpool.cache type=/boot/zfs/zpool.cache
set kFreeBSD.vfs.root.mountfrom=zfs:dkfbf1-ad4s3
set kFreeBSD.vfs.root.mountfrom.options=rw
I haven't tested the installer since that day, but I believe that the current
ZFS installer was fixed by Robert to deal with that problem.
Once the system was booted I had to fix a couple of things:
dpkg-reconfigure kbdcontrol
/boot partition was mounted on /target/boot, as that was what was
recorded on the ZFS file system; to fix it I executed the following commands:
# zfs set mountpoint=/ dkfbf1-ad4s3
# zfs set mountpoint=/boot dkfbf1-ad4s1
Where dkfbf1-ad4s3 is the root file system and dkfbf1-ad4s1 is the
original /boot.
I reported that to Robert also and I believe it is fixed on the ZFS
installer now.parted; the final result was:
# parted -l
Model: ST3250620NS/3BKS (ide)
Disk /dev/ad6: 250GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 256MB 255MB primary
2 256MB 4256MB 4000MB primary
3 4256MB 250GB 246GB primary
Model: ST3250620NS/3BKS (ide)
Disk /dev/ad4: 250GB
Sector size (logical/physical): 512B/512B
Partition Table: msdos
Number Start End Size Type File system Flags
1 1049kB 256MB 255MB primary
2 256MB 4256MB 4000MB primary linux-swap(v1)
3 4256MB 250GB 246GB primary
To use the second partition of both disks as swap I added the following to
/etc/fstab:
/dev/ad4s2 none swap sw 0 0
/dev/ad6s2 none swap sw 0 0
To configure the mirroring for the root file system I did the following:
zpool attach dkfbf1-ad4s3 ad4s3 ad6s3
As the /boot can't work as a replica I adjusted it to make two copies of
every file:
zfs set copies=2 dkfbf1-ad4s1
Leaving the second disk copy alone, although my plan is to configure it to
hold a copy of the /boot partition synchronized with rsync each night.
After all those changes the system didn't boot, as the grub-pc generates a
buggy /boot/grub/grub.cfg; the problem is on the /etc/grub.d/10_kfreebsd
section:
### BEGIN /etc/grub.d/10_kfreebsd ###
menuentry 'Debian GNU/kFreeBSD, with kFreeBSD 8.1-1-amd64' --class debian \
--class gnu-kfreebsd --class gnu --class os
insmod part_msdos
insmod zfs
set root='(hd0,1)'
search --no-floppy --fs-uuid --set a371979bb836d1fe
echo 'Loading kernel of FreeBSD 8.1-1-amd64 ...'
kfreebsd /kfreebsd-8.1-1-amd64.gz
set kFreeBSD.vfs.root.mountfrom=unknown:/dev/ad4s3
set kFreeBSD.vfs.root.mountfrom.options=rw
### END /etc/grub.d/10_kfreebsd ###
To fix it there has to be a copy of the modules for ZFS on the boot partition
(in my case I moved the /lib/modules directory to /boot and created a
link on the root partition to the new directory):
cd /boot
mkdir lib
mv /lib/modules lib
cd /lib
ln -s ../boot/lib/modules
And instead of fixing the /etc/grub.d/10_kfreebsd code I wrote a new
script (/etc/grub.d/09_zfs_kfreebsd) that creates the right config for my
current configuration on the grub.cfg file:
#!/bin/sh
prefix=/usr
exec_prefix=$ prefix
bindir=$ exec_prefix /bin
libdir=$ exec_prefix /lib
. $ libdir /grub/grub-mkconfig_lib
prepare_boot_cache="$(prepare_grub_to_access_device $ GRUB_DEVICE_BOOT sed -e "s/^/\t/")"
kfreebsd_versions="$(ls /lib/modules/)"
zfs_root_device="$(zfs list awk '/\/$/ print $1 ' head -1)"
for kversion in $kfreebsd_versions; do
cat << EOF
# Entry when using ZFS (we have issues with /etc/grub.d/10_kfreebsd)
menuentry 'Debian GNU/kFreeBSD, with kFreeBSD $kversion and ZFS' --class debian --class gnu-kfreebsd --class gnu --class os
$ prepare_boot_cache
echo 'Loading kernel of FreeBSD $kversion ...'
kfreebsd //@/kfreebsd-$kversion.gz
kfreebsd_module_elf //@/lib/modules/$kversion/opensolaris.ko
kfreebsd_module_elf //@/lib/modules/$kversion/zfs.ko
kfreebsd_module //@/zfs/zpool.cache type=/boot/zfs/zpool.cache
set kFreeBSD.vfs.root.mountfrom=zfs:$zfs_root_device
set kFreeBSD.vfs.root.mountfrom.options=rw
EOF
done
I solved the problem this way to have a working solution that does not break
with squeeze upgrades, assuming that a future grub-pc package will deal well
with my config and I'll be able to remove this script, but I guess I'll have
to install it from backports.
The entry generated by the script when called from update-grub will be
similar to:
### BEGIN /etc/grub.d/09_zfs-kfreebsd ###
# Entry when using ZFS (we have issues with /etc/grub.d/10_kfreebsd)
menuentry 'Debian GNU/kFreeBSD, with kFreeBSD 8.1-1-amd64 @ ITI' --class debian --class gnu-kfreebsd --class gnu --class os
insmod part_msdos
insmod zfs
set root='(hd0,1)'
search --no-floppy --fs-uuid --set a371979bb836d1fe
echo 'Loading kernel of FreeBSD 8.1-1-amd64 ...'
kfreebsd //@/kfreebsd-8.1-1-amd64.gz
kfreebsd_module_elf //@/lib/modules/8.1-1-amd64/opensolaris.ko
kfreebsd_module_elf //@/lib/modules/8.1-1-amd64/zfs.ko
kfreebsd_module //@/zfs/zpool.cache type=/boot/zfs/zpool.cache
set kFreeBSD.vfs.root.mountfrom=zfs:dkfbf1-ad4s3
set kFreeBSD.vfs.root.mountfrom.options=rw
### END /etc/grub.d/10_iti-kfreebsd ###
And after rebooting the machine with this new configuration the system boots
OK.
On my next post I'll continue explaining how to compile a kernel that supports
the use of the OpenBSD Packet Filter and related technologies (CARP, pflog,
etc.).
Just recently someone asked on #debian.de how to extract the 3rd to
8th character out of some string. That reminded me that the GNU
Coreutils tool cut is also quite unknown.
The solution to his problem is:
$ echo Hurzlipuh cut -c3-8 rzlipuMy favourite usage of cut is to restrict the output of programs which can t do that themselves to 80 columns (common terminal width):
$ dpkg -l grep -i macro cut -c-80 ii docbook-to-man 1:2.0.0-28 ii latex-cjk-common 4.8.2+git20090105-5 ii m4 1.4.14-3 ii mp4h 1.3.1-5 rc swfdec-gnome 2.28.0-1cut can cut out columns based on characters (-c), bytes (-b), fields (-f) delimited by tab (or the delimiter given by -d). After many comments: Yes, dpkg -l is capable of restricting and even fitting its output to the number of available columns if $COLUMNS is passed as environment variable. (And $COLUMNS is set by default in the shell, but not exported as environment variable as it may change on terminal resize or WINCH signal.)
As you re using a Palm Pre, I d request you to switch on Palm Pre by following the steps provided belowOf course, I m so silly I forgot to switch the phone on! Any suggestions for a UK SIM-only provider with a clue (and optionally including free use of Cloud hotspots)?

#!/bin/sh
set -e
IMAGES=/boot/images
. /usr/lib/grub/grub-mkconfig_lib
if test -e /boot/memdisk ; then
MEMDISKPATH=$( make_system_path_relative_to_its_root "/boot/memdisk" )
echo "Found memdisk: $MEMDISKPATH" >&2
find $IMAGES -name "*.iso" -o -name '*.img' sort
while read image ; do
IMAGEPATH=$( make_system_path_relative_to_its_root "$image" )
case "$image" in
*.iso)
echo "Found iso image: $IMAGEPATH" >&2
cat << EOF
menuentry "Bootable ISO Image: $(basename $IMAGEPATH sed s/.img//)"
EOF
prepare_grub_to_access_device $ GRUB_DEVICE_BOOT sed -e "s/^/\t/"
cat << EOF
linux16 $MEMDISKPATH iso
initrd16 $IMAGEPATH
EOF
;;
*.img)
echo "Found floppy image: $IMAGEPATH" >&2
cat << EOF
menuentry "Bootable Floppy Image: $(basename $IMAGEPATH sed s/.img//)"
EOF
prepare_grub_to_access_device $ GRUB_DEVICE_BOOT sed -e "s/^/\t/"
cat << EOF
linux16 $MEMDISKPATH raw
initrd16 $IMAGEPATH
EOF
;;
esac
done
fi
P.S. I got the idea and some code snippets from several blog and wiki entries in the net and just added the iso part, so thats not all my code :)
A few weeks ago, I ve been busy at work updating the OFED packaging for OFED 1.5.2. We needed a version of the stack newer than what s (partially) available in Squeeze. As this has now been tested, we are all happy to contribute this work to Debian, courtesy of my customer, EDF.
This morning, I ve pushed out packages for OFED 1.5.2 to the pkg-ofed SVN repository on Alioth. The packages should be made available in experimental at some point too, though a number of them will have to go through NEW.
With this update, I ve cleaned up & updated the packaging where needed and also made two important changes that I need to highlight:
Somebody linked me to this reddit story about the fact that Viewsonic appear to be engaging in the currently fashionable trend of shipping Android devices without providing any source. This one's more interesting though, in that Viewsonic appear to be entirely happy to publicly state that they have no intention of following their license obligations. I've pulled the kernel image for the device and confirmed that it contains code that's not present in the generic Android Tegra tree, so I don't think they have a leg to stand on here.
Sometime you get an UTF-8 encoded text file you want to print. But
most text to postscript converters (often invoked automatically by
your print server) can only render ISO-Latin-1 text files properly and
so you get the notorious et al on your printout.
This is especially annoying at PGP/GnuPG keysigning parties where
nowadays most people have the names in their UIDs encoded in UTF-8.
Fortunately there is paps (Debian package), a Pango based commandline tool to
convert UTF-8 encoded text files into PostScript.
See the paps home
page for a neat example.
Update 02:10 (CET): Funnily the explicitly as HTML
entities à and ¤ written
above got rendered as in Liferea, but only in the Planet
Debian and Planet Symlink feeds, and only until I put that
ä in this paragraph, because both got converted to their
ISO-Latin-1 8-bit equivalent bytes, so that without the ä ,
ä , converted to 8-bit ISO-Latin-1 characters
looks also like an UTF-8 . And Liferea seems to guess the
character set somehow and if it validates as UTF-8, it
uses UTF-8 even if it isn t UTF-8. This is a strange
Planet.
I ve never quit a job before. Well, not a real job. Quitting PC World was more than easy, it was practically required for my soul not to leave my body. Quitting Waitrose was, well, it was a freaking supermarket job. And Southampton football stadium I just stopped turning up after one girl fainted in the kitchen from heat exhaustion. But a real, proper handing in of notice is something new in no small part because I ve been in the same place since my first job as a new graduate.
Not that I m ungrateful, mind. Looking after big iron at the University of Oxford has been pretty awesome more blinky lights than you can shake a stick at but there comes a time when you need to think about your career, and move on to pastures new. I m fairly sure six and a bit years is WELL past that point.
When I started looking at work, I had only a few mandatory criteria a sysadmin job, working with Free Software, without any significant decrease to my monthly income. Beyond that well, in this economy, who am I to argue?
What I hadn t accounted for, however, was a job whose awesomeness can t be contained. A job with a dedicated Free Software company whose entire staff roster, top to bottom, is filled with the most talented, smart, and generally awesome people you could hope to work with. Such a job would be a fevered dream, the mere ramblings of a madman. Yet, somehow, for the second time running, I find myself in an enviable job, working exclusively on Free Software.
Being able to show off root access to a box with 256 cores and a tibibyte of RAM is pretty cool. But you know what s even cooler? A job where I never need to worry about openSUSE 10.1 administration ever again. A job where several of my colleagues are fellow Debian Developers, with all the prestige and knowledge that comes with such a title. And somehow, by rolling proverbial twenties, I find myself in that position.
I am very, VERY proud to say that from the start of January, I ll be joining Collabora Ltd as their new Systems Manager.
Alice: hey bob, got a second?? Bob: yes! Alice: alright cool, I want you to try something real quick Bob : ok Bob : :)At this point, I had zero suspicion about who was really talking to me..
Alice: alright bob, try this test and show me what you get.. i can't get over like a 105, its pathetic http://stupid-iq-test.comYes, looking at the stupid IQ test and knowing some facts about the person asking me to do it, I became suspicious, so I tried a first question:
Bob : what do I get from that ? :) Alice: lemme know what ya get plz, so far everyone beat me, except for Clarence LOL be carfeful some of the questions are hard ;-)Not too bad of an answer! Also, Clarence is one of our common friends and knowing Clarence, he could indeed have challenged Alice. But I was still suspicious so I tried a last question:
Bob: how much did you get ? Alice disconnectedTalking in real life, it appears that it was indeed a bot... I'm quite impressed, though. I wonder now the extend of work they have put in it to make it sound real to me...
I finally took some time to finish my color contrast corrector. It's now able to compare two colors and to tell if they are readable when used as foreground and background color for text rendering. If they are too close, the code corrects both colors so to they'll become distant enough to be readable. To do that, it uses color coordinates in the CIE L*a*b* colorspace. This allows to determine the luminance difference between 2 colors very easily by comparing the L component of the coordinates. The default threshold used to determine readability based on luminance difference is 40 (on 100), which seems to give pretty good results so far. Then it uses the CIE Delta E 2000 formula to obtain the distance between colors. A distance of 6 is considered to be enough for the colors to be distinctive in our case, but that can be adjusted anyway. That depends on reader's eyes. If both the color and luminance distances are big enough, the color pair is considered readable when used upon each other. If these criteria are not satisfied, the code simply tries to correct the color by adjusting the L (luminance) component of the colors so their difference is 40. Optionally, the background color can be fixed so only the foreground color would be adjusted; this is especially handy when the color background is not provided by any external style, but it the screen one (like the Emacs frame background in my case). Here is an example result generated over 10 pairs of random colors. Left colors are randomly generated, and right colors are the corrected one. <style type="text/css"> </style>
bg: DarkSeaGreen4 fg: gray67 -> fg: #4a6b4b bg: #cccccc bg: SlateGray4 fg: forest green -> fg: #9faec0 bg: #005700 bg: grey13 fg: grey36 -> fg: #131313 bg: #6c6c6c bg: MediumPurple2 fg: honeydew -> fg: #9e78ed bg: #f0fff0 bg: grey43 fg: chartreuse3 -> fg: #5e5e5e bg: #79de25 bg: linen fg: DeepPink2 -> fg: linen bg: DeepPink2 bg: CadetBlue4 fg: blue1 -> fg: #6c9fa4 bg: #0000e1 bg: gray33 fg: NavajoWhite3 -> fg: #525252 bg: #cfb58c bg: chartreuse1 fg: RosyBrown3 -> fg: #9cff38 bg: #b28282 bg: medium violet red fg: DeepPink1 -> fg: #9c0060 bg: #ff55b9All this has been written in Emacs Lisp. The code is now available in Gnus (and therefore in Emacs 24) in the packages color-lab and shr-color. A future work would be to add support for colour blindness. As a side note, several people pointed me at the WCAG formulas to determine luminance and contrast ratio. These are probably good criteria to choose your color when designing a user interface. However, they are not enough to determine if displayed color will be readable. This means you can use them if you are a designer, but IMHO they are pretty weak for detecting and correcting colors you did not choose.
libxul.so. The very patterns there s not much to do about, except enduring them, or hacking ld.so and/or the toolchain. The latter is not necessarily easy, and won t benefit everyone until all linux distros use an improved glibc and/or toolchain. This could take years before any actual result would reach end users.
But with a little creativity, one can overcome these limitations and improve the situation today. Here is a summary of my recent hacks.
Backwards static initializers
As Taras showed in the past, static initializers are executed in reverse order. It turns out it is an unfortunate design choice in gcc, and it also turns out not to impact all ELF binary files.
As far as I know there are currently two different implementations of the static initializers call loop, one provided by gcc, and one provided by ld.so.
In the gcc case, the compiler creates a .ctors section, starting with 0xffffffff, ending with 0x00000000, and filled with pointers to the various static initializer functions, in ascending order. The compiler also injects an initializer function, called from .init, going through this .ctors section, starting from the end (__do_global_ctors_aux in crtend.o). A similar .dtors section is created for functions to run when the library is unloaded, and the pointers in it are called in ascending order. There is actually no importance in the order in which .ctors and .dtors are executed. All that matters is that they are executed in reverse order from each other, because that limits the risks of bad ordering. It is only unfortunate that .ctors was chosen to be the one backwards.
In the ld.so case, the compiler creates a .init_array section, filled with pointers to the various static initializer functions, in ascending order. It also stores the location and the size of this section in the PT_DYNAMIC ELF header. At runtime, ld.so itself reads this information and executes the static initializers in ascending orders. A similar .fini_array section is created for functions to run when the library in unloaded, and ld.so goes through it in descending order.
The .init_array section is newer, and for backwards compatibility reasons, is not used on systems that have been using the .ctors approach forever. On the other hand, some newer ABIs, such as arm EABI, uses the new facility, which means they are not victim of backwards static initialization. I however wonder if backwards compatibility is still needed, considering how long .init_array support has been around (more than 11 years, according to glibc git repository).
While we could obviously bug the gcc maintainers to revert their .ctors execution order, or ditch .ctors support on glibc systems, which means we wouldn t get any immediate global benefit, we can also just revert the .ctors section content. Please note the source code out there doesn t take care of reverting the .dtors section accordingly, because it is currently empty in libxul.so.
Relocations
As I mentioned in an earlier post, relocations are what make it possible to load libraries at arbitrary locations. Unfortunately, a great number of relocations means awful I/O patterns: ld.so reads and applies them one by one, and while the kernel reads ahead by 128 KB chunks, when your relocation section exceeds that amount by more than an order of magnitude, it means I/O goes back and forth a lot between the relocation section and where the relocations take place.
There are two classes of relocations: REL and RELA. In both cases, there are several types of relocations, some of which require an addend. The difference between both classes is in REL relocations, the addend is stored at the offset the relocation takes place, and in RELA relocations, the addend is stored in the relocation entry. It means that RELA relocations effectively waste space, as the addend ends up actually being stored twice: it is also stored at the offset the relocation takes place, like with REL relocations, though it could technically be nulled out, there ; in any case, the space is wasted.
REL relocations thus take 2 words of storage, and RELA relocations, 3. On x86, the ELF ABI only uses REL relocations, and words are 32 bits, making each relocation take 8 bytes ; on x86-64, the ELF ABI only uses RELA relocations, and words are 64 bits, thus making each relocation take 24 bytes, 3 times that of x86 relocations. On ARM, both may be used, but apparently the compiler and the linker only use REL relocations.
These words of storage are used to store 3 or 4 bits of informations:
r_offset: the offset at which the relocation takes placer_info: containing both the relocation type and a symbol reference for the relocation. On 32 bits systems, the symbol reference is stored on 24 bits, and the relocation type on 8 bits. On 64 bits systems, the symbol reference is stored on 32 bits, and the relocation type on 32 bits (which means at least 24 bits are never going to be used: there are currently no ABI using more than 256 relocation types).r_addend: The addend, only in RELA relocationslibxul.so (taken from the mozilla-central nightly from Nov, the 22nd):
| dynamic relocations | PLT relocations | |||
|---|---|---|---|---|
| Architecture | number | size (bytes) | number | size (bytes) |
| x86 | 231,836 | 1,854,688 | 3,772 | 30,176 |
| x86-64 | 235,893 | 5,661,432 | 3,773 | 90,528 |
| Architecture | libxul.so size |
relocations size | % |
|---|---|---|---|
| x86 | 21,869,684 | 1,884,864 | 8.61% |
| x86-64 | 29,629,040 | 5,751,984 | 19.41% |
libxul.so:
| x86 relocation type | number | x86-64 relocation type | number |
|---|---|---|---|
| dynamic relocations | |||
R_386_TLS_DTPMOD32 |
1 | R_X86_64_DTPMOD64 |
1 |
R_386_GLOB_DAT |
213 | R_X86_64_GLOB_DAT |
238 |
R_386_32 |
27,643 | R_X86_64_64 |
27,611 |
R_386_RELATIVE |
203,979 | R_X86_64_RELATIVE |
208,043 |
| PLT relocations | |||
R_386_JUMP_SLOT |
3,772 | R_X86_64_JUMP_SLOT |
3,773 |
R_*_GLOB_DAT, R_*_JUMP_SLOT, R_386_32, R_X86_64_64)R_*_RELATIVE, R_386_TLS_DTPMOD32, R_X86_64_TLS_DTPMOD64)libxul.so are from that category. At this point, this is how much waste we identified:
| description | num. entries | waste per entry (bytes) | total | % of relocation size |
|---|---|---|---|---|
| x86 | ||||
| Relocation without symbol ref. | 203,980 | 3 | 611,937 | 32.46% |
| x86-64 | ||||
| Duplicated addend | 239,666 | 8 | 1,917,328 | 33.33% |
| Relocation type encoded on 32 bits | 239,666 | 3 | 718,998 | 12.49% |
| Relocation without symbol ref. | 208,044 | 4 | 832,176 | 14.46% |
| Total | 3,468,502 | 60.30% | ||
r_offset on 64 bits systems, as libxul.so is far from being bigger than 4GB. Anyways, that means we have room for improvement here, and it means that the ELF format, especially on 64 bits systems with RELA relocations, really doesn t help with big programs or libraries with a lot of relocations. (For that matter, the mach-o format used on OS-X has some kind of similar issues ; I don t know for the DLL format)
Another interesting data point is looking at how relocations r_offset are following each other, once relocations are reordered (to avoid too much symbol resolution, they are actually grouped by symbol). It turns out 206,739 relocations r_offset are at 4 bytes from the previous one on x86 (i.e. strictly following it), and 210,364 at 8 bytes from the previous on x86-64. The main reason why this happens is that most relocations are happening in pointer tables, and libxul.so has lots of them:
.ctors and .dtors sections, which are relocated as well (but not .init_array and .fini_array sections).libxul.so has lots of them, that s not an understatement: there are 184,320 relocations due to vtables (function tables you get when using virtual methods in C++) on x86 and 184,098 on x86-64. That s respectively 78.23% and 76.81% of the total number of relocations. Interestingly, while most of these relocations are R_*_RELATIVE, 26,853 are R_386_32, and 26,829 are R_X86_64_64. Except for a very few, these non relative relocations are for the __cxa_pure_virtual symbol, which is a dummy function that does nothing, used for pure virtual methods, such as the following:
class Abstract
public:
virtual void pure_virtual() = 0;
;
As for the remaining relative relocations, there are a few pointer tables responsible for several thousand relocations, such as JSString::length2StringTable, gEntries, GkAtoms_info, Html5Atoms_info, kUnixCharsets, nsIDOMCSS2Properties_properties, etc.
Packing relocations
While they are not detrimental to most binaries, we saw that relocations can have a bad effect on startup I/O for big binaries. Reducing how much space they take would have a direct impact on these startup I/Os. One way to do so is obviously to reduce the number of relocations. But as we saw above, the vast majority are due to vtables. While reducing vtables would be a nice goal, it s a long way before this can have a significant impact on the relocations number. So another possible way is to try to avoid wasting so much space in relocations.
The main problem is that relocations are applied by ld.so, and that, as mentioned in the introduction, while we can hack ld.so to do what we want, it won t work everywhere before a long time. Moreover, it s difficult to test various implementations, and binary compatibility needs to be guaranteed once something is applied in the upstream libc.
The idea I started to test a few weeks ago, is to effectively apply relocations by hand instead of relying on ld.so doing it. Considering the first thing ld.so does with a library after applying relocations is to call its DT_INIT function, the idea was to replace the dynamic relocations we can with a new DT_INIT function we would inject that d apply those relocations, while storing them in a more efficient manner. The function would obviously need to call the original DT_INIT function once done. Some parts of the PT_DYNAMIC section also obviously need to be adjusted accordingly.
The first iteration I tested a few weeks ago helped validating the idea, but didn t change much of the binary: the dynamic relocation section still was taking all the space it took before, though its content was mostly empty (we ll see further below how efficient even the current dumb format is). Once the theory that an injected DT_INIT function could apply the relocations without breaking everything, I went on to implement a program that would actually strip the ELF binary. I won t get too much into the gory details, but it required PT_LOAD splitting, thus program headers growth, which means moving the following sections, then removing a huge part of the relocations, shrinking the relocations section, injecting our code and the packed relocations as sections, and moving the remaining sections after these new sections, to avoid empty space, but still respecting the proper offsets for both PT_LOAD and the code itself.
So far, I only took care of the R_*_RELATIVE relocations. Some but not all other relocations could be taken care of, too, but everything involving symbol resolution from other libraries would be really difficult to handle from the injected code. The relocations are currently stored with a quite dumb format:
r_offsetr_offset, we just strip it from RELA relocations ; the binary being far from 4GB big, 32 bits is enough on 64 bits systems too. We also saw that a lot of relocations were next to the following ones, so instead of storing r_offset for each one, storing some kind of range is more efficient. As I ve so far been focusing on getting something that actually works more than on getting something really efficient, I only tested this format, but the results are already nice:
| x86 | x86-64 | |
|---|---|---|
| before | ||
| dynamic relocations (bytes) | 1,854,688 | 5,661,432 |
libxul.so size |
21,869,684 | 29,629,040 |
| after | ||
| dynamic relocations (bytes) | 222,856 | 668,400 |
| injected code size | 129 | 84 |
| packed relative relocations (bytes) | 224,816 | 228,568 |
libxul.so size |
20,464,836 (-6.42%) | 24,865,520 (-16.07%) |
__cxa_pure_virtual relocations would help getting this even further down, and an even better storage format could be used, too. Gathering new startup coverage data should be interesting as well.
The code is available via mercurial. Please note the Makefile deeply sucks, and that the code is in the middle of its third refactoring. Anyways, once you get the code to compile, you just need to run test-x86 or test-x64 depending on your architecture, from the build directory, and give it the libxul.so file as an argument. It will create a libxul.so.new file that you can use to replace libxul.so. You may successfully use the tool on other libraries, but chances are you ll bump into an assert(), or in the worst case, that the resulting library ends up broken. The tool might work on PIE executables, but most probably not on other executables. If you wonder, Chrome is not PIE. It s not even relocatable (which means ASLR won t work with it) ; or at least the x86-64 binaries I just got aren t.
More possible ELF hacking
The code I wrote to pack relocations allows to do various tricks on ELF files, and it opens various opportunities, such as:
.bss. As I wrote on this blog a while ago, ld.so fills the last page from the .data section with zeroes, starting at the offset of the .bss section. Unfortunately, this means reading ahead at most 128KB of data nobody needs, and the corresponding disk seek. Inserting a section full of zeroes between .data and .bss would get rid of that, while minimally wasting space (less than 4KB in a 20MB+ binary).PT_DYNAMIC section. It is one of the first bunch of data to be read from programs and libraries, yet it is near the end of the binary..ctors/.dtors with .init_array/.fini_array (thus removing the corresponding relocations, though there s only around 300 of them).__cxa_pure_virtual relocations with relative relocations pointing to an injected dummy function (it could even just point to any ret code in any existing function).-Bsymbolic)ld --verbose). And it s not guaranteed to work (Taras told me he had a hard time failing to align the .bss section). And as far as I know, you can t use the same thing depending whether you use ld or gold (AIUI, gold doesn t support the whole ld linker script syntax).
Amen to that! Enough with the coincidence vortex. As I said to Biella in IRC later: Do us a favor don t watch any shows about nuclear attacks on New York, okay
Next.