checkdescriptor.cc checkdescriptor.hh checkdescriptor.ii \
checkrule.cc checkrule.hh \
dwarflint.cc dwarflint.hh dwarflint.ii misc.h \
- low.c low.h \
+ low.c low.h elf_file.ii \
expected-at.cc expected.hh \
coverage.cc coverage.h \
readctx.c readctx.h \
--- /dev/null
+struct sec;
+struct elf_file;
+struct abbrev_table;
+struct cu;
return retval;
}
-
-void
-check_range_relocations (enum message_category cat,
- struct where *where,
- struct elf_file const *file,
- GElf_Sym *begin_symbol,
- GElf_Sym *end_symbol,
- const char *description)
-{
- if (begin_symbol != NULL
- && end_symbol != NULL
- && begin_symbol->st_shndx != end_symbol->st_shndx)
- wr_message (cat | mc_impact_2 | mc_reloc, where,
- ": %s relocated against different sections (%s and %s).\n",
- description,
- file->sec[begin_symbol->st_shndx].name,
- file->sec[end_symbol->st_shndx].name);
-}
-
-static GElf_Rela *
-get_rel_or_rela (Elf_Data *data, int ndx,
- GElf_Rela *dst, size_t type)
-{
- if (type == SHT_RELA)
- return gelf_getrela (data, ndx, dst);
- else
- {
- assert (type == SHT_REL);
- GElf_Rel rel_mem;
- if (gelf_getrel (data, ndx, &rel_mem) == NULL)
- return NULL;
- dst->r_offset = rel_mem.r_offset;
- dst->r_info = rel_mem.r_info;
- dst->r_addend = 0;
- return dst;
- }
-}
-
-bool
-read_rel (struct elf_file *file,
- struct sec *sec,
- Elf_Data *reldata,
- bool elf_64)
-{
- assert (sec->rel.type == SHT_REL
- || sec->rel.type == SHT_RELA);
- bool is_rela = sec->rel.type == SHT_RELA;
-
- struct read_ctx ctx;
- read_ctx_init (&ctx, sec->data, file->other_byte_order);
-
- size_t entrysize
- = elf_64
- ? (is_rela ? sizeof (Elf64_Rela) : sizeof (Elf64_Rel))
- : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
- size_t count = reldata->d_size / entrysize;
-
- struct where parent = WHERE (sec->id, NULL);
- struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
- where.ref = &parent;
-
- for (unsigned i = 0; i < count; ++i)
- {
- where_reset_1 (&where, i);
-
- REALLOC (&sec->rel, rel);
- struct relocation *cur = sec->rel.rel + sec->rel.size++;
- WIPE (*cur);
-
- GElf_Rela rela_mem, *rela
- = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
- if (rela == NULL)
- {
- wr_error (&where, ": couldn't read relocation.\n");
- skip:
- cur->invalid = true;
- continue;
- }
-
- int cur_type = GELF_R_TYPE (rela->r_info);
- if (cur_type == 0) /* No relocation. */
- {
- wr_message (mc_impact_3 | mc_reloc | mc_acc_bloat, &where,
- ": NONE relocation is superfluous.\n");
- goto skip;
- }
-
- cur->offset = rela->r_offset;
- cur->symndx = GELF_R_SYM (rela->r_info);
- cur->type = cur_type;
-
- where_reset_2 (&where, cur->offset);
-
- Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
- int width;
-
- switch (type)
- {
- case ELF_T_WORD:
- case ELF_T_SWORD:
- width = 4;
- break;
-
- case ELF_T_XWORD:
- case ELF_T_SXWORD:
- width = 8;
- break;
-
- case ELF_T_BYTE:
- case ELF_T_HALF:
- /* Technically legal, but never used. Better have dwarflint
- flag them as erroneous, because it's more likely these
- are a result of a bug than actually being used. */
- {
- char buf[64];
- wr_error (&where, ": 8 or 16-bit relocation type %s.\n",
- ebl_reloc_type_name (file->ebl, cur->type,
- buf, sizeof (buf)));
- goto skip;
- }
-
- default:
- {
- char buf[64];
- wr_error (&where, ": invalid relocation %d (%s).\n",
- cur->type,
- ebl_reloc_type_name (file->ebl, cur->type,
- buf, sizeof (buf)));
- goto skip;
- }
- };
-
- if (cur->offset + width >= sec->data->d_size)
- {
- wr_error (&where,
- ": relocation doesn't fall into relocated section.\n");
- goto skip;
- }
-
- uint64_t value;
- if (width == 4)
- value = dwarflint_read_4ubyte_unaligned
- (sec->data->d_buf + cur->offset, file->other_byte_order);
- else
- {
- assert (width == 8);
- value = dwarflint_read_8ubyte_unaligned
- (sec->data->d_buf + cur->offset, file->other_byte_order);
- }
-
- if (is_rela)
- {
- if (value != 0)
- wr_message (mc_impact_2 | mc_reloc, &where,
- ": SHR_RELA relocates a place with non-zero value (addend=%#"
- PRIx64", value=%#"PRIx64").\n", rela->r_addend, value);
- cur->addend = rela->r_addend;
- }
- else
- cur->addend = value;
- }
-
- /* Sort the reloc section so that the applicable addresses of
- relocation entries are monotonously increasing. */
- int compare (const void *a, const void *b)
- {
- return ((struct relocation *)a)->offset
- - ((struct relocation *)b)->offset;
- }
-
- qsort (sec->rel.rel, sec->rel.size,
- sizeof (*sec->rel.rel), &compare);
- return true;
-}
// xxx some of that will go away
extern struct abbrev *abbrev_table_find_abbrev (struct abbrev_table const *abbrevs,
uint64_t abbrev_code);
- extern bool read_rel (struct elf_file *file, struct sec *sec,
- Elf_Data *reldata, bool elf_64);
extern bool address_aligned (uint64_t addr, uint64_t align);
extern bool necessary_alignment (uint64_t start, uint64_t length,
uint64_t align);
};
// xxx low-level check entry points, will go away
- struct cu;
- extern void check_range_relocations (enum message_category cat,
- struct where *where,
- struct elf_file const *file,
- GElf_Sym *begin_symbol,
- GElf_Sym *end_symbol,
- const char *description);
extern int check_sibling_form (dwarf_version_h ver, uint64_t form);
extern bool is_location_attrib (uint64_t name);
Network licensing program, please visit www.openinventionnetwork.com
<http://www.openinventionnetwork.com>. */
+// xxx drop as soon as not necessary
+#define __STDC_FORMAT_MACROS
+
#include "reloc.h"
#include "messages.h"
#include "low.h"
#include <sstream>
#include <libebl.h>
#include <cassert>
+#include <inttypes.h>
static struct where
where_from_reloc (struct relocation_data *reloc, struct where const *ref)
}
}
}
+
+static GElf_Rela *
+get_rel_or_rela (Elf_Data *data, int ndx,
+ GElf_Rela *dst, size_t type)
+{
+ if (type == SHT_RELA)
+ return gelf_getrela (data, ndx, dst);
+ else
+ {
+ assert (type == SHT_REL);
+ GElf_Rel rel_mem;
+ if (gelf_getrel (data, ndx, &rel_mem) == NULL)
+ return NULL;
+ dst->r_offset = rel_mem.r_offset;
+ dst->r_info = rel_mem.r_info;
+ dst->r_addend = 0;
+ return dst;
+ }
+}
+
+/* Sort the reloc section so that the applicable addresses of
+ relocation entries are monotonously increasing. */
+static int
+compare_rel (const void *a, const void *b)
+{
+ return ((struct relocation *)a)->offset
+ - ((struct relocation *)b)->offset;
+}
+
+bool
+read_rel (struct elf_file *file,
+ struct sec *sec,
+ Elf_Data *reldata,
+ bool elf_64)
+{
+ assert (sec->rel.type == SHT_REL
+ || sec->rel.type == SHT_RELA);
+ bool is_rela = sec->rel.type == SHT_RELA;
+
+ struct read_ctx ctx;
+ read_ctx_init (&ctx, sec->data, file->other_byte_order);
+
+ size_t entrysize
+ = elf_64
+ ? (is_rela ? sizeof (Elf64_Rela) : sizeof (Elf64_Rel))
+ : (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
+ size_t count = reldata->d_size / entrysize;
+
+ struct where parent = WHERE (sec->id, NULL);
+ struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
+ where.ref = &parent;
+
+ for (unsigned i = 0; i < count; ++i)
+ {
+ where_reset_1 (&where, i);
+
+ REALLOC (&sec->rel, rel);
+ struct relocation *cur = sec->rel.rel + sec->rel.size++;
+ WIPE (*cur);
+
+ GElf_Rela rela_mem, *rela
+ = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
+ if (rela == NULL)
+ {
+ wr_error (&where, ": couldn't read relocation.\n");
+ skip:
+ cur->invalid = true;
+ continue;
+ }
+
+ int cur_type = GELF_R_TYPE (rela->r_info);
+ if (cur_type == 0) /* No relocation. */
+ {
+ wr_message (mc_impact_3 | mc_reloc | mc_acc_bloat, &where,
+ ": NONE relocation is superfluous.\n");
+ goto skip;
+ }
+
+ cur->offset = rela->r_offset;
+ cur->symndx = GELF_R_SYM (rela->r_info);
+ cur->type = cur_type;
+
+ where_reset_2 (&where, cur->offset);
+
+ Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
+ int width;
+
+ switch (type)
+ {
+ case ELF_T_WORD:
+ case ELF_T_SWORD:
+ width = 4;
+ break;
+
+ case ELF_T_XWORD:
+ case ELF_T_SXWORD:
+ width = 8;
+ break;
+
+ case ELF_T_BYTE:
+ case ELF_T_HALF:
+ /* Technically legal, but never used. Better have dwarflint
+ flag them as erroneous, because it's more likely these
+ are a result of a bug than actually being used. */
+ {
+ char buf[64];
+ wr_error (&where, ": 8 or 16-bit relocation type %s.\n",
+ ebl_reloc_type_name (file->ebl, cur->type,
+ buf, sizeof (buf)));
+ goto skip;
+ }
+
+ default:
+ {
+ char buf[64];
+ wr_error (&where, ": invalid relocation %d (%s).\n",
+ cur->type,
+ ebl_reloc_type_name (file->ebl, cur->type,
+ buf, sizeof (buf)));
+ goto skip;
+ }
+ };
+
+ if (cur->offset + width >= sec->data->d_size)
+ {
+ wr_error (&where,
+ ": relocation doesn't fall into relocated section.\n");
+ goto skip;
+ }
+
+ uint64_t value;
+ if (width == 4)
+ value = dwarflint_read_4ubyte_unaligned
+ ((char *)sec->data->d_buf + cur->offset, file->other_byte_order);
+ else
+ {
+ assert (width == 8);
+ value = dwarflint_read_8ubyte_unaligned
+ ((char *)sec->data->d_buf + cur->offset, file->other_byte_order);
+ }
+
+ if (is_rela)
+ {
+ if (value != 0)
+ wr_message (mc_impact_2 | mc_reloc, &where,
+ ": SHR_RELA relocates a place with non-zero value (addend=%#"
+ PRIx64", value=%#"PRIx64").\n", rela->r_addend, value);
+ cur->addend = rela->r_addend;
+ }
+ else
+ cur->addend = value;
+ }
+
+ qsort (sec->rel.rel, sec->rel.size,
+ sizeof (*sec->rel.rel), &compare_rel);
+ return true;
+}
+
+void
+check_range_relocations (enum message_category cat,
+ struct where *where,
+ struct elf_file const *file,
+ GElf_Sym *begin_symbol,
+ GElf_Sym *end_symbol,
+ const char *description)
+{
+ if (begin_symbol != NULL
+ && end_symbol != NULL
+ && begin_symbol->st_shndx != end_symbol->st_shndx)
+ wr_message (cat | mc_impact_2 | mc_reloc, where,
+ ": %s relocated against different sections (%s and %s).\n",
+ description,
+ file->sec[begin_symbol->st_shndx].name,
+ file->sec[end_symbol->st_shndx].name);
+}
/* Pedantic checking of DWARF files.
- Copyright (C) 2008,2009 Red Hat, Inc.
+ Copyright (C) 2008, 2009, 2010 Red Hat, Inc.
This file is part of Red Hat elfutils.
Red Hat elfutils is free software; you can redistribute it and/or modify
#define DWARFLINT_RELOC_H
#include "where.h"
+#include "elf_file.ii"
#include <libelf.h>
#include <gelf.h>
+// xxx remove
+#include "messages.h"
+
#ifdef __cplusplus
extern "C"
{
# include <stdbool.h>
#endif
- struct elf_file;
-
struct relocation
{
uint64_t offset;
skip_ok,
};
+ bool read_rel (struct elf_file *file, struct sec *sec,
+ Elf_Data *reldata, bool elf_64);
+
struct relocation *relocation_next (struct relocation_data *reloc,
uint64_t offset,
struct where const *where,
struct where const *where,
enum section_id offset_into, GElf_Sym **symptr);
+ void check_range_relocations (enum message_category cat,
+ struct where *where,
+ struct elf_file const *file,
+ GElf_Sym *begin_symbol,
+ GElf_Sym *end_symbol,
+ const char *description);
+
#define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
#ifdef __cplusplus