GrammaTech / gtirb-rewriting

Python API for rewriting GTIRB files
GNU General Public License v3.0
16 stars 3 forks source link

Align data added by patch #7

Open avncharlie opened 1 year ago

avncharlie commented 1 year ago

Hello, I'm trying to align data added by my patch using the .align and .balign directives. I'm having no luck with this and I'm wondering if it is because I'm using the directives incorrectly or if it isn't implemented to be used within patches. I'm currently manually adding bytes to the data added to the patch to make sure it is aligned.

Thanks, Alvin

jranieri-grammatech commented 1 year ago

At a minimum, the .align directive is supported (implemented here). Manually adding bytes is going to be more problematic, since you don't necessarily know the alignment of the code once it's been re-assembled without .align directives (e.g. you're inserting your patch into a block that's 4-byte aligned, you add manual padding based off of the block addresses, and then the pretty-printer does relayout and it now falls on a different 4-byte aligned address).

Could you attach an example?

avncharlie commented 1 year ago

In the example below, I'm trying to align the string to 16-byte alignment:

context.register_insert_function(
    'test_alignment_func',
    Patch.from_function(lambda _: '''
    nop

    .rodata
    .TEST_STRING:
        .string "TEST STRING"
        .align 4
    ''', Constraints(x86_syntax=X86Syntax.INTEL))
)

This doesn't seem to work. I've also tried moving the .align to before the added data and that doesn't do anything differently either.

jranieri-grammatech commented 1 year ago

In the example below, I'm trying to align the string to 16-byte alignment:

context.register_insert_function(
    'test_alignment_func',
    Patch.from_function(lambda _: '''
    nop

    .rodata
    .TEST_STRING:
        .string "TEST STRING"
        .align 4
    ''', Constraints(x86_syntax=X86Syntax.INTEL))
)

This doesn't seem to work. I've also tried moving the .align to before the added data and that doesn't do anything differently either.

Try this:

context.register_insert_function(
    'test_alignment_func',
    Patch.from_function(lambda _: '''
    nop

    .rodata
    .p2align 4
    .TEST_STRING:
        .string "TEST STRING"
    ''', Constraints(x86_syntax=X86Syntax.INTEL))
)

It's untested and if it doesn't work, I can dig a bit deeper to see what's going on.

avncharlie commented 1 year ago

That doesn't seem to work either unfortunately

jranieri-grammatech commented 1 year ago

I tested out the patch I mentioned, with the full program being:

import gtirb_rewriting.driver
from gtirb_rewriting import *

class MyPass(Pass):
  def begin_module(self, module, functions, rewriting_ctx) -> None:
    rewriting_ctx.register_insert_function(
      'test_alignment_func',
      Patch.from_function(lambda _: '''
        nop

        .rodata
        .p2align 4
        .TEST_STRING:
            .string "TEST STRING"
        ''', Constraints(x86_syntax=X86Syntax.INTEL))
    )

if __name__ == "__main__":
    gtirb_rewriting.driver.main(MyPass)

In the output assembly from gtirb-pprinter, I see this:

#===================================
.section .rodata ,"a",@progbits
#===================================

.align 16
.TEST_STRING:
          .string "TEST STRING"

and further down in the file I see this:

#===================================
.text
#===================================

.align 16
#-----------------------------------
.globl test_alignment_func
.type test_alignment_func, @function
#-----------------------------------
test_alignment_func:

            nop

Are you seeing some other behavior?

avncharlie commented 1 year ago

Apologies, I realise my issue is that I would like to align my added data as a whole, not within itself or at the beginning.

I tested this program below:

import gtirb_rewriting.driver
from gtirb_rewriting import *

class MyPass(Pass):
  def begin_module(self, module, functions, rewriting_ctx) -> None:
    rewriting_ctx.register_insert_function(
      'test_alignment_func',
      Patch.from_function(lambda _: '''
        nop

        .rodata
        .TEST_STRING:
            .string "TEST STRING"
            .align 16
        ''', Constraints(x86_syntax=X86Syntax.INTEL))
    )

if __name__ == "__main__":
    gtirb_rewriting.driver.main(MyPass)

The generated assembly contains this:

#===================================
.section .rodata ,"a",@progbits
#===================================

.align 16
.TEST_STRING:
          .string "TEST STRING"

I would like it to output this:

#===================================
.section .rodata ,"a",@progbits
#===================================

.TEST_STRING:
          .string "TEST STRING"
.align 16

Is there any way to do this? Thanks for the help