proyectos ejemplos c arm function-pointers memory-address thumb

ejemplos - Cambiar el valor de dirección de un puntero de función



django (4)

Tengo el siguiente código en C:

int addInt(int n, int m) { return n + m; } int (*functionPtr)(int, int); functionPtr = &addInt;

functionPtr es un puntero de función y apunta a la dirección específica de la función addInt . Quiero cambiar 1 bit de su valor, pero no puedo entender cómo.

Digamos que functionPtr apunta a 0xABC0 (asumiendo una dirección de 16 bits) después de la última declaración. Quiero cambiar su valor a 0xABC1 . Intenté O el valor con 0x1, pero supongo que algo está mal con la conversión del operando:

functionPtr = &addInt | 0x00000001; // addresses are of 32 bits

Sé que jugar con los punteros es arriesgado, pero tengo que cambiar el LSB de la dirección para ingresar al estado Pulgar de una MCU ARM Cortex-M4.



Muchos mencionaron que su enfoque es peligroso, pero en algunos casos, este es un problema real, que conocí más de una vez. Sospecho que en el momento en que su código usa la instrucción BL (bifurcación y enlace) que no cambia el modo de la CPU a pulgar, para realizar una llamada de ARM a pulgar según su puntero de función, agregue el -mthumb-interwork bandera de -mthumb-interwork a gcc al compilar tu código:

Genere código que admita llamadas entre los conjuntos de instrucciones ARM y Thumb. Sin esta opción, en arquitecturas pre-v5, los dos conjuntos de instrucciones no se pueden usar de manera confiable dentro de un programa. El valor predeterminado es -mno-thumb-interwork, ya que se genera un código ligeramente mayor cuando se especifica -mthumb-interwork. En configuraciones AAPCS, esta opción no tiene sentido.


Para modificar el valor de un puntero mediante operaciones aritméticas, deberá convertirlo a un tipo entero, realizar la operación y luego convertirlo. Sin embargo, C no define el comportamiento para convertir un puntero a otra función que no sea otro puntero de función, por lo que no hay una forma definida de hacerlo.

Sin embargo, puedes escribir esto:

typedef int (*fptr)(int, int); functionPtr = (fptr)(((intptr_t) functionPtr) | 1);

El comportamiento que está buscando es uno de los resultados más plausibles, pero una vez más, el comportamiento de ambos lanzamientos no está definido . Por lo tanto, el comportamiento esperado de realizar una llamada de función a través del puntero modificado, si su programa puede llegar tan lejos, tampoco está definido. El compilador no es necesario ni siquiera para aceptar el código.


Probablemente, es una mala idea, pero si realmente lo necesita, lo siguiente puede ser el truco:

functionPtr = &addInt; *(int*)&functionPtr |= 1;

Pero tenga en cuenta que esto no es portátil, y puede funcionar o no funcionar en su entorno.