예제 #1
0
파일: dwarf_loclist.c 프로젝트: 0mp/freebsd
int
dwarf_loclist(Dwarf_Attribute at, Dwarf_Locdesc **llbuf,
    Dwarf_Signed *listlen, Dwarf_Error *error)
{
	Dwarf_Locdesc **_llbuf;
	int i, ret;

	ret = dwarf_loclist_n(at, &_llbuf, listlen, error);
	if (ret != DW_DLV_OK)
		return (ret);

	/* Only return the first location description of the list. */
	*llbuf = _llbuf[0];

	/* Free the rest of the list. */
	for (i = 1; i < *listlen; i++) {
		if (_llbuf[i]->ld_s)
			free(_llbuf[i]->ld_s);
		free(_llbuf[i]);
	}
	free(_llbuf);

	*listlen = 1;

	return (DW_DLV_OK);
}
Dwarf_Loc dwarf_get_variable_location(Dwarf_Die die, struct dwarf_compilation_unit * unit){
  
  Dwarf_Error error = 0;
  Dwarf_Attribute *attrbuf = 0;
  Dwarf_Signed attrcount = 0;
  Dwarf_Unsigned i;
  Dwarf_Locdesc *llbuf = 0;
  Dwarf_Locdesc **llbufarray = 0;
  Dwarf_Signed no_of_elements;
  int lres = 0;
  Dwarf_Loc first_loc;

  int res = dwarf_attrlist(die,&attrbuf,&attrcount,&error);
  if(res != DW_DLV_OK) {
    return first_loc;
  }
  for(i = 0; i < attrcount ; ++i) {
    Dwarf_Half aform;
    res = dwarf_whatattr(attrbuf[i],&aform,&error);
    if(aform == DW_AT_location) {
      lres = dwarf_loclist_n(attrbuf[i], &llbufarray, &no_of_elements, &error);
      if (llbufarray[0]->ld_s){
        first_loc = (llbufarray[0]->ld_s)[0];
	return first_loc;
      }
    }
  }
  return first_loc;
}
예제 #3
0
bool DieHolder::get_operand(int const attr, ea_t const rel_addr, Dwarf_Small const atom,
                            Dwarf_Unsigned *operand, bool only_locblock)
{
  Dwarf_Attribute attrib = get_attr(attr);
  Dwarf_Locdesc **llbuf = NULL;
  Dwarf_Locdesc *locdesc = NULL;
  Dwarf_Signed count = 0;
  Dwarf_Error err = NULL;
  DwarfDealloc dealloc(m_dbg);
  bool found = false;
  bool ret = false;

  CHECK_DWERR2(attrib == NULL, NULL,
               "retrieving an operand implies finding the attribute...");

  CHECK_DWERR(dwarf_loclist_n(attrib, &llbuf, &count, &err), err,
              "cannot get location descriptions");

  dealloc.add(llbuf, DW_DLA_LIST);
  for(Dwarf_Signed idx = 0; idx < count; ++idx)
  {
    locdesc = llbuf[idx];
    // handle deallocation too
    dealloc.add(llbuf[idx], DW_DLA_LOCDESC);
    dealloc.add(llbuf[idx]->ld_s, DW_DLA_LOC_BLOCK);

    if(!found)
    {
      // from a location block?
      if(!locdesc->ld_from_loclist)
      {
        // no need to check the address
        found = true;
      }
      // this loc desc is from a location list
      else if(!only_locblock &&
              (locdesc->ld_lopc <= rel_addr &&
               locdesc->ld_hipc > rel_addr))
      {
        found = true;
      }
    }
  }

  if(found)
  {
    CHECK_DWERR2(locdesc->ld_cents != 1, NULL,
                 "only 1 location in a location description is supported");

    Dwarf_Loc *loc = &locdesc->ld_s[0];

    if(loc->lr_atom == atom)
    {
      *operand = loc->lr_number;
      ret = true;
    }
  }

  return ret;
}
예제 #4
0
void DieHolder::get_frame_base_offsets(OffsetAreas &offset_areas)
{
  Dwarf_Attribute attrib = get_attr(DW_AT_frame_base);
  Dwarf_Locdesc **llbuf = NULL;
  Dwarf_Locdesc *locdesc = NULL;
  Dwarf_Signed count = 0;
  Dwarf_Error err = NULL;
  DwarfDealloc dealloc(m_dbg);

  CHECK_DWERR2(attrib == NULL, NULL,
               "retrieving an operand implies finding the attribute...");

  CHECK_DWERR(dwarf_loclist_n(attrib, &llbuf, &count, &err), err,
              "cannot get location descriptions");

  dealloc.add(llbuf, DW_DLA_LIST);
  for(Dwarf_Signed idx = 0; idx < count; ++idx)
  {
    ea_t low_pc = 0;
    ea_t high_pc = 0;

    locdesc = llbuf[idx];
    // handle deallocation too
    dealloc.add(llbuf[idx], DW_DLA_LOCDESC);
    dealloc.add(llbuf[idx]->ld_s, DW_DLA_LOC_BLOCK);

    // only 1 location in a location description is supported
    if(locdesc->ld_cents == 1)
    {
      Dwarf_Loc *loc = &locdesc->ld_s[0];
      Dwarf_Small const atom = loc->lr_atom;

      // from a location block?
      if(!locdesc->ld_from_loclist)
      {
        low_pc = BADADDR;
        high_pc = BADADDR;
      }
      // this loc desc is from a location list
      else
      {
        low_pc = static_cast<ea_t>(locdesc->ld_lopc);
        high_pc = static_cast<ea_t>(locdesc->ld_hipc);
      }

      // is it the right atom to get the offset from?
      if(atom == DW_OP_breg4 || atom == DW_OP_breg5)
      {
        offset_areas.push_back(OffsetArea(low_pc, high_pc,
                                          // operand is unsigned, but should be signed...
                                          static_cast<sval_t>(loc->lr_number),
                                          (atom == DW_OP_breg5)));
      }
    }
  }
}
예제 #5
0
void DieHolder::retrieve_var(func_t *funptr, ea_t const cu_low_pc,
                             OffsetAreas const &offset_areas, func_type_info_t *info,
                             var_visitor_fun visit)
{
  Dwarf_Attribute attrib = get_attr(DW_AT_location);

  if(attrib != NULL)
  {
    Dwarf_Locdesc **llbuf = NULL;
    Dwarf_Locdesc *locdesc = NULL;
    Dwarf_Signed count = 0;
    Dwarf_Error err = NULL;
    DwarfDealloc dealloc(m_dbg);
    size_t const nb_args = (info == NULL) ? 0 : info->size();

    CHECK_DWERR(dwarf_loclist_n(attrib, &llbuf, &count, &err), err,
                "cannot get location descriptions");

    dealloc.add(llbuf, DW_DLA_LIST);
    for(Dwarf_Signed idx = 0; idx < count; ++idx)
    {
      locdesc = llbuf[idx];
      // handle deallocation too
      dealloc.add(llbuf[idx], DW_DLA_LOCDESC);
      dealloc.add(llbuf[idx]->ld_s, DW_DLA_LOC_BLOCK);

      visit(*this, locdesc, funptr, cu_low_pc, offset_areas, info);

      if(info != NULL && info->size() != nb_args)
      {
        // parameter has already been added, do not add it twice!
        info = NULL;
      }
    }
  }
}