пятница, 20 сентября 2024 г.

Tracking arguments of functions in gcc

I continuing to improve my gcc plugin for collecting cross-references: 1, 2, 3, 4, 5, 6 & 7. On this week I decided to see if I can extract source of complex types like records and most prominent kind of them is arguments of function - they are easy to identify in asm (but not so easy to bind them in gcc RTL expressions)

Having function declaration fdecl we can extract arguments with something like:

for (tree arg = DECL_ARGUMENTS (fdecl); arg; arg = DECL_CHAIN (arg))
  {
    auto a = DECL_RTL_IF_SET (arg);
    if ( a && REG_EXPR(a) ) { // do something with argument in
REG_EXPR(a)

 
I need only arguments that are a pointer or reference to record/union so I filtered them in method check_arg

Those was easiest part, and now try to find how arguments can be tracked in RTL. 

We can see using of arguments in expression like

insn 7 6 8 2 (set (reg/f:DI 0 ax [orig:82 _1 ] [82])
        (mem/f:DI (plus:DI (reg/f:DI 0 ax [85])
                (const_int 88 [0x58])) [170 this_3(D)->m_outfp+0 S8 A64])) "my_plugin.h":53:14 80 {*movdi_internal}

They come from RTX with type MEM and tree code COMPONENT_REF where left part in TREE_OPERAND (expr, 0) is SSA_NAME (and right part in TREE_OPERAND (expr, 1) in this case is FIELD_DECL)

You can check if SSA has name with SSA_NAME_IDENTIFIER and extract name of SSA with IDENTIFIER_POINTER. But linking just by name is bad idea - you could legally have local variable with the same name as argument, so it's better to extract type with SSA_NAME_VAR

Unfortunately this nice and simple method does not work for cases described in my previous post - we have type info scattered in several RTX:

  • SET REG RMEM without COMPONENT_REF - instead we have nameless SSA_NAME pointing to type of referred field, so we cannot extract type of class and field name
  • EXPR_LIST (seems that it always has index 6) with note (notes can be extracted with GET_MODE) REG_EQUAL containing expression like PLUS MEM CONST_INT where MEM is PARM_DECL but offset is just constant integer

So I couldn't come up with a more elegant solution than:

  1. identify that currently processed RTX has note REG_EQUAL
  2. while processing MEM expression within REG_EQUAL store reference to argument and it's type
  3. and finally while processing CONST_INT check that it has both base type and expression PLUS above in stack and then manually find field at that offset in base type (see method add_fref_from_equal). Value of offset can be extracted with XWINT. Open question is what to do if base type is union - it this case we can have several fields on the same offset
     
Looks very ugly and clumsy but it works - for method append_name it extracted two references to aux_type_clutch.txt from first argument of function

Комментариев нет:

Отправить комментарий