2.2. Estructura y decisiones de diseño

En esta sección se discuten decisiones que se tuvieron que tomar antes y durante el desarrollo del software. Desde el sistema de compilación, pasando por el lenguaje, hasta las convenciones de programación usadas.

Todas las decisiones se hacen entorno a unas cuantas premisas y/o objetivos marcados que ya se han comentado en el capítulo de introducción. Aún así recordemos que los cuatro objetivos principales son:

En las siguientes subsecciones se discuten las principales decisiones tomadas para lograr estas metas.

2.2.1. Lenguaje y sistema de compilación

Debido a que se decidió no reusar el código de DITools en el desarrollo de pDI-Tools la primera decisión que se tuvo que tomar fue que lenguaje usar, y consecuentemente, el paradigma de programación adecuado.

El lenguaje escogido fue el C con un diseño de programación descendente. Los lenguajes C y C++ son idóneos para programar a bajo nivel. No obstante la programación orientada a objetos presenta varios inconvenientes en un proyecto de esta índole. Los motivos para desestimar el lenguaje C++ y la programación orientada a objetos se enumeran a continuación:

También se usan las aplicaciones Autoconf y Automake para gestionar la compilación del software. La herramienta Autoconf permite despreocuparse de las peculiaridades del compilador, de las librerías y de la arquitectura ya que es él quien se encarga de detectarlas y, en muchas ocasiones, ocultarlas. Automake automatiza la creación de los ficheros makefile, generándolos específicos para la versión de make instalada.

El motivo de escoger el par de aplicaciones Autoconf y Automake en lugar de otro equivalente como podría ser Imake es debido a su gran flexibilidad. Autoconf frecuentemente ha funcionado en sistemas en los que nunca se había ejecutado antes, lo cual es directamente imposible en un sistema de base de datos como Imake. Esto hace que este par funcione sobre una gran variedad de sistemas POSIX. Además, una vez construido el "script" configure.in, sólo es necesario disponer de una "shell" sh(1), un compilador de C y la herramienta make para poder compilar el programa. Imake, por el contrario, necesita estar instalado para poder realizar la compilación. Por último es mucho más difícil extender las funcionalidades de Imake debido a su naturaleza basada en una gigantesca base de datos: no es posible distribuir sólo los cambios y usarlos sin instalarlos en la base de datos de Imake.

2.2.2. Organización del código

Todas las funciones y símbolos públicos de pDI-Tools van precedidos del prefijo _pdi_. Esto reduce la posibilidad de que haya una colisión de nombres con los del programa a instrumentar.

En determinadas ocasiones se añade un infijo para agrupar determinadas funciones de tal forma que nos permita, sólo mediante el nombre, deducir a que parte del programa pertenece. Así tenemos el prefijo _pdi_bcfg_ para las funciones encargadas de manejar los ficheros de comandos, el prefijo _pdi_linux_ para todo los símbolos específicos para GNU/Linux y así sucesivamente.

Los prefijos registrados actualmente son los siguientes:

Tabla 2-1. Prefijos de los símbolos de pDI-Tools

PrefijoDescripción
_pdi_ Prefijo genérico. Todos los símbolos públicos de pDI-Tools deben estar precedidos por este prefijo.
_pdi_becfg_ Este prefijo agrupa todas las funciones relacionadas directamente con la gestión de los ficheros de comandos.
_pdi_ebe_ El infijo "ebe" se traduce como "Elf Backend". Todas las funciones con este infijo acceden directa o indirectamente a las estructuras de información ELF tanto para consultas como para realizar modificaciones. No obstante su implementación es muy genérica o totalmente desligada de la arquitectura subyacente, así que se trata de un código altamente portable. Estas funciones logran esta independencia mediante una capa de abstracción específica para la plataforma.
_pdi_arch_ Todas las funciones precedidas por este prefijo son totalmente dependientes de la arquitectura y deben ser implementadas por el código específico para la plataforma. En realidad nunca encontraremos símbolos exportados con este prefijo. Este prefijo en realidad es una macro que se traducirá al prefijo específico para la plataforma: así si llamamos a la función _pdi_arch_init en realidad estamos llamando a _pdi_linux_init en GNU/Linux, o a _pdi_irix_init en Irix, etc.
_pdi_safe_ Este grupo de símbolos son en realidad punteros a funciones. Estos punteros apuntan a funciones de la librería de C. Así por ejemplo _pdi_safe_fputc es un puntero a la función fputc. Estos punteros nos permiten llamar a funciones de C sin vernos afectados por instrumentaciones agresivas.
_pdi_irix_ Funciones y símbolos específicos para la implementación de pDI-Tools para Irix.
_pdi_linux_ Funciones y símbolos específicos para la implementación de pDI-Tools para GNU/Linux.
_pdi_solaris_ Funciones y símbolos específicos para la implementación de pDI-Tools para Solaris.

La convención usada para los tipos, constantes y variables es la siguiente:

2.2.3. Distribución de los ficheros

pDI-Tools se distribuye en un fichero .tar.gz con un nombre de la forma pditools-VERSIÓN.tar.gz donde VERSIÓN indica la versión que contiene de pDI-Tools.

La estructura de directorios en la distribución de pDI-Tools obedece a las indicaciones hechas por GNU. En el directorio principal se encuentra el "script" de configuración configure.in y ficheros de texto describiendo el contenido del paquete. También encontramos los siguientes subdirectorios:

Directorios contenidos en la distribución de pDI-Tools

./doc/

En este directorio se encuentran todos los "script" y ficheros fuente XML DocBook necesarios para construir la documentación. Además se incluye la documentación ya generada en diversos formatos (entre otros HTML, PDF y PostScript®).

./etc/

Aquí se encuentran los ficheros de configuración independientes de la plataforma.

./include/

Separamos en este directorio todos los ficheros de cabecera necesarios para poder programar con pDI-Tools. Son útiles para la programación de objetos "backend" o aplicaciones que interaccionen con pDI-Tools.

Dentro de este directorio encontramos más subdirectorios donde cada uno contiene los ficheros de cabecera específicos para una plataforma. Así por ejemplo encontramos los directorios ./include/irix/, ./include/linux/ y ./include/solaris/.

./src/

Dentro de este directorio encontramos otros subdirectorios con el código fuente necesario para construir pDI-Tools, sus utilidades y programas de "test". Y es en el directorio ./src/link/ donde está el código fuente que termina generando el núcleo de pDI-Tools: libpdi.so.

Dentro del directorio ./src/link/, al igual que pasaba en el directorio ./include/, encontramos varios subdirectorios donde cada uno contiene el código específico para una determinada plataforma.

Notas

[1]

Es posible con algunos "hacks" basados en declarar punteros de funciones en las estructuras, el uso de union y algunas macros