5. Desarrollo del proyecto

El proyecto propuesto por Jesús Labarta y Judit Giménez fue portar DITools a GNU/Linux sobre INTEL® 386.

El desarrollo de pDI-Tools se ha dividido en cuatro partes básicas: evaluación del proyecto, formación e investigación, desarrollo de pDI-Tools y creación de la documentación. Seguidamente describimos cada una de ellas.

5.1. Evaluación del proyecto

El primer paso fue evaluar la viabilidad del proyecto. Para ello solicite una copia del código fuente de DITools y toda la documentación posible sobre el mismo. Resultó que no se pudo encontrar documentación sobre DITools, a parte de los artículos [DITools] y [DITools2]. Estos artículos son descriptivos y no dan información detallada sobre el funcionamiento interno de DITools.

Así que se empezó a leer directamente el código e intentar conocer en detalle el funcionamiento de DITools. Por el estado del código fuente de DITools se deduce que esta aplicación se desarrolló según las necesidades que aparecían y se ha modificado por diferentes personas. El código está vagamente documentado y es en ocasiones bastante inconsistente y caótico. Esto significó un gran esfuerzo de ingeniería inversa para poder deducir el funcionamiento del código.

A la vez que se estudiaba DITools se empezó a estudiar el funcionamiento de ELF y como este se aplica sobre Irix/MIPS®.

De contrastar ambos estudios se llegó, en dos semanas, a concluir que la tarea de portar DITools directamente a GNU/Linux sería extremadamente compleja e ineficiente. Además, visto como se resolvían ciertas cosas en DITools, se prefirió comenzar desde cero para tener un programa con mejores prestaciones y más sencillo de mantener y portar.

5.2. Formación e investigación

Se retomó el estudio de DITools para extraer de él toda la experiencia e ideas posibles. Era necesario conocer bien su funcionamiento para que la nueva aplicación ofreciese, no sólo nuevas funcionalidades, sino una importante compatibilidad con él.

Fue complicado por la falta de comentarios y el degenerado estado del código debido, principalmente, a que distintos programadores introdujeron modificaciones sin reciclar código y sin evaluar el impacto que tendrían éstas en el resto del programa. El resultado es un código difícil de seguir con mucho código desactivado, apaños, condiciones extrañas y notas escritas por los programadores justificando su último "hack".

El esfuerzo de ingeniería inversa se combinó con un esfuerzo de reestructuración y depuración del código. Modificando y mejorando el código a la vez que se estudiaba permitió acelerar el proceso de aprendizaje. Tomar una posición activa facilita la comprensión y es más interesante que una simple posición pasiva donde simplemente se lee.

Se trabajó sobre DITools intensamente durante unos tres meses a la vez que se estudiaba el estándar ELF. Es aconsejable tener un conocimiento de ELF para poder entender como funciona DITools, aunque no muy profundo. Esto se debe a dos motivos: el primero es que DITools se apoya fuertemente sobre las API específicas de rld(5) (el "Runtime Linker" de Irix). El segundo motivo es que la implementación de ELF en Irix sobre MIPS® es bastante particular.

Por ello se dedicó una gran cantidad de tiempo a analizar "Runtime Linker" de otros sistemas operativos. El formato ELF es un estándar que se ve muy afectado por la arquitectura, y además se implementa de forma irregular.

Esto se debe a que un formato de enlace dinámico debe ser muy eficiente. No tiene sentido un enlace dinámico lento: nadie lo usaría y sería rechazado de inmediato. Por eso mismo siempre que se puede se explotan al máximo las características del "hardware" subyacente y por lo tanto se introducen serias diferencias de una plataforma a otra.

También es debido a que el enlace dinámico sólo se suele gestionar por herramientas específicas del sistema operativo y rara vez las aplicaciones acceden directamente a sus estructuras. Y cuando no es así, en la mayor parte de los casos intermedia la librería de C, que al igual que el "Runtime Linker", está muy ligada al sistema operativo.

