Make your own executable shared library on Linux

Hello there, it’s been a long time since my last post 🙂

Since I’m on vacation, and kinda frustrated about my playbook experience, I decided to  statisfy something that always tickled my fancy about shared libraries.

As you may know, under GNU/Linux is it possible to make shared libraries also executable: prominent examples are libc and Qt libraries, as shown in the screenshot below.

libc and libQtCore output

libc and libQtCore output

Those libraries, when executed from the command line, print useful information about the library version itself, the compiler used, processor features, author, copyright and so on .

But how they achieved that? Libraries don’t have an entry point .. or they do?

LD manual to the rescue

Of course the answer is yes, they do .. sort of. If you look at the options you can issue to ld, you will notice that there is the following option:

-e entry

--entry=entry  Use entry as the explicit symbol for beginning execution of your program, rather than the default entry point. […]

Bingo!

So what you will actually do is to define a function, from whithin your library, that will be used as entry point when executed. From there, you can execute your arbitrary piece of code.

The Code

We will start by defining a sample library composed of just one class (I kept everything as simple as possible to improve readabilty), which will do nothing but print “hello lib!”  upon construction:

/* lib/mysamplelib.h */
#ifndef SAMPLELIB_H
#define SAMPLELIB_H
namespace MySampleLib
{

class SampleLib
{

public:
    SampleLib();
};

} // namespace MySampleLib

#endif // SAMPLELIB_H

/* lib/mysamplelib.cpp */
#include "samplelib.h"
#include

namespace MySampleLib
{

SampleLib::SampleLib()
{
    std::cout << "hello lib!" << std::endl;
}

} // namespace MySampleLib

Then, we will define our custom entry point function in a separate file: this will print “Hello from custom entry point lib!”.

/* lib/dump_function.cpp */

#include
#include

extern "C" void my_dump_function() {
    printf("Hello from custom entry point lib!\n");
    exit(0);
}

We also need a very basic main.cpp file, which prints the usual “Hello World!” and then instantiate a SampleLib object:

/* main.cpp */

#include
#include "lib/samplelib.h"

int main()
{
    std::cout << "Hello World!" << std::endl;
    SampleLib lib = SampleLib();
    return 0;
}

For completeness, I will also include the two CMakeLists.txt files used in the project.

/* CMakeLists.txt */
project(executable_library)
cmake_minimum_required(VERSION 2.8)

add_subdirectory(lib)

set(SRC_LIST
    main.cpp
)

add_executable(${PROJECT_NAME} ${SRC_LIST})
target_link_libraries(${PROJECT_NAME} sampleLib)

/* lib/CMakeLists.txt */
set(LIB_SRC
    samplelib.cpp
    dump_function.cpp
)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -e my_dump_function")

add_library(SampleLib SHARED ${LIB_SRC})

And now we can finally build and run our app and our library and see the results 🙂

First Attempt

First Attempt

Urg .. What’s going on here?

Compilation and linkage were successful, the executable ran perfectly, but executing the library directly produced a segfault.

The Fix

Let’s try to find out what’s wrong here. We will run readelf to see the if there are some parts in common between the executable, our library, and some other executable library – i.e. libc – . These are the output:

readelf exec

readelf exec

readelf libc

readelf libc

And now, our libSampleLib

readelf samplelib

readelf samplelib

Nice, now we have much more infos about the issue. As you can see the executable, libc, and our SampleLib, all have  an entry point defined. That means that ld processed our command option as we intended.

But, as opposed to the executable and libc, our SampleLib does not have an interpreter section defined. This is normally good when a library gets executed through a regular application, because every application has an interpreter defined. In our case anyway, that missing definition is the reason of our segfault.

So we need to tell the compiler to add an interpreter header. From a quick search on google, all you need is to add the following line inside dump_funcion.c (outside the function body of course)

extern const char elf_interpreter[] __attribute__((section(".interp"))) = "/lib64/ld-linux-x86-64.so.2";

Recompile all, and now …

Second Attempt

Second Attempt

Awesome, we did it!

But we are serious programmer, aren’t we? Hardcoding the interpreter absolute path is always a Bad Thing™; if you work in a team where everyone may potentially have different setup and machines, that’s even worse.

CMake to the rescue!

With a little help of CMake, we can automate the interpeter path retrival.

