Showing posts with label notes. Show all posts
Showing posts with label notes. Show all posts

Thursday, September 27, 2007

GraphViz


Some notes on the great GraphViz package

Visualize a build dependency tree

maketograph.py

#! /usr/bin/python
import sys
import re

sys.stdout.write("digraph Makefile {\n")

regex = re.compile("^([^:]+): (.+)$")
for line in sys.stdin.read().split('\n'):
    mo = regex.match(line)
    if mo:
        origin = mo.group(1)
        targets = mo.group(2).split()
        for target in targets:
            sys.stdout.write('\t"%s" -> "%s";\n' % (target, origin))

sys.stdout.write("}")

the Makefile

all: main main2

main: main.c libhello.so
    gcc -o $@ $< -L. -lhello

main2: main2.c libhello.so
    gcc -o $@ $< -ldl

hello.o: hello.c hello.h
    gcc -c -fPIC $<

libhello.so: hello.o
    gcc -shared -o $@ $<

clean:
    rm -fr libhello.so main *.o

creating the graph

$ ./maketograph.py < Makefile > Makefile.dot
$ dot -Tpng Makefile.dot >| Makefile.png

The result:


further

  • egypt - create call graph from gcc RTL dump

Libraries


Here are some notes on building an using libraries in their different flavours on POSIX systems.

the library

hello.h

typedef void (*HelloFunc)();
void hello();

hello.c

#include <stdio.h>
#include "hello.h"

void hello()
{
    printf("hello world\n");
}

building the library:

gcc -fPIC -c hello.c
gcc -shared -o libhello.o hello.o

binding on load time

main.c

#include "hello.h"
int main()
{
    hello();
    return 0;
}

building main

gcc -o main main.c -L. -lhello

running main

$ LD_LIBRARY_PATH=. ./main
hello world

binding on run time

main2.c

#include <dlfcn.h>
#include <stdio.h>
#include "hello.h"

int main()
{
    void* handle = dlopen("./libhello.so", RTLD_NOW);
    if (handle == NULL) {
        printf("dlopen failed: %s\n", dlerror());
        return 1;
    }

    void* symbol = dlsym(handle, "hello");
    if (symbol == NULL) {
        printf("dlsym failed: %s\n", dlerror());
        return 1;
    }

    HelloFunc helloFunc = (HelloFunc) symbol;
    helloFunc();

    if (dlclose(handle) != 0) {
        printf("dlclose failed: %s\n", dlerror());
        return 1;
    }

    return 0;
}

building main

gcc -o main2 main2.c -ldl

running main

$ ./main2
hello world

static binding

building the library

gcc -c hello.c
ar rc libhello.a hello.o
ranlib libhello.a

building main

gcc -o main main.o libhello.a

running main

$ ./main
hello world

further reading

tools:
  • ldd - print shared library dependencies
  • nm - list symbols from object files
  • objdump - display information from object files
  • readelf - Displays information about ELF files
More on libraries can be found here.

Update: Ian Lance Taylor has written a series of 20 articles on linkers and the ELF format. Here is the first one.