2012-03-20 11 views
6

Estamos trabajando en un programa C compilado con arm-eabi-gcc en Linux.Cómo obtener la dirección relativa de un campo en un volcado de estructura. [C]

Estamos utilizando un volcado de una estructura grande y estamos teniendo problemas para determinar en qué dirección debemos leer varios campos de nuestra estructura (como 50 de ellos), (alineación de memoria y relleno no son tan predecibles para yo).

¿Hay alguna manera de obtener la asignación de memoria de la estructura producida por nuestro compilador? Una opción en gdb? ¿O alguna herramienta que nos ayude a encontrar la correspondencia entre campos y direcciones en el volcado?

+0

Probablemente me falta algo obvio aquí, pero si tiene una variable (digamos 'x') que se declara como una instancia de estructura (o un puntero a la estructura), entonces debería ser capaz de simplemente escribir' imprima x' (o 'print * x' si es un puntero) en gdb para volcar todos los miembros. –

+0

No estoy tratando de obtener la dirección de lo que quiero descargar. Ya tengo el vertedero y necesito la dirección relativa de todos los miembros. – Akhneyzar

Respuesta

23

Puede hacerlo con gdb. A modo de ejemplo, voy a utilizar esta fuente:

struct A { 
    int a; 
    char b; 
    short c; 
}; 

int main() { 
    struct A a; 
} 

Cargando el binario en gdb:

(gdb) print (int)&((struct A*)0)->a 
$1 = 0 
(gdb) print (int)&((struct A*)0)->b 
$2 = 4 
(gdb) print (int)&((struct A*)0)->c 
$3 = 6 

ACTUALIZACIÓN:

Si tiene que hacerlo para un gran número de campos, entonces puede ser útil usar la nueva interfaz de python de GDB (necesitará una versión reciente de GDB para usarla, estoy usando 7.4). He creado offsets.py:

import gdb 

class Offsets(gdb.Command): 
    def __init__(self): 
     super (Offsets, self).__init__ ('offsets-of', gdb.COMMAND_DATA) 

    def invoke(self, arg, from_tty): 
     argv = gdb.string_to_argv(arg) 
     if len(argv) != 1: 
      raise gdb.GdbError('offsets-of takes exactly 1 argument.') 

     stype = gdb.lookup_type(argv[0]) 

     print argv[0], '{' 
     for field in stype.fields(): 
      print ' %s => %d' % (field.name, field.bitpos//8) 
     print '}' 

Offsets() 

A continuación, puede añadir a su .gdbinit:

python 
sys.path.insert(0, '/path/to/script/dir') 
import offsets 
end 

Luego de usarlo en GDB, como:

(gdb) offsets-of "struct A" 
struct A { 
    a => 0 
    b => 4 
    c => 6 
} 

Este script hace una pocas suposiciones simplificadoras, como que no se usan campos de bits, y no profundiza en estructuras anidadas, pero esos cambios son bastante sencillos si los necesita.

+0

I undertand pero me gustaría hacer una lista como los 50 campos necesarios en ese país. – Akhneyzar

+0

Hice una versión más completa de esto, gracias por la inspiración. [Clicky] (https://github.com/Craxic/PyGDBOffsets/blob/master/offsets.py) – AStupidNoob

+0

Su '.gdbinit' se ve raro. ¿Por qué no? Source/path/to/script/dir/offssets.py' – zhangyoufu

-1

Me parece que se podría escribir un poco de código como este para los campos requeridos

struct MyStruct S; 
int Offset_of_X=((long)&(S.X))-((long)&S); 

para calcular el desplazamiento en bytes en esta situación de compilación.

Esto debería tener en cuenta cualquier problema de alineación que tenga el compilador.

+0

Pero carece de eficiencia para 50 campos o más. – Akhneyzar

+0

Esto no se compila: aritmética puntero no le permiten restar un puntero a S de un puntero a X. –

2

Puede hacerlo desde un programa en C utilizando la macro estándar offsetof(), definida en stddef.h. Sin embargo, no estoy seguro de que esto sea lo que desea, ya que es posible que no pueda ejecutarlo (compilarlo en el host probablemente devuelva correcciones incorrectas).

#include <stdio.h> 
#include <stddef.h> 

struct A { 
    int a; 
    char b; 
    short c; 
}; 

int main() { 
    printf("Offset of b in A is %zu\n", offsetof(struct A, b)); 
    return 0; 
} 

Sin embargo, es posible que pueda emplear algunos trucos para conseguir el desplazamiento desde un binario compilado sin ejecutarlo. Tal vez asigne una variable estática al valor de compensación y encuentre alguna manera de obtener su valor.

Cuestiones relacionadas