Firs we execute readelf on a command that is present in every linux distro, which is “ls” ; then, with a little cmake regexp magic, we extract the path, and finally add a new cmake definition whose value will be assigned to the elf_interpreter[] var inside dump_function.cpp .

The updated CMake file and main.cpp look now like this:

/* lib/CMakeLists.txt */
set(INTERPRETER_DESCRIPTION "Requesting program interpreter:")

execute_process(COMMAND readelf -l /bin/ls
    RESULT_VARIABLE return_value
    OUTPUT_VARIABLE result
)

if(return_value)
    message(STATUS "Cannot find a valid ELF interpreter")
else()
    string(REGEX REPLACE
        ".*[[]${INTERPRETER_DESCRIPTION} ([/][^ ].+)[]].*" "\\1"
        _ELF_INTERPRETER_PATH "${result}"
    )

    add_definitions( -DELF_INTERPRETER_PATH="${_ELF_INTERPRETER_PATH}" )
    message(STATUS "ELF interpreter is ${_ELF_INTERPRETER_PATH}")
endif()
set(LIB_SRC
   samplelib.cpp
   dump_function.cpp
)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -e my_dump_function")
add_library(SampleLib SHARED ${LIB_SRC})

/* lib/dump_function.cpp */
/* showing only the relevant line here, too lazy to copy everythin again! */
extern const char elf_interpreter[] __attribute__((section(".interp"))) = ELF_INTERPRETER_PATH;

That’s better 🙂

Further improvements and how to get the code

You can find an improved version of the code shown here on my gitorious repository . I made some modifications to make it prettier and more reusable, such as define a FindELFInterpreter script for that purpose, added a simple macro to retrieve the hash commit/current branch of your source tree (in this case, mine), and embed that info within my_dump_function(). I’ve also added some debug compiler options, and added to the dump function, just to show some other interesting output you may be interested in seeing. Pretty neat, isn’t it? 🙂

Last Attempt

Last Attempt

An other interesting thing to implement could be use cmake feature to create header files through its configure_file() command, and put all of those definitions inside it and include that file whenever you need it, but I leave this as an exercise to the reader, cheers 😉

Advertisements

My New Laptop Review

Ok, it’s been over three weeks since when I got my windows-free laptop. During this time, I’ve ran KUbuntu 10.10 with KDE 4.5.?  for about a week, then I moved to KDE trunk as usual and now it’s time to share my two cents (and personal random thoughts and rants) about this laptop 🙂

Technical Specs

The full reference is listed over here; below, I’m listing only the changes I’ve made from the configuration showed in the website.

  • Cpu: Intel Core i3 330M (2 cores@2.16GHz with 4 threads running concurrently);
  • Hard Disk: removed the default 320GB hd and replaced with a 128GB Kingston SSD;
  • Ram: upgraded to 4GB ddr3.

One really cool thing about this laptop is the possibility to mount up to two (sata) hard drives and, since my old laptop has a sata drive too, data recovery was amazingly easy: I simply had to remove my old hd and install it in my new laptop, and then move the content of my home directory to the new location, that’s all!

Design

Design is the first thing you notice when you unpack you laptop, be it its finishes or its input/output ports placement. Design (and design choiches) affects the way you are going to use your notebook, and it is responsible of the sensations you feel when you see it for the first time1.  Since I really care about design, let’s start with showing some pics I took to both my new and old laptop, and sharing my nit-picking opinions (I’m sorry for the quality of these pictures, I made it with my cellphone):

New laptop
My new laptop
Old laptop
My old laptop

The overall look of the new one is quite good: the 17.3″ screen is absolutely amazing, and the satin-finished chassis gives a professional appearance to the whole.  I said “quite good” because, on the other hand, this laptop gives me a sensation of brittleness due to its tiny screen pivots (in the old one, they are firmer and bigger).

One thing I really  miss in this laptop is the presence of the multimedia keys (play/pause/stop/next/previous); every time I need to change track within amarok, I need to switch the application I’m currently working on, or set a weird shortcut to do the dirty work for me 😦

Other minor annoyance  are the ports placement. Let’s start, for example, with the audio jack port. In the following picture I’ll show where they are situated, and the nuisances arose with a wrong2 positioning.

Audio jack placement, new laptop

Audio jack placement, new laptop

Audio jack placement, old laptop

Audio jack placement, old laptop

