2011-10-28 41 views
9

dudo que alguien puede ayudar con esta pregunta por lo siguiente en Erlang's compile documentation:¿Cómo modificar el ensamblaje de Erlang? ¿Hay algún recurso disponible?

Tenga en cuenta que el formato de los archivos de ensamblador no está documentada, y puede cambiar entre versiones - esta opción es principalmente para uso interno de depuración.

... pero por si acaso, aquí va seguimiento de la pila de la historia:

  • de compilación: archivo/2 con [ 'S'] para generar el código de montaje
  • archivo
  • Leer .S y crear una estructura de datos clave-valor con la clave siendo las tuplas 'función' en el archivo .S, y el valor es el cuerpo de la función, es decir, las instrucciones de ensamblaje que implementan la función.
  • Modifica la estructura de datos agregando el conjunto para realizar una llamada de función externa en ciertas funciones.
  • accidente ...

desgracia acabo rápidamente desnatada los archivos .S generados al compilar un módulo que contiene la función siguiente, con y sin la primera expresión de la función comentada:

spawn_worker(Which) -> 
    %syner:sync_pt(), 
    case Which of 
      ?NAIVE -> spawn(err1, naive_worker_loop, []) 
    end. 

Cuando lo hice, pensé que lo único que cambió fue la tupla:

{call_ext, 0, {extfunc, syner, sync_pt, 0}}.

... así que supuse que lo único necesario inyectar una llamada de función en la asamblea fue la de añadir esa n ... pero ahora que llegué a la inyección de la tupla realidad ... estoy viendo que el montaje generado tiene algunas instrucciones adicionales:

Sin syner: sync_pt():

{function, spawn_worker, 1, 4}. 
{label,3}. 
    {func_info,{atom,err1},{atom,spawn_worker},1}. 
{label,4}. 
    {test,is_eq_exact,{f,5},[{x,0},{atom,naive}]}. 
    {move,{atom,naive_worker_loop},{x,1}}. 
    {move,nil,{x,2}}. 
    {move,{atom,err1},{x,0}}. 
    {call_ext_only,3,{extfunc,erlang,spawn,3}}. 
{label,5}. 
    {case_end,{x,0}}. 

Con syner: sync_pt():

{function, spawn_worker, 1, 4}. 
{label,3}. 
    {func_info,{atom,err1},{atom,spawn_worker},1}. 
{label,4}. 
    {allocate,1,1}. 
    {move,{x,0},{y,0}}. 
    {call_ext,0,{extfunc,syner,sync_pt,0}}. 
    {test,is_eq_exact,{f,5},[{y,0},{atom,naive}]}. 
    {move,{atom,naive_worker_loop},{x,1}}. 
    {move,nil,{x,2}}. 
    {move,{atom,err1},{x,0}}. 
    {call_ext_last,3,{extfunc,erlang,spawn,3},1}. 
{label,5}. 
    {case_end,{y,0}}. 

Simplemente no se puede concluir que algo así como la adición:

{allocate,1,1}. 
    {move,{x,0},{y,0}}. 
    {call_ext,0,{extfunc,syner,sync_pt,0}}. 

a cada función Quiero inyectar una llamada a la función externa en, hará el truco.

  1. , porque no estoy seguro de si eso código de montaje se aplica a todas las funciones que quiero para inyectar en (por ejemplo, es {asignar, 1,1} siempre bien)
  2. porque si usted toma una mirada más cercana en el resto del conjunto, cambia ligeramente (por ejemplo, {call_ext_only, 3, {extfunc, erlang, spawn, 3}}. cambios en {call_ext_last, 3, {extfunc, erlang, spawn, 3}, 1 }.).

Así que ahora la pregunta es, ¿hay algún recurso que pueda usar para comprender y manipular el ensamblado generado por la compilación de Erlang: archivo/2?

Estoy haciendo esta pregunta por las dudas. Dudo que haya un recurso para esto, ya que la documentación establece claramente que no existe, pero no tengo nada que perder, supongo. Incluso si hubiera, parece que manipular el código ensamblador va a ser más complicado de lo que me gustaría. Usar parse_transform/2 es definitivamente más fácil, y logré obtener algo similar para trabajar con él ... simplemente probando diferentes alternativas.

Gracias por su tiempo.

+0

(Según las pruebas, no de fuentes de lectura) '' {allocate, 1,1} 'asigna un lugar en la pila y. La pila x es la pila "normal", los registros. La pila y es una pila auxiliar. '{movimiento, {x, 0}, {y, 0}}' mueve la x superior a la más inferior y (al menos cree que crecen en dirección inversa). Mi archivo de prueba: http://pastebin.com/R21ZJ29Q. Su resultado: http://pastebin.com/jULjMCV0. – kay

+0

Gracias por la ayuda kay. Parece que calcular el montaje me tomará demasiado tiempo, así que no estoy planeando descifrarlo. Aclamaciones. – justin

Respuesta

3

la única herramienta que conozco que el uso de t él beam asm es HiPE, hay muchos ejemplos de código y tal en https://github.com/erlang/otp/tree/master/lib/hipe/icode, aunque no recomendaría hacer mucho con este formato ya que está cambiando todo el tiempo.

+1

Punto tomado. Trabajar con la representación de la asamblea es buscar problemas. Aclamaciones. – justin

2

No estoy seguro de qué intenta lograr con esto, pero core erlang podría ser un mejor nivel para manipular código. Esto está documentado (bien uno versión de todas maneras, pero esto es mejor que nada) aquí (y hay más sólo Google para el núcleo Erlang):

Para compilar desde y hacia el uso del núcleo de Erlang 'to_core' y 'from_core' (por desgracia no documentadas) opciones:

c(my_module, to_core). %%this generates my_module.core 
c(my_module, from_core). %%this loads my_module.core 
+1

Creo que core erlang es lo que usa lfe (https://github.com/rvirding/lfe), puede encontrar información útil allí – Lukas

+0

hmm ye, leí rápidamente ese artículo pero no intenté usar core Erlang todavía . Creo que lo investigaré un poco más. Gracias por el puntero TamasNagy. – justin

+0

lfe usa core erlang huh. Genial, una razón más para comprobarlo. Gracias Lukas. – justin

1

Me pareció que lo que está tratando de hacer podría abordarse fácilmente manipulando el código abstracto. Simplemente escriba un módulo parse_transform dentro del cual podría insertar la llamada a la función en las funciones en cuestión.

Escribí un ?funclog basado en el erlang decorators. ver https://github.com/nicoster/erl-decorator-pt#funclog

Cuestiones relacionadas