blob: eda9fd971cd43f28286915b99a72ccae9ac419fa [file] [log] [blame]
/* Pedantic checking of DWARF files.
Copyright (C) 2008, 2009, 2010, 2011 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
elfutils is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#ifndef DWARFLINT_RELOC_H
#define DWARFLINT_RELOC_H
#include "locus.hh"
#include "elf_file_i.hh"
#include <libelf.h>
#include <gelf.h>
struct relocation
{
uint64_t offset;
uint64_t addend;
int symndx;
int type;
bool invalid; /* Whether this one relocation should be
ignored. Necessary so that we don't report
invalid & missing relocation twice. */
relocation ()
: offset (0)
, addend (0)
, symndx (0)
, type (0)
, invalid (false)
{}
};
struct relocation_data
{
Elf_Data *symdata; /* Symbol table associated with this
relocation section. */
size_t type; /* SHT_REL or SHT_RELA. */
struct relocation *rel; /* Array of relocations. May be NULL if
there are no associated relocation
data. */
size_t size;
size_t alloc;
size_t index; /* Current index. */
relocation_data ()
: symdata (NULL)
, type (SHT_NULL)
, rel (NULL)
, size (0)
, alloc (0)
, index (0)
{}
};
enum skip_type
{
skip_unref = 0,
skip_mismatched = 1,
skip_ok,
};
struct rel_target
{
enum target
{
rel_value, /* For relocations, this denotes that the
relocation is applied to target value, not a
section offset. */
rel_address, /* Same as above, but for addresses. */
rel_exec, /* Some as above, but we expect EXEC bit. */
};
private:
bool _m_is_section;
union
{
section_id _m_section;
target _m_target;
};
public:
rel_target (section_id sec)
: _m_is_section (true)
, _m_section (sec)
{}
rel_target (target t)
: _m_is_section (false)
, _m_target (t)
{}
bool
operator== (section_id sec)
{
return _m_is_section && _m_section == sec;
}
bool
operator== (target tgt)
{
return !_m_is_section && _m_target == tgt;
}
template<class T>
bool
operator!= (T t)
{
return !(*this == t);
}
};
bool read_rel (struct elf_file *file, struct sec *sec,
Elf_Data *reldata, bool elf_64);
relocation *relocation_next (struct relocation_data *reloc,
uint64_t offset,
locus const &loc,
enum skip_type st);
void relocation_reset (struct relocation_data *reloc);
void relocation_skip (struct relocation_data *reloc, uint64_t offset,
locus const &loc, enum skip_type st);
void relocation_skip_rest (struct relocation_data *reloc,
locus const &loc);
void relocate_one (struct elf_file const *file,
struct relocation_data *reloc,
struct relocation *rel,
unsigned width, uint64_t *value,
locus const &loc,
rel_target reltgt,
GElf_Sym **symptr);
#define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
#endif//DWARFLINT_RELOC_H