Audio jack, new laptop

Audio jack, new laptop

Audio jack, old laptop

Audio jack, old laptop

As you can see, the audio jacks has been moved from the bottom-right border (old laptop), to the top-right border (new laptop); since I’m used to wear headphones for about 90% of my time (so does my brother too, in order to listen our favourite songs, watch our favourite movies etc.. without bothering each other), this means a headphone cable always annoying my right hand3. The annoyance is even greater when you play a game (did I mentionend quakelive? :P), and you notice that your movements are not as fluid as before. An other detail I miss a lot is the wheel volume controller. You can clearly see it in the Audio jack placement, old laptop picture: it’s the first element from the left. This could sound silly, but how many times happened that someone has turned on his/her laptop in the College library, and the infamous login sound spreaded loudly all over the rooms? With a simple wheel scroll-down, the quiet of the library would be preserved 🙂

The power supply jack is an other example of not so wise™ placement.

Power jack, new laptop

Power jack, new laptop

Power jack, old laptop

Power jack, old laptop

In fact, it is now placed between other I/O devices (ethernet, usb, e-sata and ieee1394), rather than being situated near an edge of the chassis, far from other ports. So, in the worst case (which also happens to be mine), the power supply cable lies along the whole length of the back panel, occluding the other ports and forcing me to manually move it away every time I need to plug-in my external hard drive, or ethernet cable.

Ok, now stop being fussy, and let’s talk more interesting stuff 😉

Hardware compatibility

This is a major point for every Linux user, so I’m going to describe the issues I’ve encountered while running a KDE SC 4.5 from a live-cd distrubution, from an apt-gegt updated version of it, and finally from trunk (KDE SC 4.5.86).

  • KUbuntu 10.10 (with KDE 4.5.?) live-cd: wireless adapter, webcam, bluetooth, memory card reader, screen brightness fully working, suspend/hibernate too. Unfortunately, the audio was completely absent: I’ve tried to tweak alsa and phonon, with no results. Desktop running at the maximum resolution, but with desktop effects disabled.
  • KUbuntu 10.10 installed on hard drive: upgraded to 10.10.1, with KDE 4.5.3: again, wireless adapter, webcam, bluetooth, memory card reader, screen brightness, suspend/hibernate fully working. After tweaking alsa-base conf, I got the sound working from the audio jack, but still no sound from the speakers. I experienced a lot of X crashes with the Ati proprietary video drivers, but switching to the experimental ubuntu repo (ppa.launchpad.net/ubuntu-x-swat/x-updates/ubuntu/) did the trick 🙂
  • KUbuntu4 10.10.1 with KDE 4.5.86:  wireless adapter, webcam, memory card reader, suspend/hibernate fully working. Bluetooth keep crashing kded, so it’s disabled for now (I barely use it, however). Screen brightness is not working anymore, so here it is an other interesting thing to investigate during this holidays :P. Audio still refuses to work from the speakers, this is kinda disappointing but I’m also confident that in the next few upgrades it will be fixed. Plasma desktop works like a charm, with all effects enabled and very little footprint, compared with two months ago. Good job, guys 😉

Performance

Ooh, I really enjoyed writing this chapter!

After installing KUbuntu for the first time, I wasn’t that curious to see how much time the SSD took to boot the operating system up. The reason is simple: as every one of you most likely did, I read a lot of reviews about SSD performaces and the opinions were (almost) always the same: the more performant are the Intel ones, next the Corsair, and then the Ocz and Kingston drives. I was absolutely amazed when i discovered that my fresh Kubuntu install took only ~9 seconds to boot, against my usual 30 seconds and more!

Now, with after a month of use, upgrades, and a full switch to KDE from trunk, the boot time is still impressive, around 11 seconds5. Check the video below, if you don’t trust me 😛

[blip.tv ?posts_id=4560072&dest=-1]

As you should have guessed from a small detail on that video, I was so curious to test the boot speed on other operating system that I grabbed a copy of Windows7 license kindly offered6 by my University, created a partition,  installed Win7, and performed some tests. And guess what? It took 23 seconds to show the login screen, really slow compared with Linux boot. But the interesting part of the test isn’t come yet. I’ve measured the boot time of my brother’s laptop (a cheap model, 6 months old), powered by an usual sata drive@5400 rpm,  surprisingly scoring only 31 seconds! Just 7 seconds of improvement between a fresh Win7 install on a SSD, and a 6 months old installation on a 5400rpm sata drive… sounds like Windows’ Failboat delivered a huge present to its customers, again.