Por ello, a pesar de las incompatibilidades, apenas hay problemas a la hora de portar aplicaciones normales. Sólo en algunos pocos casos, en los que las aplicaciones acceden directamente a estas estructuras, puede haber problemas. Pero estas aplicaciones son pocas ya que suelen ser muy especiales: un depurador de "software" (por ejemplo GNU Debugger), una herramienta de "profiling", o el mismo pDI-Tools. Por eso no hay un importante esfuerzo por seguir estrictamente los estándares.

Se descubrió que apenas hay documentación y "software" relacionado con ELF y el enlace dinámico. Se recurrió a todo tipo de documentos, artículos, notas, código y "mails" que pudiesen aclarar ELF, los "Runtime Linker", técnicas de reenlace, particularidades de ELF, etc.

Esta recopilación de información junto el conocimiento obtenido de DITools se usó para valorar que requisitos debía cumplir la nueva aplicación que desarrollaríamos. Se decidió que características de DITools se debían mantener, cuales evitar y como evitar futuros problemas de portabilidad.

5.3. Desarrollo de pDI-Tools

Con la información y experiencia reunida se comenzó un nuevo programa que recibe el nombre de pDI-Tools. Este introduce importantes cambios estructurales (respecto DITools) orientados a mejorar la portabilidad, velocidad, estabilidad y eficiencia. Aún así se intentaría imitar el comportamiento de DITools para facilitar el "porting" de OMPItrace (programa de instrumentación de programas paralelos desarrollado por el CEPBA) a pDI-Tools.

Durante todos estos estudios se fueron realizando pruebas para comprobar si era posible implementar los mecanismos de reenlace y gestión de "backends" en GNU/Linux sobre INTEL® 386. Estas pruebas eran pequeños programas específicos, parte en ensamblador y parte en C que introducían a fuerza bruta interposiciones, comprobaban si las estructuras ELF eran siempre coherentes, evaluaban casos extremos y demás. Estos programas, que denominamos "pruebas de concepto", sirvieron para demostrar que el proyecto era totalmente viable.

También se hicieron pruebas de concepto sobre otras arquitecturas como SPARC e Itanium®. Estas pruebas mostraron hasta que punto podemos confiar en el estándar para conseguir nuestros propósitos.

Las pruebas de concepto no se conservan en su mayor parte, ya sea porque fueron borradas al acabar de usarse o recicladas en otras pruebas. Tampoco hubiera aportado mucho conservarlas ya que dependían de demasiados parámetros (como el compilador, las librerías, el programa de reenlace, etc.) y sólo servían para probar un determinado fenómeno.

Cuando se tuvo suficiente experiencia y estaba seguro sobre como se implementarían los mecanismos comencé a escribir DITools comenzando por la parte independiente de la arquitectura. Esto incluye:

Mientras se desarrollaba todo esto se escribió en paralelo un "Elf Backend" ("driver" encargado de gestionar las estructuras ELF específicas para un sistema operativo y arquitectura) para GNU/Linux sobre INTEL® 386.

El desarrollo de este "Elf Backend" a su vez redirigió la escritura del código de la parte no dependiente: la experiencia lograda con las pruebas de concepto sumado a esta puesta en práctica ayudaba a discernir que era lo bastante genérico como para ir a la parte independiente de la arquitectura y que era específico para Linux™/INTEL® 386.

Cuando se obtuvo un primer prototipo aparentemente portable se empezó a desarrollar en paralelo una versión para Solaris sobre SPARC a la vez que se terminaba la versión para GNU/Linux/INTEL® 386.

Se escogió esta arquitectura SPARC debido a que es una arquitectura frecuente en laboratorios de cálculo. Otro buen motivo fue que generalmente todo lo relativo a ella y en ella suele estar muy pulido y claro. Se encontró una documentación muy buena, el ensamblador es muy claro y elegante, y además la implementación suele ser muy fiel a las especificaciones.

Para investigar y aprender más sobre esta plataforma adquirí mi propia máquina Sun Microsystems™, una UltraSPARC™ II, por un módico precio en el mercado de segunda mano.

Este "porting" desveló que la parte independiente de la arquitectura no era tan independiente. Se encontraron diferencias entre las librerías de C de Solaris, nuevas particularidades del "Runtime Linker" y nuevas necesidades a la hora de gestionar los mecanismos de interposición.

