lunes, 27 de mayo de 2013

Compilar linux-2.6.37 para Intel + parche

Tuve la necesidad de usar el “viejo” linux 2.6 y además compilándomelo para reducir su tamaño al mínimo, he pasado varias horas buscando en la web por algunos errores de compilación que me daba. Con lo que ha “llovido” desde entonces  probablemente esto ya esté parcheado para esta versión y resuelto nativamente para las posteriores (esto si me consta) así que simplemente considero incrementar tus probabilidades de dar con la solución que yo no pude econtrar. El primer error se refiere a una inconsistencia en la declaración de dos funciones:
extern long syscall_trace_enter(struct pt_regs *);
extern void syscall_trace_leave(struct pt_regs *);
en el archivo “./linux-2.6.37/arch/x86/include/asm/ptrace.h“. Se trata de un atributo especificado a las funciones en la implementación(“./linux-2.6.37/arch/x86/kernel/ptrace.c“) de la función y no así en la declaración. Esto se expresaba con “asmregparm” como una macro (” #define asmregparm __attribute__((regparm(3))”) del archivo (“./linux-2.6.37/arch/x86/include/asm/linkage.h“) la sustitución llevada a cabo por el preprocesador especificaba a la función el atributo __attribute__((regparm(x))) como antes mencionaba.
__attribute__((regparm(number))):
Este puede ser utilizado solo para arquitectura intel(i386 y x86-64) y se refiere a que el paso de parámetros se hará de manera directa mediante registros( EAX, EDX,y ECX) si estos son de tipo entero y no por el stack en memoria como suele ser, son pasados los que numeran entre el primero y “number”, los que siguen después de la cantidad “number” serán pasados por el stack de forma común y ello se aplica también para las funciones que reciben un número de argumentos variable. Más documentación al respecto la puedes obtener en la especificación de tu compilador, yo me he referido a gcc que es el que uso y según tengo entendido agrega esta característica desde su versión 3.4.0 para linux (i686-pc-linux-gnu). Además agregar que cuando he usado atributos para las funciones lo he puesto en la declaración de esta, no en la implementación y al final, no al inicio, no me queda claro que esto sea relevante pero lo he visto en algún libro sobre herramientas GNU que ahora no recuerdo el título.
El segundo error se debe a una variable duplicada (expeculando, la impresión que me dio fue que escribieron el cuerpo del struct en dos momentos diferentes  dejando pasar por alto este pequeño detalle) en el strcut igbvf_buffer del archivo ./linux-2.6.37/drivers/net/igbvf/igbvf.h En la documentación de gcc podemos ver en un topic(“Unnamed struct/union fields within structs/unions”) dedicado a estructuras/uniones anónimas que según lo establecido por la norma ISO C1X y por compatibilidad con otros compiladores se permite definir estructuras y uniones que contienen como alguno/os de su/us campo/os estructuras y/o uniones sin nombre. Pero nunca se deberán crear estas estructuras de manera que cause definición de campos ambiguos como en este caso(y el caso del error en el código linux):
struct {
int a;
struct {
int a;
};
} foo;
Sin más te dejo el parche );. Tal vez te sea de ayuda un post para cómo aplicarlo.
git clone https://github.com/denisacostaq/intel_asmregparm-page_anonymous_struct-2.6.37.patch.git

domingo, 26 de mayo de 2013

Crear/aplicar un parche usando Git

Git es un software de control de versiones diseñado por Linus Torvalds, pensando en la eficiencia y la confiabilidad del mantenimiento de versiones de aplicaciones cuando estas tienen un gran número de archivos de código fuente
Antes de comenzar con los pasos señalar que si el parche que deseas hacer es para corregir un bug o agregar una nueva funcionalidad deberías hacer esto en una nueva rama dedicada solo a ello, en base a esto el parche que contruiremos en este post se creará a partir de las diferencias entre dos ramas aunque también se puede crear entre versiones, fechas, marcas, …
  1. Crear un directorio donde estará nuestro “gran proyecto” (mkdir test-git).
  2. Entrar e inicializar un repositorio vacio. (cd test-git/ ; git init)
  3. Crear algún archivo y editarlo(nano main.c):
    #include <stdio.h>
    int main (int argv, char *argvv[])
    {
         printf ("hello git\n");
         return 0;
    }
  4. Agregar a git el directorio actual(que en el se encuentra el archivo de interés) y hacer nuestro primer commit lo que además abilitará la rama master.(git add . ; git commit -m “the first commit”)
  5. Ya podemos listar las ramas y ver que se encuentra activa la master(git branch).
  6. Creamos una nueva rama “en la que escribiremos los cambio al proyecto”(git branch crpatch).
  7. Nos movemos a la nueva rama y verificamos que sea la activa (git checkout crpatch ; git branch).
  8. Efectuamos los cambio al proyecto:       
  9. Crear algún archivo y editarlo(nano main.c):
    #include <stdio.h>
    int main (int argv, char *argvv[])
    {
         printf ("
    hello git, this program become from a patch\n");
         return 0;
    }
  10. Agregar los cambios (git add . ; git commit -m “commit for the patch”).
  11. Ya podemos ir chequeando las diferencias que ha tomado el proyecto con repecto a la rama master (git diff master).
  12. Por útimo crear el parche… (git format-patch master --stdout > crpatch.patch).
Ya tenemos el parche, ahora veremos como aplicarlo:
  1. Nos movemos a la rama master y eliminamos la rama “crpatch” con lo que perderiamos todos los cambios efectuados si no fuese porque contamos con el parche(git checkout master ; git branch -D crpatch).
  2. Revisamos los cambios que presumpondría el aplicar el parche(git apply --stat crpatch.patch).
  3. Revisamos si el aplicar el parche nos pudiese taer algún error (git apply --check crpatch.patch). Si no obtienes nada en la salida es porque puedes aplicar el pache satisfactoriamente.
  4. Por último aplicamos el parche revisando antes y después el contenido para comprobar y entender el trabajo(cat main.c ; git apply crpatch.patch ; cat main.c).
Listo!!!, espero que estés preparado lo mismo para “escribir” un parche y enviarlo a los desarrolladores con los cuales quieras colaborar que para parchear algún programa con un parche que tengas para ello.