However, boot performance aside, let’s come back to our Linux/KDE world. Benefits of an solid state disk are more than just boot speed. The whole desktop experience is more fluid, fast and resposive (of course credits must be given to the Cpu and Ram too, see below). One example for all, OpenOffice: every time I opened an office file with it, it took ages to load and open it. Now, the app is amazingly quick.

The same for Dolphin: I have the bad habit to put everything in my home folder to save time and, when launching dolphin in the past, it took over 6-7 seconds to show up: now that time is significantly decreased.

Last, but not least, is the quietness of the whole computer: when it’s not performing heavy tasks, the loudest noise you can hear is the cpu fan.

Ok, I’ve talked a lot about solid state disk performance. Now, it’s time to spend some words about the cpu. As I’ve already said, it is responsible of the snappiness and fluidity of the whole desktop. But, from a developer perspective, what really matters is “How much time does it take to compile the package X.Y?” 😛

With my old laptop (running a Core Duo T7200@2.0GHz), I measured the compile time of the QT framework (Qt 4.7.0 RC1, on early September), with the following configure switches

$./configure -qt-gif -debug -fast -system-libpng -system-libjpeg -system-zlib -dbus -webkit -no-phonon -plugin-sql-mysql -developer-build -declarative -opensource -script -scripttools -nomake examples -nomake demos -prefix /opt/qt4

and a MAKEFLAGS environment var set to -j3. With this setup, it took 94 minutes to compile everything.

With the same setup, and MAKEFLAGS  set to -j6, the new laptop scored an incredible result of only 40 minutes! But the detail that impressed me even more, is the overall responsiveness of the desktop: I could chat, watch videos on youtube, and desktop effects were running seamlessly, with small lags between the action that triggers the effect, and its actual accomplishment! With my old laptop, all of this was a mere dream (if someone owns my same old cpu, and ever tried to do what I did, knows exactly what I’m saying).

Kudos to the Intel Engineers for this awesome product, and of course to the Linux kernel developers too, who were able to exploit cpu resources at their best!

And now, the graphics card and the ram. The best way to push  graphic card and ram to their limits is to  –play the latest game?– , of course no! It’s performing real-time computation on graphical data, which means 3D modeling a high-poly object. Unfortunately, I don’t have Maya for Linux here, so I downloaded and installed ZBrush (take a look at it, it’s a very impressive piece of software) and started modeling a sort of alien face using HD geometry. For a graphic card designed to be installed on a laptop, I must admit I was surprised of the level of details I’ve been able to reach.

Wait, the review it’s not finished yet! There is still the audio performance to talk about. Even if the audio is half working on linux, and I hope to get it fixed soon, having an other OS gave me the opportunity to test how all the components works. And, hell, the speakers plus the subwoofer are really kick ass! They play sounds clear and loud, very very loud!

Conclusion

In consideration of all the points I’ve discussed in this post, I give to this laptop 8 out of 10 as final score. The performances are good, but the hardware compatibility with Linux is not as good as I would expect from a high-end laptop. If I was a person with no experience on tweaking linux, I’d probably switched to Windows after the second try on the audio configuration process. Design is fine, but could be better for, again, for a high-end laptop.

I hope I don’t have annoyed you with my loooong and enthusiastic review about my laptop, Merry Christmas and Happy New 2011 =)
A special thanks to my friend Alberto, who spent his time to help me with the ATI driver setup (and his trolling mood too :P), and to my beloved girlfriend Mariaelena, who bears the weight of my nerd vein!

_______________________________________________________________

1: Sounds kinda romantic, isn’t it? 😛
2: In my opinion, of course.
3: This might sound silly but, hey, try working on a computer with your right hand 10 centimeters farther than you were used to, and then we will talk about it.
4: Well, let’s say the basics packages of K/Ubuntu 10.10.1 because, if you read some of my older blog posts, I completely build KDE and QT from sources, so I don’t need the ones supplied by Ubuntu (I apt-get remove all of them after every new system install).
5: Now, I’m REALLY curious to see how long does the boot sequence take on an Intel Extreme SSD …
6: Whooops, i forgot the <sarcams></sarcams> tag here.