Pero la novedad más impactante fue la introducción de los 64 bits. Esto afecto a la totalidad de pDI-Tools, desde los "scripts" de configuración hasta la organización del código. A pesar de tratarse la misma CPU, cada modelo implica un formato ELF distinto y tipos de datos algo distintos. Se destaparon y resolvieron problemas de portabilidad dados por los tipos de datos y obligó a crear una nueva capa de abstracción en los "drivers" de sistema operativo para poder manejar diferentes CPU's.

También obligó a escribir un código aún más genérico en la parte no dependiente que nos permitió ver que código era redundante en ambos "Elf Backend" y así detectar código portable que a priori pensábamos que era específico.

Los resultados fueron satisfactorios ya que en poco más de un mes ya habían tres versiones nuevas plenamente funcionales de pDI-Tools: GNU/Linux sobre INTEL® 386 (sólo 32 bits), Solaris sobre SPARC en 32 bits, Solaris sobre SPARC en 64 bits.

La única diferencia entre la versión INTEL® 386 y las versiones SPARC son las interposiciones mediante el mecanismo de "callback". De hecho este tipo de interposiciones sólo está disponible en pDI-Tools para GNU/Linux sobre INTEL® 386. Debido a su complejidad y coste se decidió implementar únicamente sobre INTEL® 386 únicamente para demostrar que son posibles. La programación de este tipo de interposición llevo más un mes de trabajo, y la mayor parte del código es totalmente dependiente de la arquitectura INTEL® 386.

Una vez terminadas de programar estas versiones se comenzó a analizar la plataforma PowerPC™ 32 bits, muy similar a SPARC 32 bits. Esta tarea ayudó a que el API tuviese unas estructuras de datos más firmes y flexibles ante nuevas plataformas.

Crear esta versión de pDI-Tools para Linux™/PowerPC™ 32 bits permitió ver como se gestiona la portabilidad dentro de un mismo "Elf Backend". Recordemos que el código se divide en sistemas operativos, y la gestión de los "drivers" de CPU corren a cuenta del "Elf Backend". Luego se hizo un gran esfuerzo por marcar un esquema en los "Elf Backend" que aislará toda la parte dependiente de la CPU en localizados puntos.

Con todo esto el prototipo actual ya presentaba un gran nivel de portabilidad. Ahora sólo quedaba completar el trabajo sobre PowerPC™ e implementar la versión de 64 bits de pDI-Tools.

Aparentemente, teniendo hecha la versión de PowerPC™ 32, portar pDI-Tools a 64 bits tendría que ser algo fácil. Pero sus respectivos ABI son muy distintos, y esto hizo que fuese en realidad la versión más difícil de implementar.

La especificación ELF se divide en un documento general para todas las plataformas y luego en documentos específicos para cada plataforma que reciben el nombre de suplementos. El formato ELF para GNU/Linux sobre PowerPC™ 64 está todavía en desarrollo y no hay todavía un verdadero suplemento ELF, sino una especie de indicaciones de como se debería implementar. Estas indicaciones están basadas en la especificación PowerOpen™ del formato COFF. Como IBM AIX implementaba inicialmente el ABI PowerOpen™, sus desarrolladores lo disimularon mediante un disfraz que ofrece un pequeño grado de compatibilidad con el formato ELF. Este disfraz no permite trabajar correctamente con casi ninguna estructura ELF y de hecho no cumple el estándar ELF.

En resumen esta arquitectura no dispone de buena documentación y la implementación es muy discordante respecto a la poca documentación existente.

Todo ello llevo a una nueva etapa de investigación bastante dura ya que se tuvo que desensamblar mucho código para ver si era posible o no implementar pDI-Tools sobre GNU/Linux para PowerPC™ 64.

Por suerte todo fue bien y en el plazo de casi 3 semanas se consiguió una implementación funcional y correcta de pDI-Tools para PowerPC™ 64.

