Quantcast
Channel: windows deep internals
Viewing all articles
Browse latest Browse all 264

custom attributes in gcc and dwarf

$
0
0

Lets check if we can add our own attributes (if Google can afford it, then why is it forbidden to mere mortals?). For example I want to have in gcc and dwarf flag about functions/methods parameters direction - is some param IN or OUT. I chose the value of this dwarf attribure 0x28ff

It`s pretty obviously that we can add our own custom attribute in gcc - they even have example how to do this. But what about dwarf producer? Long story short - seems that you cannot do it from plugin. The only dwarf related pass for plugins is pass_dwarf2_frame. So we need to patch gcc. But before this we need to 

build gcc from sources

At moment of writing latest stable version of gcc was 12.0 so run 

git clone --branch releases/gcc-12 https://github.com/gcc-mirror/gcc.git

and then follows instructions

patch gcc

Lets see how gcc produces dwarf output. All symbol table formatters implement gcc_debug_hooks and currently gcc has 3 (btw there are patches for mingw to produce PDB, so in theory you could have vmlinux.pdb):

so lets add function add_param_direction in dwarf2out.cc:
bool add_param_direction(tree decl, dw_die_ref parm_die)
{
  bool pa1 = lookup_attribute ("param_in", DECL_ATTRIBUTES (decl));
  bool pa2 = lookup_attribute ("param_out", DECL_ATTRIBUTES (decl));
  if ( !(pa1 ^ pa2) )
    return false;
  unsigned char pa_value = 0;
  // seems that you can`t have flag with value 1 - see gcc_assert at line 9599
  if ( pa1 )
    pa_value = 2;
  if ( pa2 )
    pa_value = 3;
  add_AT_flag(parm_die, (dwarf_attribute)0x28ff, pa_value);
  return true;
}
It first checks if parameter has attribute param_in or param_out (but not both at the same time bcs this is senseless) and adds custom dwarf flag attribute via add_AT_flag call. Then we just need to call this function from gen_formal_parameter_die
 
Now we can add our custom attributes- this can be done via plugin but I preferred to patch c-family/c-attribs.cc:
 
tree handle_param_in_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                         int ARG_UNUSED(flags), bool *no_add_attrs)
{
  if ( !DECL_P (*node) )
  {
    warning (OPT_Wattributes, "%qE attribute can apply to params declarations only", name);
    *no_add_attrs = true;
    return NULL_TREE;
  }
  tree decl = *node;
  if (TREE_CODE (decl) != PARM_DECL)
  {
    warning (OPT_Wattributes, "%qE attribute can apply to params only", name);
    *no_add_attrs = true;
  } else {
    // check presense of param_out
    if ( lookup_attribute ("param_out", DECL_ATTRIBUTES (decl)) )
    {
      warning (OPT_Wattributes, "%qE attribute useless when param_out was used", name);
      *no_add_attrs = true;
      DECL_ATTRIBUTES (decl) = remove_attribute("param_out", DECL_ATTRIBUTES (decl));
    }
  }
  return NULL_TREE;
}

Function handle_param_in_attribute checks that this attribute linked with function/method parameter. Then it checks that the same parameter don`t have attribute param_out - in this case it just removes both
 
All patches located here 

results

Lets define couple of new keywords:

#define IN    __attribute__((param_in))
#define OUT    __attribute__((param_out))

and mark some arguments as IN or OUT - for example for method bool PlainRender::dump_type(uint64_t key, OUT std::string &res, named *n, int level)

After rebuilding of debug version with our patched gcc we can see in objdump output something like this

<1><10d8ac>: Abbrev Number: 18 (DW_TAG_subprogram)
    <10d8ad>   DW_AT_specification: <0x103579>
    <10d8b1>   DW_AT_object_pointer: <0x10d8cc>
    <10d8b5>   DW_AT_low_pc      : 0x4301a6
    <10d8bd>   DW_AT_high_pc     : 0x4317e7
    <10d8c5>   DW_AT_frame_base  : 1 byte block: 9c     (DW_OP_call_frame_cfa)
    <10d8c7>   DW_AT_GNU_all_tail_call_sites: 1
    <10d8c8>   DW_AT_sibling     : <0x10db29>
 <2><10d8cc>: Abbrev Number: 10 (DW_TAG_formal_parameter)
    <10d8cd>   DW_AT_name        : (indirect string, offset: 0x107d3): this
    <10d8d1>   DW_AT_type        : <0x1035e5>
    <10d8d5>   DW_AT_artificial  : 1
    <10d8d6>   DW_AT_location    : 3 byte block: 91 98 7c       (DW_OP_fbreg: -488)
 <2><10d8da>: Abbrev Number: 45 (DW_TAG_formal_parameter)
    <10d8db>   DW_AT_name        : key
    <10d8df>   DW_AT_decl_file   : 1
    <10d8e0>   DW_AT_decl_line   : 123
    <10d8e1>   DW_AT_decl_column : 38
    <10d8e2>   DW_AT_type        : <0xfb4be>
    <10d8e6>   DW_AT_location    : 3 byte block: 91 90 7c       (DW_OP_fbreg: -496)
 <2><10d8ea>: Abbrev Number: 234 (DW_TAG_formal_parameter)
    <10d8ec>   Unknown AT value: 28ff: 3
    <10d8ed>   DW_AT_name        : res


Viewing all articles
Browse latest Browse all 264

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>