Exemplo n.º 1
0
Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f, Dwarf_P_Die type) {
  Dwarf_Error error = 0;

  /* top level DIE for each function */
  Dwarf_P_Die func = dwarf_new_die(m_dwarfProducer,
    DW_TAG_subprogram, nullptr, nullptr, nullptr, nullptr, &error);
  if (reinterpret_cast<Dwarf_Addr>(func) == DW_DLV_BADADDR) {
    logError("unable to create child DIE");
    return nullptr;
  }

  Dwarf_Signed file;
  FileDB::iterator it = m_fileDB.find(f->file);
  /* if this function is from an unseen file, register file name
   * and get index to file name */
  if (it == m_fileDB.end()) {
    file = dwarf_add_file_decl(m_dwarfProducer,
      (char *)f->file, 0, 0, 1000, &error);
    if (file == DW_DLV_NOCOUNT) {
      logError("unable to add file declaration");
      return nullptr;
    }
    m_fileDB[f->file] = file;
  } else {
    file = it->second;
  }

  /* add function name attribute to function DIE */
  Dwarf_P_Attribute at;
  at = dwarf_add_AT_name(func, (char *)f->name.c_str(), &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add name attribute to function");
    return nullptr;
  }

  /* Add lower PC bound to function DIE */
  at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_low_pc,
    reinterpret_cast<Dwarf_Unsigned>(f->range.begin()), 0, &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add low_pc attribute to function");
    return nullptr;
  }

  /* add upper PC bound to function DIE */
  at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_high_pc,
    reinterpret_cast<Dwarf_Unsigned>(f->range.end()), 0, &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add high_pc attribute to function");
    return nullptr;
  }

  /* register line number information for function:
   * 1. register start address */
  Dwarf_Unsigned u;
  u = dwarf_lne_set_address(m_dwarfProducer,
    reinterpret_cast<Dwarf_Addr>(f->range.begin()), 0, &error);
  if (u != 0) {
    logError("unable to set line start address");
    return nullptr;
  }

  /* 2. register line number info for each tracelet in function */
  std::vector<LineEntry>::iterator it2;
  for (it2 = f->m_lineTable.begin(); it2 != f->m_lineTable.end(); it2++) {
    u = dwarf_add_line_entry(m_dwarfProducer,
      file, reinterpret_cast<Dwarf_Addr>(it2->range.begin()), it2->lineNumber,
      0, 1, 0, &error);
    if (u != 0) {
      logError("unable to add line entry");
      return nullptr;
    }
    TRACE(1, "elfwriter tracelet: %s %p %p\n",
          m_filename.c_str(), it2->range.begin(), it2->range.end());
  }

  /* 3. register end address of function */
  u = dwarf_lne_end_sequence(m_dwarfProducer,
    reinterpret_cast<Dwarf_Addr>(f->range.end()), &error);
  if (u != 0) {
    logError("unable to set line end address");
    return nullptr;
  }

  /* 4. register frame base of function */
  Dwarf_P_Expr locExpr = dwarf_new_expr(m_dwarfProducer, &error);
  if (locExpr == nullptr) {
    logError("unable to create new location expression");
    return nullptr;
  }

  u = dwarf_add_expr_gen(locExpr, DW_OP_call_frame_cfa, 0, 0, &error);
  if (u == DW_DLV_NOCOUNT) {
    logError("unable to add subexpression to location expression");
    return nullptr;
  }

  u = dwarf_add_expr_gen(locExpr, DW_OP_const1u, CFA_OFFSET, 0, &error);
  if (u == DW_DLV_NOCOUNT) {
    logError("unable to add subexpression to location expression");
    return nullptr;
  }

  u = dwarf_add_expr_gen(locExpr, DW_OP_minus, 0, 0, &error);
  if (u == DW_DLV_NOCOUNT) {
    logError("unable to add subexpression to location expression");
    return nullptr;
  }

  Dwarf_P_Attribute frameBaseAttr = dwarf_add_AT_location_expr(m_dwarfProducer,
    func, DW_AT_frame_base, locExpr, &error);
  if (reinterpret_cast<Dwarf_Addr>(frameBaseAttr) == DW_DLV_BADADDR) {
    logError("unable to add frame_base attribute");
    return nullptr;
  }

  /* 5. register all the named locals of function */
  Dwarf_P_Die lastLocal = nullptr;
  int i = 1;
  for (std::vector<std::string>::iterator it = f->m_namedLocals.begin();
       it != f->m_namedLocals.end(); it++) {
    Dwarf_P_Die localVar = dwarf_new_die(m_dwarfProducer,
      DW_TAG_variable, nullptr, nullptr, nullptr, nullptr, &error);
    if (reinterpret_cast<Dwarf_Addr>(localVar) == DW_DLV_BADADDR) {
      logError("unable to create new DIE for local variable");
      return nullptr;
    }

    /* Create location expression defined w.r.t DW_AT_frame_base */
    Dwarf_P_Expr locExpr = dwarf_new_expr(m_dwarfProducer, &error);
    if (locExpr == nullptr) {
      logError("unable to create new location expression");
      return nullptr;
    }

    u = dwarf_add_expr_gen(locExpr, DW_OP_fbreg,
      -(i * sizeof(TypedValue)), 0, &error);
    ++i;
    if (u == DW_DLV_NOCOUNT) {
      logError("unable to add subexpression to location expression");
      return nullptr;
    }

    Dwarf_P_Attribute locAttr = dwarf_add_AT_location_expr(m_dwarfProducer,
      localVar, DW_AT_location, locExpr, &error);
    if (reinterpret_cast<Dwarf_Addr>(locAttr) == DW_DLV_BADADDR) {
      logError("unable to add location attribute to local variable");
      return nullptr;
    }

    Dwarf_P_Attribute nameAttr = dwarf_add_AT_name(localVar, const_cast<char *>(it->data()), &error);
    if (reinterpret_cast<Dwarf_Addr>(nameAttr) == DW_DLV_BADADDR) {
      logError("unable to add name attribute to local variable");
      return nullptr;
    }

    Dwarf_P_Attribute varTypeAttr = dwarf_add_AT_reference(m_dwarfProducer,
      localVar, DW_AT_type, type, &error);
    if (reinterpret_cast<Dwarf_Addr>(varTypeAttr) == DW_DLV_BADADDR) {
      logError("unable to add type attribute to local variable DIE");
      return nullptr;
    }

    Dwarf_P_Die res = 0;
    if (lastLocal != nullptr) {
      res = dwarf_die_link(localVar, nullptr, nullptr, lastLocal, nullptr, &error);
    } else {
      res = dwarf_die_link(localVar, func, nullptr, nullptr, nullptr, &error);
    }
    if (reinterpret_cast<Dwarf_Addr>(res) == DW_DLV_BADADDR) {
      logError("unable to link die");
      return nullptr;
    }
    lastLocal = localVar;
  }

  return func;
}
Exemplo n.º 2
0
Dwarf_P_Die ElfWriter::addFunctionInfo(FunctionInfo* f) {
  Dwarf_Error error = 0;

  /* top level DIE for each function */
  Dwarf_P_Die func = dwarf_new_die(m_dwarfProducer,
    DW_TAG_subprogram, NULL, NULL, NULL, NULL, &error);
  if (reinterpret_cast<Dwarf_Addr>(func) == DW_DLV_BADADDR) {
    logError("unable to create child DIE");
    return NULL;
  }

  Dwarf_Signed file;
  FileDB::iterator it = m_fileDB.find(f->file);
  /* if this function is from an unseen file, register file name
   * and get index to file name */
  if (it == m_fileDB.end()) {
    file = dwarf_add_file_decl(m_dwarfProducer,
      (char *)f->file, 0, 0, 1000, &error);
    if (file == DW_DLV_NOCOUNT) {
      logError("unable to add file declaration");
      return NULL;
    }
    m_fileDB[f->file] = file;
  } else {
    file = it->second;
  }

  /* add function name attribute to function DIE */
  Dwarf_P_Attribute at;
  at = dwarf_add_AT_name(func, (char *)f->name.c_str(), &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add name attribute to function");
    return NULL;
  }

  /* Add lower PC bound to function DIE */
  at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_low_pc,
    reinterpret_cast<Dwarf_Unsigned>(f->range.begin()), 0, &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add low_pc attribute to function");
    return NULL;
  }

  /* add upper PC bound to function DIE */
  at = dwarf_add_AT_targ_address(m_dwarfProducer, func, DW_AT_high_pc,
    reinterpret_cast<Dwarf_Unsigned>(f->range.end()), 0, &error);
  if (reinterpret_cast<Dwarf_Addr>(at) == DW_DLV_BADADDR) {
    logError("unable to add high_pc attribute to function");
    return NULL;
  }

  /* register line number information for function:
   * 1. register start address */
  Dwarf_Unsigned u;
  u = dwarf_lne_set_address(m_dwarfProducer,
    reinterpret_cast<Dwarf_Addr>(f->range.begin()), 0, &error);
  if (u != 0) {
    logError("unable to set line start address");
    return NULL;
  }

  /* 2. register line number info for each tracelet in function */
  std::vector<LineEntry>::iterator it2;
  for (it2 = f->m_lineTable.begin(); it2 != f->m_lineTable.end(); it2++) {
    u = dwarf_add_line_entry(m_dwarfProducer,
      file, reinterpret_cast<Dwarf_Addr>(it2->range.begin()), it2->lineNumber,
      0, 1, 0, &error);
    if (u != 0) {
      logError("unable to add line entry");
      return NULL;
    }
    TRACE(1, "elfwriter tracelet: %s %p %p\n",
          m_filename.c_str(), it2->range.begin(), it2->range.end());
  }

  /* 3. register end address of function */
  u = dwarf_lne_end_sequence(m_dwarfProducer,
    reinterpret_cast<Dwarf_Addr>(f->range.end()), &error);
  if (u != 0) {
    logError("unable to set line end address");
    return NULL;
  }
  return func;
}