{"id":448,"date":"2009-12-05T13:00:18","date_gmt":"2009-12-05T12:00:18","guid":{"rendered":"http:\/\/blog.benny-baumann.de\/?p=448"},"modified":"2009-12-05T13:00:18","modified_gmt":"2009-12-05T12:00:18","slug":"besonderheiten-beim-linken-mit-gcc","status":"publish","type":"post","link":"https:\/\/blog.benny-baumann.de\/?p=448","title":{"rendered":"Besonderheiten beim Linken mit GCC"},"content":{"rendered":"<p>Manchmal sind Programme wie der GCC selbst f\u00fcr gestandene Entwickler ein R\u00e4tsel. Nehmen wir ein beliebiges, einfaches, ggf. etwas gr\u00f6\u00dferes Projekt, dessen C-Source zu compilieren ist. Nimmt man jetzt noch an, dass dieses Projekt mehrere Module beinhalten kann, so bieten sich ja eigentlich Libraries an. Handelt es sich dabei um ein Projekt, bei dem dynamisches Linken nicht m\u00f6glich ist, so sind sogar .a-Dateien (Object File Archives) eine gangbare Alternative &#8211; k\u00f6nnte man denken. Aber gut. Selbst als gestandener Entwickler wird man immer wieder von seinen Tools \u00fcberrascht.<!--more--><\/p>\n<p>So ging es zumindest mir die letzten Tage, w\u00e4hrend ich an einem etwas gr\u00f6\u00dferen Projekt gearbeitet habe, bei dem ich zur Modularisierung meine Sources in einzelne Verzeichnisse gepackt und dann jedes Verzeichnis in eine .a-Datei verpackt habe. Das ist auch weiter nix, was unter klassische Rocket Science geh\u00f6rt, aber immerhin ein etwas exzentrischer Ansatz, Libraries zu nutzen ohne wirklich Libraries zu verwenden. Das ist aber auch weniger mein Punkt.<\/p>\n<p>Da ich f\u00fcr die einzelnen Module eine gewisse Austauschbarkeit haben wollte und zudem Namespaces nutzen wollte, fiel mein Blick auf den Linker, mit dessen Hilfe Symbolnamen dynamisch beim Linken umgebogen werden sollten. Und dieser Satz ist bewusst im Konjunktiv verfasst, da genau hier Murphy wieder einmal einen Auftritt hatte: M\u00f6chte man mit dem GCC, bzw. dem Linker die in einer Objektfile referenzierten Symbole (also Variablen und Funktionsnamen), die z.B. nach dem Schema LibName_Task_ImplVer_Function aufgebaut sind an externe Objektfiles binden, die von der spezifischen Implementierung unabh\u00e4ngige Namen nutzen (also LibName_Task_Function), so w\u00e4re der \u00fcbliche Weg eigentlich die Verwendung von ld &#8211;def-symbol generischerName=spezifischerName &#8230;<\/p>\n<p>Wie gesagt lie\u00dfen sich also alle C-Sources reibungslos \u00fcbersetzen, was an sich schon einmal ein recht gro\u00dfer Erfolg war, woran es dann scheiterte, war mir mehr oder wenigerfraglich: W\u00e4hrend des Linkens versuchte LD zwar Abh\u00e4ngigkeiten zu finden, ignorierte aber beim Einbinden von neuen Archivdateien gro\u00dfz\u00fcgig die Abh\u00e4ngigkeiten, die durch Symbole, die via Kommandozeile referenziert wurde. Zum Umschreiben von Funktionsnamen und somit der Nutzung von Namespaces taugt LD demnach nicht.<\/p>\n<p>W\u00e4re zumindest das Problem bzgl. dem Linken der Programmbestandteile gekl\u00e4rt. Folge war zwar, dass ich eine Reihe von Sources in bezug auf die verwendeten Bezeichner etwas refactoren musste, was sich aber in Grenzen hielt und recht z\u00fcgig erledigt war.<\/p>\n<p>Nun fand LD zwar alle Symbole, konnte aber dennoch seine eigene Libraries nicht finden. Um den Weg hier abzuk\u00fcrzen, gen\u00fcgte es, statt LD direkt aufzurufen, die Kommandozeile vom GCC zusammenstellen zu lassen, was nur wenige Modifikationen erforderte. Was zumindest bei mir nun (GCC 3.4.2) zu einem weiteren Problem f\u00fchrte: M\u00f6chte man ein Programm mit einer Befehlszeile wie<\/p>\n<pre lang=\"bash\">gcc -o executable.bin archive1.a archive2.a archive3.a archive4.a<\/pre>\n<p>linken, ignoriert der GCC jegliche Archive, solange er nicht zumindest einmal eine O-Datei gesehen hat, in der das main-Symbol aufgetaucht ist. Dass man bei dieser Art einige Archive doppelt angeben muss, mag ja vielleicht noch einzusehen sein, dass er aber jegliche Archive ignoriert, solange nichtt explizit die Object File angegeben wurde, in der der Programmeinsprungspunkt auftaucht, ist vollst\u00e4ndig unlogisch, da Archive eigentlich wie normale Object-Files behandelt werden sollten. Ein Aufruf der Form<\/p>\n<pre lang=\"bash\">gcc -o executable.bin main.o archive1.a archive2.a archive3.a archive4.a<\/pre>\n<p>funktioniert somit, selbst wenn main.o bereits in einem der Archive enthalten ist. Mit Logik hat das zumindest nur wenig zu tun &#8230;<\/p>\n<p>Ob sich dieses Verhalten \u00e4ndert, wenn man -Wl,-u -Wl,main als Parameter mitgibt, habe ich aber nicht mehr probiert. Ich vermute hier aber einmal, dass dies den GCC genauso wenig beeindruckt, wie rein die Angabe von A-Dateien, ggf. mit dem Unterschied, dass er beim Linken jegliche Boot-Symbole vergessen wird.<\/p>\n<p class=\"wp-flattr-button\"><a href=\"https:\/\/blog.benny-baumann.de\/?flattrss_redirect&amp;id=448&amp;md5=5e1a7e768826d356dfde79423d9ae007\" title=\"Flattr\" target=\"_blank\"><img src=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" srcset=\"http:\/\/blog.benny-baumann.de\/wp-content\/plugins\/flattr\/img\/flattr-badge-large.png\" alt=\"Flattr this!\"\/><\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>Manchmal sind Programme wie der GCC selbst f\u00fcr gestandene Entwickler ein R\u00e4tsel. Nehmen wir ein beliebiges, einfaches, ggf. etwas gr\u00f6\u00dferes Projekt, dessen C-Source zu compilieren ist. Nimmt man jetzt noch an, dass dieses Projekt mehrere Module beinhalten kann, so bieten sich ja eigentlich Libraries an. Handelt es sich dabei um ein Projekt, bei dem dynamisches [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[29],"tags":[62,98,241],"class_list":["post-448","post","type-post","status-publish","format-standard","hentry","category-software","tag-bug","tag-developement","tag-gcc"],"_links":{"self":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/448","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=448"}],"version-history":[{"count":1,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/448\/revisions"}],"predecessor-version":[{"id":449,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=\/wp\/v2\/posts\/448\/revisions\/449"}],"wp:attachment":[{"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=448"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=448"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.benny-baumann.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=448"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}