From 0e847121f4fa9135e773c07213b0cbf3f73a2495 Mon Sep 17 00:00:00 2001 From: Amand Tihon Date: Sat, 8 Aug 2009 20:31:14 +0200 Subject: [PATCH] Update documentation, add example and install script. --- doc/README | 16 +- doc/README.html | 530 ++++++++++++++++++++++++++++++++++++++++ examples/flow2/Makefile | 11 + examples/flow2/flow2.c | 93 +++++++ setup.py | 15 ++ 5 files changed, 663 insertions(+), 2 deletions(-) create mode 100644 doc/README.html create mode 100644 examples/flow2/Makefile create mode 100644 examples/flow2/flow2.c create mode 100755 setup.py diff --git a/doc/README b/doc/README index a66fb64..8318838 100644 --- a/doc/README +++ b/doc/README @@ -1,4 +1,4 @@ -.. HTML version generated with rst2html -t README > README.html +.. HTML version generated with LC_ALL=C rst2html -t README > README.html .. |date| date:: %b %e, %Y @@ -60,7 +60,14 @@ recompile the source code into an object file. Installation ============ -TBD. +Go into Bold's directory, and run :: + + python setup.py build + +Then, as root or using sudo, run :: + + python setup.py install + Using Bold @@ -213,4 +220,9 @@ Executables generated by ``ld`` usually have a lot of entries in their And that's it! +Examples +======== +The ``examples/`` directory contains a port of the *flow2* intro +(http://www.pouet.net/prod.php?which=30589). Adding the dropper is left as an +exercise for the reader. diff --git a/doc/README.html b/doc/README.html new file mode 100644 index 0000000..8e79cb0 --- /dev/null +++ b/doc/README.html @@ -0,0 +1,530 @@ + + + + + + +Bold - The Byte Optimized Linker + + + + + + +
+

Bold - The Byte Optimized Linker

+ +++ + + + + + + + + + + + +
Author:Amand Tihon
Contact:<amand.tihon@alrj.org>
Version:0.1.0
Date:Aug 8, 2009
Copyright:GNU GPL version 3 + Exception, see copyright file.
+ + +
+

1   Abstract

+

Bold is an ELF linker, currently only targetting x86_64 under Linux. Being +limited in capabilities, it should not be considered as an all-purpose linker.

+
+
+

2   Rationale

+

Bold's main purpose is to generate very small executable programs.

+

While ld from the GNU binutils can do almost anything anyone would ever +need, some specific goals need an awful lot of tweaking, or can simply not be +achieved. Bold uses several tricks to reduce the size of the final executable +binary.

+
+
+

3   Getting Bold

+

You can download the tarball from http://www.alrj.org/projects/bold +or get the latest development version with the following git command:

+
+git clone http://git.alrj.org/git/bold.git
+
+

A gitweb interface is also available at http://git.alrj.org/

+
+
+

4   Requirements

+

Bold itself is entirely written in Python. There are no additionnal +dependencies.

+

The runtime library that contains the external symbols resolver is written +in assembler (Intel syntax). An assembler like Nasm or Yasm is needed to +recompile the source code into an object file.

+
+
+

5   Installation

+

Go into Bold's directory, and run

+
+python setup.py build
+
+

Then, as root or using sudo, run

+
+python setup.py install
+
+
+
+

6   Using Bold

+
+

6.1   Synopsys

+
+bold [options] objfile...
+
+
+

6.2   Description

+

Bold combines a number of object files, relocate their data and resolves their +symbols references, in order to generate executable binaries.

+

Bold has only one, very specific purpose: making small executables.

+
+
+

6.3   Options

+ +++ + + + + + + + + + + + + + + + + + + + + + + + +
+--versionShow program's version and exit.
+-h, --helpShow help message and exit.
+-e SYMBOL, --entry=SYMBOL
 Use SYMBOL as the explicit symbol for beginning execution of your program. +If --raw is specified, it defaults to _start.
+-l LIBNAME, --library=LIBNAME
 Link against the shared library specified by LIBNAME. Bold relies on python's +ctypes module to find the libraries. This option may be used any number of +times.
+-L DIRECTORY, --library-path=DIRECTORY
 This option does nothing, and is present ony for compatibility reasons. It +MAY get implemented in the future, though. This option may be used any number +of times.
+-o FILE, --output=FILE
 Set the output file name (default value is a.out).
+--rawDon't include the builtin external symbols resolution code. This is +described in details further in this document.
+-c, --ccallMake external symbols directly callable by C, without having to declare the +pointers on functions. This option adds 6 bytes for each externally defined +function. This is described in details further in this document.
+-a, --alignAlign the wrappers for external symbols on an 8 byte boundary, to take +advantage of the RIP-relative addressing. This is described in details +further in this document.
+
+
+

6.4   Notes

+

The LD_PRELOAD environment variable may not always work (as expected or +at all).

+

The main() function is called without any argument. Its return code is used +as exit code, though.

+
+
+
+

7   Internals

+
+

7.1   External symbols resolution

+

The "import by hash" method is from parapete, leblane, las, as described on +http://www.pouet.net/topic.php?which=5392

+
+
+

7.2   Calling from C

+

If you write your code in C and need to call the external symbols, you +basically have two options. The first one is to redefine them (or define new +ones) to call by pointers. For instance,

+
+int SDL_Init(int);
+
+

would become:

+
+int (*SDL_Init)(int);
+
+

Repeat it for all functions, or write a tool to automate it (hint: look at +http://research.mercury-labs.org/ibh-i386-0.2.2.tar.gz for help).

+

There's a second possibility however, and it's the one used by Bold when you +specify the --ccall option: make the resolved symbol point, not to the +address of the function, but to a JMP instruction to the actual address:

+
+global SDL_Init
+
+.text
+
+SDL_Init:          jmp [rel _bold__SDL_Init]
+SDL_SetVideoMode:  jmp [rel _bold__SDL_SetVideoMode]
+
+.bss
+
+_bold__SDL_Init          resq        ; Filled by the import by hash code
+_bold__SDL_SetVideoMode  resq
+
+

This approach takes 6 bytes (the JMP instruction) for each external function +used.

+
+
+

7.3   Aligning

+

The x86_64 architecture has this nice thing called "RIP-relative addressing". +If all the JMP instructions are in the same order than the pointers to the +functions they refer to, having them aligned with the pointers would result +in identical instructions. This is done with the --align option.

+

Adding two null bytes between each JMP enlarges the final executable by +2 x (number of function - 1) bytes, and may seem to go against our goal. +However, the result is a repetition of the same eight bytes, something that +can improve compression a lot!

+
+
+

7.4   Additional Trick 1: DT_DEBUG

+

Bold declares a global symbol named _dt_debug, that points to the value of +the DT_DEBUG entry of the DYNAMIC table, for easy access. Just in case, +the DYNAMIC table can also be reached using the global _DYNAMIC symbol.

+
+
+

7.5   Additional Trick 2: Short DYNAMIC table

+

Executables generated by ld usually have a lot of entries in their +DYNAMIC table. Bold puts only the strict necessary:

+
    +
  • One DT_NEEDED entry for each shared library to load (obviously).
  • +
  • A DT_SYMTAB entry, with null-pointer. Without this one, the interpreter +wouldn't do its job.
  • +
  • a DT_DEBUG entry, that will be used for symbol resolution.
  • +
+

And that's it!

+
+
+
+

8   Examples

+

The examples/ directory contains a port of the flow2 intro +(http://www.pouet.net/prod.php?which=30589). Adding the dropper is left as an +exercise for the reader.

+
+
+ + + diff --git a/examples/flow2/Makefile b/examples/flow2/Makefile new file mode 100644 index 0000000..669383d --- /dev/null +++ b/examples/flow2/Makefile @@ -0,0 +1,11 @@ +#! /usr/bin/make + + +all: flow2 + +flow2.o: flow2.c + gcc -c -Os `sdl-config --cflags` -o $@ $< + +flow2: flow2.o + bold -c -a `sdl-config --libs` -lGL -o $@ $< + diff --git a/examples/flow2/flow2.c b/examples/flow2/flow2.c new file mode 100644 index 0000000..4ec7389 --- /dev/null +++ b/examples/flow2/flow2.c @@ -0,0 +1,93 @@ + +// Linux x86_64 port of flow2, to be linked with the bold linker. +// Ported by Amand Tihon (alrj). +// Original comments in flow2 source code copied verbatim + + +// Chris Thornborrow (auld/sek/taj/copabars) +// If you use this code please credit...blahblah +// Example OGL + shaders in 1k +// Requires crinkler - magnificent tool +// VS2005 modifications by benny!weltenkonstrukteur.de from dbf +// Greets! +// NOTE: DX will beat this no problem at all due to OpenGL forced +// to import shader calls as variables..nontheless we dont need +// d3dxblahblah to be loaded on users machine. + +#include "GL/gl.h" +#include "SDL.h" + +// NOTE: in glsl it is legal to have a fragment shader without a vertex shader +// Infact ATi/AMD drivers allow this but unwisely forget to set up variables for +// the fragment shader - thus all GLSL programs must have a vertex shader :-( +// Thanks ATI/AMD + +// This is pretty dirty...note we do not transform the rectangle but we do use +// glRotatef to pass in a value we can use to animate...avoids one more getProcAddress later +const GLchar *vsh="\ +varying vec4 p;\ +void main(){\ +p=sin(gl_ModelViewMatrix[1]*9.0);\ +gl_Position=gl_Vertex;\ +}"; + +// an iterative function for colour +const GLchar *fsh="\ +varying vec4 p;\ +void main(){\ +float r,t,j;\ +vec4 v=gl_FragCoord/400.0-1.0;\ +r=v.x*p.r;\ +for(int j=0;j<7;j++){\ +t=v.x+p.r*p.g;\ +v.x=t*t-v.y*v.y+r;\ +v.y=p.g*3.0*t*v.y+v.y;\ +}\ +gl_FragColor=vec4(mix(p,vec4(t),max(t,v.x)));\ +}"; +//p.g*3.0*t*v.y+i;\ + +static void setShaders() { + + GLuint v = glCreateShader(GL_VERTEX_SHADER); + GLuint f = glCreateShader(GL_FRAGMENT_SHADER); + GLuint p = glCreateProgram(); + + glShaderSource(v, 1, &vsh, NULL); + glCompileShader(v); + glAttachShader(p, v); + glShaderSource(f, 1, &fsh, NULL); + glCompileShader(f); + glAttachShader(p, f); + glLinkProgram(p); + glUseProgram(p); +} + +int main() +{ + static SDL_Event e; + SDL_Init(SDL_INIT_VIDEO); + SDL_SetVideoMode(1024, 768, 0, SDL_OPENGL); + + SDL_ShowCursor(SDL_DISABLE); + setShaders(); + //********************** + // NOW THE MAIN LOOP... + //********************** + // there is no depth test or clear screen...as we draw in order and cover + // the whole area of the screen. + do + { + glRotatef(0.3f, 1, 1, 1); + glRecti(-1, -1, 1, 1); + SDL_GL_SwapBuffers(); + + SDL_PollEvent(&e); + + if (e.type == SDL_KEYDOWN) + break; + } while (e.type != SDL_QUIT); + + return 0; +} + diff --git a/setup.py b/setup.py new file mode 100755 index 0000000..322bdd7 --- /dev/null +++ b/setup.py @@ -0,0 +1,15 @@ +#! /usr/bin/python +# -*- coding: utf-8 -*- + +from distutils.core import setup + +setup(name='Bold', + version='0.1.0', + description='The Byte Optimized Linker', + author='Amand Tihon', + author_email='amand.tihon@alrj.org', + url='http://www.alrj.org/projects/bold/', + packages=['Bold'], + scripts=['bold'], + data_files=[('/usr/lib/bold', ['runtime/bold_ibh-x86_64.o'])] + ) -- 2.39.2