Ordered my new laptop, Windows free =D

[Edit:] Got the laptop, time to build KDE 😀

This is not a kde-related post, so you can skip it if you like. However, since I managed to achieve this awesome result, I thought it’s worth sharing it with the community 🙂

As you should’ve noticed,  I’m not on irc anymore because my old laptop broke1 (after more than 4 years of honourable service), and it was my only computer at home. So, during this period, I looked for vendors that sell  linux-based laptops.  The criteria were the following:

  • Linux powered, or no operating system at all (of course ;));
  • 17″ screen size: since this laptop will be my only computer, I’m going to use it for coding, university stuff, multimedia and I don’t want to stress too much my eyes with smaller screen size  (I’m already myopic asd);
  • Intel i3 or i5 processor;
  • a good video card;
  • a reasonable amount of ram and hard drive space 😛

Turned out that most of the vendors that respect my first criteria are located in US, and they can ship their products only in US and Canada (some of them to Europe, but with restrictions) . The only exeption was zareason which ships worldwide but first,  — what if the laptop will broke? I can’t wait months for being fixed — and second, they don’t provide a 17″ model at the moment (unlike System76 does, for example). Of course I found a couple of vendors in italy, but they are quite unknown compared with the aforementioned ones, with little possibility of customization too.

So, before my surrender, I decided to give a last try with my previous laptop vendor (www.enface.it). I was really happy with it: a very good machine2, with an amazing audio and, a bright display and a good processor. Four years ago I was more naive than now, and when the retailer told me — “No, we aren’t allowed to sell you our laptops without XP” — I didn’t insisted; instead, I agreed.

But not this time.

After configuring the laptop according to my budget and wishes, here it is the most important part of our conversation:

Advisor:  “Now, by default this laptop comes out with windows7 Home Premium, but I think an upgrade to Professional would be a wise choice.”

Me: “Actually, I don’t want any Windows operating system at all.”

A: “What?”

M: “You heard me: I don’t want Windows in my laptop.”

A: “Well, this is not feasible because the vendor and Microsoft made an agreement, and we can’t overcome that.”

M: “I’m not pretty sure about that. I downloaded, printed and readed the full Windows7 EULA and, at page 1, it says — “By using the software, you accept these terms. If you do not accept them, do not use the software. Instead, return it to the retailer for a refund or credit” –. I’m saying I don’t want to use that software, ergo you don’t even have to waste your time with installing it; simply skip that step, subtract its cost and that’s all.

A: “I’m sorry, but we can’t. Furthermore, for a smoother and immersive desktop experience, we strongly recommend you Windows7.”

M: “I’m sorry for wasting your time then, because I have no intention on buying a laptop with Windows. I’ll try somewhere else. Sorry.”

A: “Hmm wait, let me make a call to the tech-support, ok?”

M: “Ok.”

[~30 seconds phone call]

A: “Ok, seems like it’s possbile to ship our laptops without OS. However, because of the agreement we and Microsoft made, the cost of the license is far different from the one you can find in a store. We can refund you 78€3 though.”

M: “That sounds great! Where should I sign?”

So yeah, an other little battle won against Micro$oft dictature 😀

If some you guys are in the same situation I was, just remember these two things:

  1. never give up, be perseverant!
  2. you are not asking anything illegal, neither you are stealing a percentage of the retailer’s income: it’s your right to refuse Microsoft EULA and, if the retalier doesn’t allow you doing so, he is acting illegally, not you!

I will receive my laptop in about a week, so expect an other blog post with more details soon 😛

Cheers !!
____________________________________________________
1: Because of an unfortunate event beyond my control, daaaamn ='(
2: if you are curious, check the tech details here (italian only)
3: About 104$, not so bad at all!

I’ve spotted Tux :D

Yesterday I was having a look around Abano Terme with my girlfriend, when I saw somethign really really really really strange on the right side of the road; I was so surprised that I picked my N73 cell phone, I gave it to my girfriend who took this photo:

Yeah, the picture quality sucks, by the way let’s zoom in, and see the lower left quarter of the image.

Yay, a wild Tux appeared 😀

Even though the photo is blurred, you can read the following text “TUX Birreria-Pizzeria”, which means “TUX Brewery-Pizzeria”, how awesome !!!

What about scheduling the next Tokamak in its neighbourhood? 😉