Para evaluar el nivel de portabilidad logrado, se probó a portar a Irix sobre MIPS®. El objetivo era ver el tiempo necesario para implementar un nuevo "Elf Backend" desde cero. Los resultados fueron sorprendentes: en una semana pDI-Tools estaba funcionando en Irix sobre MIPS®, tanto para 32 como 64 bits. Además no se tuvo que realizar ningún cambio en la parte no dependiente de la arquitectura. Con esto quedo probada la gran portabilidad de pDI-Tools.

La ventaja de haber desarrollado sobre todas estas arquitecturas, y en algunas ocasiones en paralelo, es haber constrastado las diferencias más importantes entre arquitecturas. Con ello se ha ganado experiencia y ayuda a ver donde la implementación es susceptible a presentar incompatibilidades. Además ha obligado a adoptar una serie de hábitos y métodos que ayudarán en el futuro a portar pDI-Tools.

Finalizada la versión de Irix/MIPS® todos los requerimientos de la especificación ya estaban cumplidos. Ahora sólo quedaba mejorar el rendimiento del programa, buscar posibles errores y/o limitaciones y arreglarlas y dar ciertas garantías de que el código es correcto y portable.

5.4. Creación de la documentación

Durante los últimos siete meses se había empezado ya el entorno de documentación y se dedicaba una parte importante del tiempo a escribir esta documentación.

La documentación se empezó con la creación del entorno de proceso de documentos XML en formato DocBook. DocBook/XSL es un lenguaje XML que permite escribir documentos grandes, insertando marcas semánticas, sin preocuparse de su presentación. Es similar a LaTeX pero en XML. Se escogió este sistema de documentación en lugar de Texinfo, el sistema sugerido por la FSF para el software GNU, debido a que es más potente, flexible y especialmente por su auge en importantes proyectos como Gnome™ o el kernel de GNU/Linux.

Para editar documentos DocBook/XSL basta con un editor de textos cualquiera. El problema surge cuando se intenta traducir el documento a un formato imprimible o legible, es decir, que ya no contenga marcas semánticas y en su lugar se hayan aplicado unos estilos de presentación.

No hay "software" libre en el mercado que permita realizar fácilmente esta operación. Sólo se dispone es del programa OpenJade y un conjunto de hojas de estilo DSSSL publicadas por Norman Walsh que permiten convertir un documento DocBook en formato PDF, PostScript®, RTF y HTML. También existe FOP[1], pero se desestimó su uso por su dependencia en Java, una herramienta no libre.

Fue necesario crear un entorno compuesto de ficheros makefile, hojas de estilo XSLT y CSS, "scripts", etc. que facilitasen y automatizasen al máximo el proceso de generación de la documentación formateada.

También se han creado varios programas en Perl encargados de realizar ciertas tareas sencillas. Por ejemplo, se usan estos "scripts" para generar las marcas de índice que se usarán en el documento DocBook/XSL para generar el índice conceptual de la versión impresa. Estos "scripts" generan ficheros XML que se combinarán con los ficheros XML de la documentación.

La documentación se divide en una multitud de pequeños ficheros XML que se combinan, junto a los XML generados por los "scripts", en un documento final. Este fichero se construye con hojas de transformación XSLT y el programa xsltproc.

Una vez ya se tiene el documento DocBook este se pasa a un conjunto de "scripts" encargados de aplicar las hojas de transformación de Norman Walsh con OpenJade. Esto resultará en una renderización del documento. Aprovechando que OpenJade es en realidad un procesador de documentos SGML y hojas de estilo DSSSL, con unas hojas de estilo escritas por mi se adecua el aspecto del documento.

Se necesitó alrededor de dos semanas para escribir lo más básico del entorno de desarrollo. A partir de ahí se fue mejorando poco a poco y se le fueron añadiendo más funcionalidades.

En cuanto pudo generar documentos se uso para escribir el documento de presentación del proyecto: pDI-Tools: Descripción del proyecto.

Durante la escritura de ese documento se fue perfeccionando el entorno DocBook/XSL. Cuando este documento estuvo acabado, el entorno estaba lo suficiente evolucionado como para poder usarlo en la escritura de la presente memoria.

Notas

[1]

Es un formateador de documentos XML en formato XSL-FO: FOP.