#include <unistd.h>
#include "../libdw/dwarf.h"
-#include "../libdw/libdwP.h"
#include "../libdw/known-dwarf.h"
#include "../libebl/libebl.h"
#include "dwarfstrings.h"
#include "dwarflint.h"
+#include "dwarflint-readctx.h"
/* Bug report address. */
const char *argp_program_bug_address = PACKAGE_BUGREPORT;
/* If true, we accept silently files without debuginfo. */
static bool tolerate_nodebug = false;
-static void process_file (Dwarf *dwarf, const char *fname, bool only_one);
+static void process_file (Elf *elf, const char *fname, bool only_one);
struct message_term
{
if (layout_rel_file (elf))
goto invalid_elf;
- Dwarf *dwarf = dwarf_begin_elf (elf, DWARF_C_READ, NULL);
- if (dwarf == NULL)
- {
- if (!tolerate_nodebug)
- wr_error (NULL,
- gettext ("cannot generate Dwarf descriptor: %s\n"),
- dwarf_errmsg (-1));
- }
- else
- {
- process_file (dwarf, argv[remaining], only_one);
-
- if (dwarf_end (dwarf) != 0)
- wr_error (NULL,
- gettext ("error while closing Dwarf descriptor: %s\n"),
- dwarf_errmsg (-1));
- }
+ process_file (elf, argv[remaining], only_one);
- if (elf_end (elf) != 0)
+ elf_errno (); /* Clear errno. */
+ elf_end (elf);
+ int err = elf_errno ();
+ if (err != 0)
wr_error (NULL,
gettext ("error while closing Elf descriptor: %s\n"),
- elf_errmsg (-1));
+ elf_errmsg (err));
if (prev_error_count == error_count && !be_quiet)
puts (gettext ("No errors"));
#define PRI_NOT_ENOUGH ": not enough data for %s.\n"
#define PRI_LACK_RELOCATION ": %s seems to lack a relocation.\n"
-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
- double-report invalid & missing
- relocation. */
-};
-
-struct relocation_data
-{
- struct elf_file *file;
- 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. */
-};
-
-struct section_data
-{
- struct elf_file *file;
- size_t secndx; /* Index into file->sec. */
- Elf_Data *data;
- struct relocation_data rel;
-};
-
-static struct sec *
-data_get_sec (struct section_data *data)
-{
- return data->file->sec + data->secndx;
-}
-
-/* Functions and data structures related to bounds-checked
- reading. */
-
-struct read_ctx
-{
- Dwarf *dbg;
- Elf_Data *data;
- const unsigned char *ptr;
- const unsigned char *begin;
- const unsigned char *end;
-};
-
-
-static void read_ctx_init (struct read_ctx *ctx, Dwarf *dbg,
- Elf_Data *data);
-static bool read_ctx_init_sub (struct read_ctx *ctx,
- struct read_ctx *parent,
- const unsigned char *begin,
- const unsigned char *end);
-static uint64_t read_ctx_get_offset (struct read_ctx *ctx);
-static bool read_ctx_need_data (struct read_ctx *ctx, size_t length);
-static bool read_ctx_read_ubyte (struct read_ctx *ctx, unsigned char *ret);
-static int read_ctx_read_uleb128 (struct read_ctx *ctx, uint64_t *ret);
-static int read_ctx_read_sleb128 (struct read_ctx *ctx, int64_t *ret);
-static bool read_ctx_read_2ubyte (struct read_ctx *ctx, uint16_t *ret);
-static bool read_ctx_read_4ubyte (struct read_ctx *ctx, uint32_t *ret);
-static bool read_ctx_read_8ubyte (struct read_ctx *ctx, uint64_t *ret);
-static bool read_ctx_read_offset (struct read_ctx *ctx, bool dwarf64,
- uint64_t *ret);
-static bool read_ctx_read_var (struct read_ctx *ctx, int width, uint64_t *ret);
-static const char *read_ctx_read_str (struct read_ctx *ctx);
-static bool read_ctx_skip (struct read_ctx *ctx, uint64_t len);
-static bool read_ctx_eof (struct read_ctx *ctx);
-
/* Functions and data structures related to raw (i.e. unassisted by
libdw) Dwarf abbreviation handling. */
/* Functions for checking of structural integrity. */
-static struct cu * check_info_structural (struct section_data *data,
+static struct cu * check_info_structural (struct elf_file *file,
+ struct sec *sec,
struct abbrev_table *abbrev_chain,
Elf_Data *strings,
struct cu_coverage *cu_coverage);
-static bool check_aranges_structural (struct section_data *data,
+static bool check_aranges_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain,
struct coverage *coverage);
-static bool check_pub_structural (struct section_data *data,
+static bool check_pub_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain);
-static bool check_location_expression (struct read_ctx *ctx,
+static bool check_location_expression (struct elf_file *file,
+ struct read_ctx *ctx,
uint64_t init_off,
struct relocation_data *reloc,
size_t length,
struct where *wh,
bool addr_64);
-static bool check_loc_or_range_structural (struct section_data *data,
+static bool check_loc_or_range_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain,
struct cu_coverage *cu_coverage);
-static bool read_rel (struct section_data *secdata,
+static bool read_rel (struct elf_file *file,
+ struct sec *sec,
Elf_Data *reldata,
bool elf_64);
-static bool check_line_structural (struct section_data *data,
+static bool check_line_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain);
const char *
wh->addr3 = addr;
}
-#define WHERE_SECDATA(DATA, PARENT) (WHERE (data_get_sec (DATA)->id, PARENT))
-
static bool
address_aligned (uint64_t addr, uint64_t align)
{
return address_aligned (start + length, align) && length < align;
}
-static void
-process_file (Dwarf *dwarf, const char *fname, bool only_one)
+static bool
+elf_file_init (struct elf_file *file, Elf *elf)
{
- if (!only_one)
- printf ("\n%s:\n", fname);
+ WIPE (*file);
- struct elf_file file;
- WIPE (file);
-
- file.dwarf = dwarf;
- file.ebl = ebl_openbackend (dwarf->elf);
- if (file.ebl == NULL)
- goto invalid_elf;
- if (gelf_getehdr (dwarf->elf, &file.ehdr) == NULL)
- goto invalid_elf;
- file.addr_64 = file.ehdr.e_ident[EI_CLASS] == ELFCLASS64;
-
-#define DEF_SECDATA(VAR, SEC) \
- struct section_data VAR = {&file, (size_t)-1, NULL, \
- {&file, NULL, SHT_NULL, NULL, 0, 0, 0}}
-
- DEF_SECDATA (abbrev_data, sec_abbrev);
- DEF_SECDATA (aranges_data, sec_aranges);
- DEF_SECDATA (info_data, sec_info);
- DEF_SECDATA (line_data, sec_line);
- DEF_SECDATA (loc_data, sec_loc);
- DEF_SECDATA (pubnames_data, sec_pubnames);
- DEF_SECDATA (pubtypes_data, sec_pubtypes);
- DEF_SECDATA (ranges_data, sec_ranges);
- DEF_SECDATA (str_data, sec_str);
-
-#undef DEF_SECDATA
+ file->elf = elf;
+ file->ebl = ebl_openbackend (elf);
+
+ if (file->ebl == NULL
+ || gelf_getehdr (elf, &file->ehdr) == NULL)
+ return false;
+
+ file->addr_64 = file->ehdr.e_ident[EI_CLASS] == ELFCLASS64;
struct secinfo
{
const char *name;
- struct section_data *dataptr;
- Elf_Data *reldata;
- enum section_id sec;
+ enum section_id id; /* Section type. */
+ Elf_Data *reldata; /* Relocation data if any found. */
+ size_t reltype; /* SHT_REL or SHT_RELA. We need this
+ temporary store to be able to resolve
+ relocation section appearing before
+ relocated section. */
+ size_t secndx; /* Index into file->sec or 0 if not yet loaded. */
};
struct secinfo secinfo[] = {
-#define DEF_SECINFO(SEC) {".debug_" #SEC, &SEC##_data, NULL, sec_##SEC}
-#define DEF_NOINFO(SEC) {".debug_" #SEC, NULL, NULL, sec_##SEC}
- DEF_SECINFO (abbrev),
- DEF_SECINFO (aranges),
- DEF_SECINFO (info),
- DEF_SECINFO (line),
- DEF_SECINFO (loc),
- DEF_SECINFO (pubnames),
- DEF_SECINFO (pubtypes),
- DEF_SECINFO (ranges),
- DEF_SECINFO (str),
-#undef DEF_NOINFO
-#undef DEF_SECINFO
+#define SEC(n) {".debug_" #n, sec_##n, NULL, 0, 0},
+ DEBUGINFO_SECTIONS
+#undef SEC
};
Elf_Scn *reloc_symtab = NULL;
return NULL;
}
- struct section_data *find_secdata (const char *secname)
- {
- struct secinfo *info = find_secentry (secname);
- if (info != NULL)
- return info->dataptr;
- else
- return NULL;
- }
-
/* Now find all necessary debuginfo sections and associated
relocation sections. */
- Elf_Scn *scn = NULL;
-
/* Section 0 is special, skip it. */
- REALLOC (&file, sec);
- file.sec[file.size++].id = sec_invalid;
+ REALLOC (file, sec);
+ file->sec[file->size++].id = sec_invalid;
- while ((scn = elf_nextscn (dwarf->elf, scn)) != NULL)
+ bool check_rel = true;
+
+ for (Elf_Scn *scn = NULL; (scn = elf_nextscn (elf, scn)); )
{
- REALLOC (&file, sec);
- size_t curndx = file.size++;
- struct sec *cursec = file.sec + curndx;
+ REALLOC (file, sec);
+ size_t curndx = file->size++;
+ struct sec *cursec = file->sec + curndx;
GElf_Shdr *shdr = gelf_getshdr (scn, &cursec->shdr);
if (shdr == NULL)
{
invalid_elf:
- /* A "can't happen". libdw already managed to parse the Elf
- file when constructing the Dwarf object. */
wr_error (NULL, "Broken ELF.\n");
- goto skip_rel;
+ return false;
}
- const char *scnname = elf_strptr (dwarf->elf, file.ehdr.e_shstrndx,
+ const char *scnname = elf_strptr (elf, file->ehdr.e_shstrndx,
shdr->sh_name);
if (scnname == NULL)
goto invalid_elf;
scnname, shdr->sh_addr, shdr->sh_addralign);
struct secinfo *secentry = find_secentry (scnname);
- struct section_data *secdata = secentry != NULL ? secentry->dataptr : NULL;
cursec->scn = scn;
- cursec->id = secentry != NULL ? secentry->sec : sec_invalid;
+ cursec->id = secentry != NULL ? secentry->id : sec_invalid;
cursec->name = scnname;
+ cursec->rel = (struct relocation_data){NULL, SHT_NULL, NULL, 0, 0, 0};
- if (secdata != NULL)
+ /* Dwarf section. */
+ if (secentry != NULL)
{
- if (secdata->secndx == (size_t)-1)
+ if (unlikely (secentry->secndx != 0))
+ wr_error (NULL, "Multiple occurrences of section %s.\n", scnname);
+ else
{
- secdata->data = elf_getdata (scn, NULL);
- if (secdata->data == NULL || secdata->data->d_buf == NULL)
- wr_error (NULL, "Data-less section %s.\n", scnname);
- secdata->secndx = curndx;
+ /* Haven't seen a section of that name yet. */
+ cursec->data = elf_getdata (scn, NULL);
+ if (cursec->data == NULL || cursec->data->d_buf == NULL)
+ {
+ wr_error (NULL, "Data-less section %s.\n", scnname);
+ cursec->data = NULL;
+ }
+ secentry->secndx = curndx;
}
- else
- wr_error (NULL, "Multiple occurrences of section %s.\n", scnname);
}
+ /* Relocation section. */
else if (shdr->sh_type == SHT_RELA || shdr->sh_type == SHT_REL)
{
/* Get data of section that this REL(A) section relocates. */
- Elf_Scn *relocated_scn = elf_getscn (dwarf->elf, shdr->sh_info);
- Elf_Scn *symtab_scn = elf_getscn (dwarf->elf, shdr->sh_link);
+ Elf_Scn *relocated_scn = elf_getscn (elf, shdr->sh_info);
+ Elf_Scn *symtab_scn = elf_getscn (elf, shdr->sh_link);
if (relocated_scn == NULL || symtab_scn == NULL)
goto invalid_elf;
goto invalid_elf;
const char *relocated_scnname
- = elf_strptr (dwarf->elf, file.ehdr.e_shstrndx,
+ = elf_strptr (elf, file->ehdr.e_shstrndx,
relocated_shdr->sh_name);
struct secinfo *relocated
= find_secentry (relocated_scnname);
- if (relocated != NULL && relocated->dataptr != NULL)
+ if (relocated != NULL)
{
if (relocated->reldata != NULL)
wr_error (NULL,
else
{
relocated->reldata = elf_getdata (scn, NULL);
- if (relocated->reldata == NULL)
- wr_error (NULL,
- "Data-less relocation section %s.\n", scnname);
- relocated->dataptr->rel.type = shdr->sh_type;
+ if (unlikely (relocated->reldata == NULL
+ || relocated->reldata->d_buf == NULL))
+ {
+ wr_error (NULL,
+ "Data-less relocation section %s.\n", scnname);
+ relocated->reldata = NULL;
+ }
+ else
+ relocated->reltype = shdr->sh_type;
}
if (reloc_symtab == NULL)
}
}
- Elf_Data *reloc_symdata = NULL;
- if (reloc_symtab != NULL)
+ for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
+ if (secinfo[i].secndx != 0)
+ file->debugsec[secinfo[i].id] = file->sec + secinfo[i].secndx;
+
+ if (check_rel)
{
- reloc_symdata = elf_getdata (reloc_symtab, NULL);
- if (reloc_symdata == NULL)
+ Elf_Data *reloc_symdata = NULL;
+ if (reloc_symtab != NULL)
{
- wr_error (NULL,
- "Couldn't obtain symtab data.\n");
- /* But carry on, we can check a lot of stuff even without
- symbol table. */
+ reloc_symdata = elf_getdata (reloc_symtab, NULL);
+ if (reloc_symdata == NULL)
+ /* Not a show stopper, we can check a lot of stuff even
+ without a symbol table. */
+ wr_error (NULL,
+ "Couldn't obtain symtab data.\n");
}
- }
- /* Check relocation sections that we've got. */
- for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
- {
- struct secinfo *cur = secinfo + i;
- if (cur->dataptr != NULL
- && cur->reldata != NULL)
+ /* Check relocation sections that we've got. */
+ for (size_t i = 0; i < sizeof (secinfo) / sizeof (*secinfo); ++i)
{
- if (cur->dataptr->data == NULL)
- wr_error (&WHERE_SECDATA (secinfo[i].dataptr, NULL),
- ": this data-less section has a relocation section.\n");
- else if (read_rel (cur->dataptr, cur->reldata, file.addr_64))
- cur->dataptr->rel.symdata = reloc_symdata;
+ struct secinfo *cur = secinfo + i;
+ if (cur->secndx != 0 && cur->reldata != NULL)
+ {
+ struct sec *sec = file->sec + cur->secndx;
+ sec->rel.type = cur->reltype;
+ if (sec->data == NULL)
+ wr_error (&WHERE (sec->id, NULL),
+ ": this data-less section has a relocation section.\n");
+ else if (read_rel (file, sec, cur->reldata, file->addr_64))
+ sec->rel.symdata = reloc_symdata;
+ }
}
+
+ if (find_secentry (".debug_str")->reldata != NULL)
+ wr_message (mc_impact_2 | mc_elf, &WHERE (sec_str, NULL),
+ ": there's a relocation section associated with this section.\n");
}
- if (str_data.rel.size > 0)
- wr_message (mc_impact_2 | mc_elf, &WHERE (sec_str, NULL),
- ": there's a relocation section associated with this section.\n");
+ return true;
+}
+
+static void
+process_file (Elf *elf, const char *fname, bool only_one)
+{
+ if (!only_one)
+ printf ("\n%s:\n", fname);
+
+ struct elf_file file;
+ if (!elf_file_init (&file, elf))
+ return;
- skip_rel:;
struct abbrev_table *abbrev_chain = NULL;
struct cu *cu_chain = NULL;
struct read_ctx ctx;
- struct hl_ctx *hlctx = hl_ctx_new (dwarf);
+ struct hl_ctx *hlctx = hl_ctx_new (elf);
+
+#define SEC(sec) (file.debugsec[sec_##sec])
- /* If we got Dwarf pointer, .debug_abbrev and .debug_info are
- present inside the file. But let's be paranoid. */
- if (likely (abbrev_data.data != NULL))
+ if (likely (SEC(abbrev) != NULL))
{
- read_ctx_init (&ctx, dwarf, abbrev_data.data);
+ read_ctx_init (&ctx, &file, SEC(abbrev)->data);
abbrev_chain = abbrev_table_load (&ctx);
}
else if (!tolerate_nodebug)
struct cu_coverage *cu_coverage = NULL;
if (abbrev_chain != NULL)
{
- if (info_data.data != NULL)
+ if (SEC(info) != NULL)
{
cu_coverage = calloc (1, sizeof (struct cu_coverage));
- cu_chain = check_info_structural (&info_data, abbrev_chain,
- str_data.data, cu_coverage);
+ cu_chain = check_info_structural (&file, SEC(info), abbrev_chain,
+ SEC(str)->data, cu_coverage);
if (cu_chain != NULL && do_high_level)
check_expected_trees (hlctx);
}
}
bool ranges_sound;
- if (ranges_data.data != NULL && cu_chain != NULL)
- ranges_sound
- = check_loc_or_range_structural (&ranges_data, cu_chain, cu_coverage);
+ if (SEC(ranges) != NULL && cu_chain != NULL)
+ ranges_sound = check_loc_or_range_structural (&file, SEC(ranges),
+ cu_chain, cu_coverage);
else
ranges_sound = false;
- if (loc_data.data != NULL && cu_chain != NULL)
- check_loc_or_range_structural (&loc_data, cu_chain, NULL);
+ if (SEC(loc) != NULL && cu_chain != NULL)
+ check_loc_or_range_structural (&file, SEC(loc), cu_chain, NULL);
- if (aranges_data.data != NULL)
+ if (SEC(aranges) != NULL)
{
- read_ctx_init (&ctx, dwarf, aranges_data.data);
+ read_ctx_init (&ctx, &file, SEC(aranges)->data);
/* If ranges were needed and not loaded, don't pass them down
for CU/aranges coverage analysis. */
struct coverage *cov
- = cu_coverage->need_ranges ? NULL : &cu_coverage->cov;
+ = (cu_coverage != NULL
+ && cu_coverage->need_ranges) ? NULL : &cu_coverage->cov;
- if (check_aranges_structural (&aranges_data, cu_chain, cov)
+ if (check_aranges_structural (&file, SEC(aranges), cu_chain, cov)
&& ranges_sound && do_high_level && !be_tolerant && !be_gnu)
check_matching_ranges (hlctx);
}
- if (pubnames_data.data != NULL)
- check_pub_structural (&pubnames_data, cu_chain);
+ if (SEC(pubnames) != NULL)
+ check_pub_structural (&file, SEC(pubnames), cu_chain);
else
wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf,
&WHERE (sec_pubnames, NULL), ": data not found.\n");
- if (pubtypes_data.data != NULL)
- check_pub_structural (&pubtypes_data, cu_chain);
+ if (SEC(pubtypes) != NULL)
+ check_pub_structural (&file, SEC(pubtypes), cu_chain);
else
wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf | mc_pubtypes,
&WHERE (sec_pubtypes, NULL), ": data not found.\n");
- if (line_data.data != NULL)
- check_line_structural (&line_data, cu_chain);
+ if (SEC(line) != NULL)
+ check_line_structural (&file, SEC(line), cu_chain);
else
wr_message (mc_impact_4 | mc_acc_suboptimal | mc_elf | mc_loc,
&WHERE (sec_line, NULL), ": data not found.\n");
ebl_closebackend (file.ebl);
free (file.sec);
hl_ctx_delete (hlctx);
-}
-
-static void
-read_ctx_init (struct read_ctx *ctx, Dwarf *dbg, Elf_Data *data)
-{
- if (data == NULL)
- abort ();
-
- ctx->dbg = dbg;
- ctx->data = data;
- ctx->begin = data->d_buf;
- ctx->end = data->d_buf + data->d_size;
- ctx->ptr = data->d_buf;
-}
-
-static bool
-read_ctx_init_sub (struct read_ctx *ctx, struct read_ctx *parent,
- const unsigned char *begin, const unsigned char *end)
-{
- if (parent == NULL)
- abort ();
-
- if (begin < parent->begin
- || end > parent->end)
- return false;
-
- ctx->dbg = parent->dbg;
- ctx->data = parent->data;
- ctx->begin = begin;
- ctx->end = end;
- ctx->ptr = begin;
- return true;
-}
-
-static uint64_t
-read_ctx_get_offset (struct read_ctx *ctx)
-{
- assert (ctx->ptr >= ctx->begin);
- return (uint64_t)(ctx->ptr - ctx->begin);
-}
-
-static bool
-read_ctx_need_data (struct read_ctx *ctx, size_t length)
-{
- const unsigned char *ptr = ctx->ptr + length;
- return ptr <= ctx->end && (length == 0 || ptr > ctx->ptr);
-}
-
-static bool
-read_ctx_read_ubyte (struct read_ctx *ctx, unsigned char *ret)
-{
- if (!read_ctx_need_data (ctx, 1))
- return false;
- if (ret != NULL)
- *ret = *ctx->ptr;
- ctx->ptr++;
- return true;
-}
-
-static int
-read_ctx_read_uleb128 (struct read_ctx *ctx, uint64_t *ret)
-{
- uint64_t result = 0;
- int shift = 0;
- int size = 8 * sizeof (result);
- bool zero_tail = false;
-
- while (1)
- {
- uint8_t byte;
- if (!read_ctx_read_ubyte (ctx, &byte))
- return -1;
-
- uint8_t payload = byte & 0x7f;
- zero_tail = payload == 0 && shift > 0;
- result |= (uint64_t)payload << shift;
- shift += 7;
- if (shift > size && byte != 0x1)
- return -1;
- if ((byte & 0x80) == 0)
- break;
- }
- if (ret != NULL)
- *ret = result;
- return zero_tail ? 1 : 0;
+#undef SEC
}
static bool
return st >= 0;
}
-static int
-read_ctx_read_sleb128 (struct read_ctx *ctx, int64_t *ret)
-{
- int64_t result = 0;
- int shift = 0;
- int size = 8 * sizeof (result);
- bool zero_tail = false;
- bool sign = false;
-
- while (1)
- {
- uint8_t byte;
- if (!read_ctx_read_ubyte (ctx, &byte))
- return -1;
-
- uint8_t payload = byte & 0x7f;
- zero_tail = shift > 0 && ((payload == 0x7f && sign)
- || (payload == 0 && !sign));
- sign = (byte & 0x40) != 0; /* Set sign for rest of loop & next round. */
- result |= (int64_t)payload << shift;
- shift += 7;
- if ((byte & 0x80) == 0)
- {
- if (shift < size && sign)
- result |= -((int64_t)1 << shift);
- break;
- }
- if (shift > size)
- return -1;
- }
-
- if (ret != NULL)
- *ret = result;
- return zero_tail ? 1 : 0;
-}
-
static bool
checked_read_sleb128 (struct read_ctx *ctx, int64_t *ret,
struct where *where, const char *what)
return st >= 0;
}
-static bool
-read_ctx_read_2ubyte (struct read_ctx *ctx, uint16_t *ret)
-{
- if (!read_ctx_need_data (ctx, 2))
- return false;
- uint16_t val = read_2ubyte_unaligned_inc (ctx->dbg, ctx->ptr);
- if (ret != NULL)
- *ret = val;
- return true;
-}
-
-static bool
-read_ctx_read_4ubyte (struct read_ctx *ctx, uint32_t *ret)
-{
- if (!read_ctx_need_data (ctx, 4))
- return false;
- uint32_t val = read_4ubyte_unaligned_inc (ctx->dbg, ctx->ptr);
- if (ret != NULL)
- *ret = val;
- return true;
-}
-
-static bool
-read_ctx_read_8ubyte (struct read_ctx *ctx, uint64_t *ret)
-{
- if (!read_ctx_need_data (ctx, 8))
- return false;
- uint64_t val = read_8ubyte_unaligned_inc (ctx->dbg, ctx->ptr);
- if (ret != NULL)
- *ret = val;
- return true;
-}
-
-static bool
-read_ctx_read_offset (struct read_ctx *ctx, bool dwarf64, uint64_t *ret)
-{
- if (dwarf64)
- return read_ctx_read_8ubyte (ctx, ret);
-
- uint32_t v;
- if (!read_ctx_read_4ubyte (ctx, &v))
- return false;
-
- if (ret != NULL)
- *ret = (uint64_t)v;
- return true;
-}
-
-static bool
-read_ctx_read_var (struct read_ctx *ctx, int width, uint64_t *ret)
-{
- switch (width)
- {
- case 4:
- case 8:
- return read_ctx_read_offset (ctx, width == 8, ret);
- case 2:
- {
- uint16_t val;
- if (!read_ctx_read_2ubyte (ctx, &val))
- return false;
- *ret = val;
- return true;
- }
- case 1:
- {
- uint8_t val;
- if (!read_ctx_read_ubyte (ctx, &val))
- return false;
- *ret = val;
- return true;
- }
- default:
- return false;
- };
-}
-
/* The value passed back in uint64_t VALUEP may actually be
type-casted int64_t. WHAT and WHERE describe error message and
context for LEB128 loading. */
return false;
}
-static const char *
-read_ctx_read_str (struct read_ctx *ctx)
-{
- const char *ret = (const char *)ctx->ptr;
- uint8_t byte;
- do
- if (!read_ctx_read_ubyte (ctx, &byte))
- return NULL;
- while (byte != 0);
- return ret;
-}
-
-static bool
-read_ctx_skip (struct read_ctx *ctx, uint64_t len)
-{
- if (!read_ctx_need_data (ctx, len))
- return false;
- ctx->ptr += len;
- return true;
-}
-
-static bool
-read_ctx_eof (struct read_ctx *ctx)
-{
- return !read_ctx_need_data (ctx, 1);
-}
-
static bool
attrib_form_valid (uint64_t form)
{
const char *scnname = sco->sec->name;
struct sec *sec = sco->sec;
- Elf_Data *data = elf_getdata (sec->scn, NULL);
- if (data == NULL)
- {
- wr_error (&where, ": couldn't read the data of section %s.\n", scnname);
- return false;
- }
-
GElf_Xword align = sec->shdr.sh_addralign;
/* We don't expect some sections to be covered. But if they
get stripped debuginfo file, the data may not be available. In
that case don't report the hole, if it seems to be alignment
padding. */
- if (data->d_buf != NULL)
+ if (sco->sec->data->d_buf != NULL)
{
bool zeroes = true;
for (uint64_t j = begin; j < end; ++j)
- if (((char *)data->d_buf)[j] != 0)
+ if (((char *)sco->sec->data->d_buf)[j] != 0)
{
zeroes = false;
break;
/* Skip all the remaining relocations. */
static void
-relocation_skip_rest (struct section_data *data)
+relocation_skip_rest (struct sec *sec)
{
- if (data->rel.rel != NULL)
- relocation_next (&data->rel, (uint64_t)-1, &WHERE_SECDATA (data, NULL),
+ if (sec->rel.rel != NULL)
+ relocation_next (&sec->rel, (uint64_t)-1, &WHERE (sec->id, NULL),
skip_mismatched);
}
which case we failed or didn't get around to obtain the symbol from
symbol table, or non-NULL, in which case the symbol was initialized. */
static void
-relocate_one (struct relocation_data *reloc, struct relocation *rel,
+relocate_one (struct elf_file *file,
+ struct relocation_data *reloc,
+ struct relocation *rel,
unsigned width, uint64_t *value, struct where *where,
enum section_id offset_into, GElf_Sym **symptr)
{
return;
}
- Elf_Type type = ebl_reloc_simple_type (reloc->file->ebl, rel->type);
+ Elf_Type type = ebl_reloc_simple_type (file->ebl, rel->type);
unsigned rel_width;
switch (type)
": %d-byte relocation relocates %d-byte datum.\n",
rel_width, width);
- /* Tolerate that we might have failed to obtain a symbol table. */
+ /* Tolerate that we might have failed to obtain the symbol table. */
if (reloc->symdata != NULL)
{
symbol = gelf_getsym (reloc->symdata, rel->symndx, symbol);
don't update symbol table doing that. So instead of looking
at symbol value, look at section address. */
uint64_t sym_value = symbol->st_value;
- if (reloc->file->ehdr.e_type == ET_REL
+ if (file->ehdr.e_type == ET_REL
&& ELF64_ST_TYPE (symbol->st_info) == STT_SECTION)
{
assert (sym_value == 0);
- sym_value = reloc->file->sec[section_index].shdr.sh_addr;
+ sym_value = file->sec[section_index].shdr.sh_addr;
}
/* It's target value, not section offset. */
&& (section_index == SHN_UNDEF
|| section_index == SHN_COMMON))))
{
- Elf_Scn *scn;
- GElf_Shdr shdr_mem, *shdr;
if (offset_into != rel_address && section_index == SHN_UNDEF)
wr_error (&reloc_where,
": relocation of an address is formed against SHN_UNDEF symbol"
" (symtab index %d).\n", rel->symndx);
- else if ((scn = elf_getscn (reloc->file->dwarf->elf,
- section_index)) == NULL)
- wr_error (&reloc_where,
- ": couldn't obtain associated section #%" PRId64 ".\n",
- section_index);
- else if ((shdr = gelf_getshdr (scn, &shdr_mem)) == NULL)
- wr_error (&reloc_where,
- ": couldn't obtain header of associated section #%" PRId64 ".\n",
- section_index);
else
{
+ GElf_Shdr *shdr = &file->sec[section_index].shdr;
if ((shdr->sh_flags & SHF_ALLOC) != SHF_ALLOC)
wr_message (mc_reloc | mc_impact_3, &reloc_where,
": associated section %s isn't SHF_ALLOC.\n",
- reloc->file->sec[section_index].name);
+ file->sec[section_index].name);
if (offset_into == rel_exec
&& (shdr->sh_flags & SHF_EXECINSTR) != SHF_EXECINSTR)
/* This may still be kosher, but it's suspicious. */
wr_message (mc_reloc | mc_impact_2, &reloc_where,
": relocation against %s is suspicious, expected executable section.\n",
- reloc->file->sec[section_index].name);
+ file->sec[section_index].name);
}
}
}
enum section_id id;
/* If symtab[symndx].st_shndx does not match the expected
debug section's index, complain. */
- if (section_index >= reloc->file->size)
+ if (section_index >= file->size)
wr_error (&reloc_where,
": invalid associated section #%" PRId64 ".\n",
section_index);
- else if ((id = reloc->file->sec[section_index].id) != offset_into)
+ else if ((id = file->sec[section_index].id) != offset_into)
{
char *wh1 = id != sec_invalid
? strdup (where_fmt (&WHERE (id, NULL), NULL))
- : (char *)reloc->file->sec[section_index].name;
+ : (char *)file->sec[section_index].name;
char *wh2 = strdup (where_fmt (&WHERE (offset_into, NULL), NULL));
wr_error (&reloc_where,
": relocation references section %s, but %s was expected.\n",
/* Only do the actual relocation if we have ET_REL files. For
non-ET_REL files, only do the above checking. */
- if (reloc->file->ehdr.e_type == ET_REL)
+ if (file->ehdr.e_type == ET_REL)
{
*value = rel->addend + sym_value;
if (rel_width == 4)
+1 in case some dies were actually loaded
*/
static int
-read_die_chain (struct read_ctx *ctx,
+read_die_chain (struct elf_file *file,
+ struct read_ctx *ctx,
struct cu *cu,
struct abbrev_table *abbrevs,
Elf_Data *strings,
struct ref_record *local_die_refs,
struct coverage *strings_coverage,
struct relocation_data *reloc,
- struct elf_file *file,
struct cu_coverage *cu_coverage)
{
bool got_die = false;
if ((rel = relocation_next (reloc, ctx_offset,
&where, skip_mismatched)))
- relocate_one (reloc, rel, dwarf_64 ? 8 : 4,
+ relocate_one (file, reloc, rel, dwarf_64 ? 8 : 4,
&addr, &where, sec_str, NULL);
else if (type_is_rel)
wr_message (mc_impact_2 | mc_die_other | mc_reloc | mc_strings,
if ((rel = relocation_next (reloc, ctx_offset,
&where, skip_mismatched)))
{
- relocate_one (reloc, rel, addr_64 ? 8 : 4, &addr, &where,
- reloc_target (form, it), symbolp);
+ relocate_one (file, reloc, rel, addr_64 ? 8 : 4, &addr,
+ &where, reloc_target (form, it), symbolp);
if (relocatedp != NULL)
*relocatedp = true;
}
{
if ((rel = relocation_next (reloc, ctx_offset,
&where, skip_mismatched)))
- relocate_one (reloc, rel, 4, &value, &where,
+ relocate_one (file, reloc, rel, 4, &value, &where,
reloc_target (form, it), NULL);
else if (type_is_rel && check_ptr != check_nothing)
wr_message (mc_impact_2 | mc_die_other | mc_reloc
{
if ((rel = relocation_next (reloc, ctx_offset,
&where, skip_mismatched)))
- relocate_one (reloc, rel, 8, &value, &where,
+ relocate_one (file, reloc, rel, 8, &value, &where,
reloc_target (form, it), NULL);
else if (type_is_rel && check_ptr != check_nothing)
wr_message (mc_impact_2 | mc_die_other | mc_reloc
if (is_location_attrib (it->name))
{
uint64_t expr_start = cu->offset + read_ctx_get_offset (ctx);
- if (!check_location_expression (ctx, expr_start,
+ if (!check_location_expression (file, ctx, expr_start,
reloc, length,
&where, addr_64))
return -1;
if (abbrev->has_children)
{
- int st = read_die_chain (ctx, cu, abbrevs, strings,
+ int st = read_die_chain (file, ctx, cu, abbrevs, strings,
dwarf_64, addr_64,
local_die_refs,
- strings_coverage, reloc, file,
+ strings_coverage, reloc,
cu_coverage);
if (st == -1)
return -1;
}
static bool
-check_cu_structural (struct read_ctx *ctx,
+check_cu_structural (struct elf_file *file,
+ struct read_ctx *ctx,
struct cu *const cu,
struct abbrev_table *abbrev_chain,
Elf_Data *strings,
bool dwarf_64,
struct coverage *strings_coverage,
struct relocation_data *reloc,
- struct elf_file *file,
struct cu_coverage *cu_coverage)
{
uint8_t address_size;
struct relocation *rel
= relocation_next (reloc, ctx_offset, &cu->where, skip_mismatched);
if (rel != NULL)
- relocate_one (reloc, rel, dwarf_64 ? 8 : 4,
+ relocate_one (file, reloc, rel, dwarf_64 ? 8 : 4,
&abbrev_offset, &cu->where, sec_abbrev, NULL);
else if (file->ehdr.e_type == ET_REL)
wr_message (mc_impact_2 | mc_info | mc_reloc, &cu->where,
WIPE (local_die_refs);
cu->cudie_offset = read_ctx_get_offset (ctx) + cu->offset;
- if (read_die_chain (ctx, cu, abbrevs, strings,
+ if (read_die_chain (file, ctx, cu, abbrevs, strings,
dwarf_64, address_size == 8,
&local_die_refs, strings_coverage,
(reloc != NULL && reloc->size > 0) ? reloc : NULL,
- file, cu_coverage) >= 0)
+ cu_coverage) >= 0)
{
for (size_t i = 0; i < abbrevs->size; ++i)
if (!abbrevs->abbr[i].used)
}
static struct cu *
-check_info_structural (struct section_data *data,
+check_info_structural (struct elf_file *file,
+ struct sec *sec,
struct abbrev_table *abbrev_chain,
Elf_Data *strings,
struct cu_coverage *cu_coverage)
{
struct read_ctx ctx;
- read_ctx_init (&ctx, data->file->dwarf, data->data);
+ read_ctx_init (&ctx, file, sec->data);
struct ref_record die_refs;
WIPE (die_refs);
strings_coverage = &strings_coverage_mem;
}
- struct relocation_data *reloc = data->rel.size > 0 ? &data->rel : NULL;
+ struct relocation_data *reloc = sec->rel.size > 0 ? &sec->rel : NULL;
while (!read_ctx_eof (&ctx))
{
const unsigned char *cu_begin = ctx.ptr;
}
cu_ctx.ptr = ctx.ptr;
- if (!check_cu_structural (&cu_ctx, cur, abbrev_chain,
+ if (!check_cu_structural (file, &cu_ctx, cur, abbrev_chain,
strings, dwarf_64,
- strings_coverage, reloc, data->file,
+ strings_coverage, reloc,
cu_coverage))
{
success = false;
": CU lengths don't exactly match Elf_Data contents.");
else
/* Did we consume all the relocations? */
- relocation_skip_rest (data);
+ relocation_skip_rest (sec);
}
low_pc/high_pc pairs, or via DW_AT_ranges references). If
non-NULL, analysis of arange coverage is done against that set. */
static bool
-check_aranges_structural (struct section_data *data, struct cu *cu_chain,
+check_aranges_structural (struct elf_file *file,
+ struct sec *sec,
+ struct cu *cu_chain,
struct coverage *coverage)
{
struct read_ctx ctx;
- read_ctx_init (&ctx, data->file->dwarf, data->data);
+ read_ctx_init (&ctx, file, sec->data);
bool retval = true;
}
struct relocation *rel;
- if ((rel = relocation_next (&data->rel, ctx_offset,
+ if ((rel = relocation_next (&sec->rel, ctx_offset,
&where, skip_mismatched)))
- relocate_one (&data->rel, rel, dwarf_64 ? 8 : 4,
+ relocate_one (file, &sec->rel, rel, dwarf_64 ? 8 : 4,
&cu_offset, &where, sec_info, NULL);
- else if (data->file->ehdr.e_type == ET_REL)
+ else if (file->ehdr.e_type == ET_REL)
wr_message (mc_impact_2 | mc_aranges | mc_reloc | mc_header, &where,
PRI_LACK_RELOCATION, "debug info offset");
if (!read_ctx_read_ubyte (&sub_ctx, &c))
{
wr_error (&where,
- ": section ends after the header, but before the first entry.\n");
+ ": section ends after the header, "
+ "but before the first entry.\n");
retval = false;
goto next;
}
goto next;
}
- if ((rel = relocation_next (&data->rel, ctx_offset,
+ if ((rel = relocation_next (&sec->rel, ctx_offset,
&where, skip_mismatched)))
{
address_relocated = true;
- relocate_one (&data->rel, rel, address_size,
+ relocate_one (file, &sec->rel, rel, address_size,
&address, &where, rel_address, NULL);
}
- else if (data->file->ehdr.e_type == ET_REL
- && address != 0)
+ else if (file->ehdr.e_type == ET_REL && address != 0)
wr_message (mc_impact_2 | mc_aranges | mc_reloc, &where,
PRI_LACK_RELOCATION, "address field");
}
if (aranges_coverage != NULL)
- compare_coverage (data->file, coverage, aranges_coverage,
- sec_aranges, "aranges");
-
- coverage_free (aranges_coverage);
+ {
+ compare_coverage (file, coverage, aranges_coverage,
+ sec_aranges, "aranges");
+ coverage_free (aranges_coverage);
+ }
return retval;
}
static bool
-check_pub_structural (struct section_data *data,
+check_pub_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain)
{
struct read_ctx ctx;
- read_ctx_init (&ctx, data->file->dwarf, data->data);
+ read_ctx_init (&ctx, file, sec->data);
bool retval = true;
while (!read_ctx_eof (&ctx))
{
- struct where where = WHERE_SECDATA (data, NULL);
+ struct where where = WHERE (sec->id, NULL);
where_reset_1 (&where, read_ctx_get_offset (&ctx));
const unsigned char *set_begin = ctx.ptr;
}
struct relocation *rel;
- if ((rel = relocation_next (&data->rel, ctx_offset,
+ if ((rel = relocation_next (&sec->rel, ctx_offset,
&where, skip_mismatched)))
- relocate_one (&data->rel, rel, dwarf_64 ? 8 : 4,
+ relocate_one (file, &sec->rel, rel, dwarf_64 ? 8 : 4,
&cu_offset, &where, sec_info, NULL);
- else if (data->file->ehdr.e_type == ET_REL)
+ else if (file->ehdr.e_type == ET_REL)
wr_message (mc_impact_2 | mc_pubtables | mc_reloc | mc_header, &where,
PRI_LACK_RELOCATION, "debug info offset");
struct cu *cu = NULL;
- enum section_id sec = data_get_sec (data)->id;
if (cu_chain != NULL && (cu = cu_find_cu (cu_chain, cu_offset)) == NULL)
wr_error (&where, ": unresolved reference to " PRI_CU ".\n", cu_offset);
if (cu != NULL)
{
where.ref = &cu->where;
- bool *has = sec == sec_pubnames
+ bool *has = sec->id == sec_pubnames
? &cu->has_pubnames : &cu->has_pubtypes;
if (*has)
wr_message (mc_impact_2 | mc_pubtables | mc_header, &where,
if (sub_ctx.ptr != sub_ctx.end
&& !check_zero_padding (&sub_ctx, mc_pubtables,
- &WHERE (sec, NULL)))
+ &WHERE (sec->id, NULL)))
{
wr_message_padding_n0 (mc_pubtables | mc_error,
- &WHERE (sec, NULL),
+ &WHERE (sec->id, NULL),
read_ctx_get_offset (&sub_ctx),
read_ctx_get_offset (&sub_ctx) + size);
retval = false;
}
if (retval)
- relocation_skip_rest (data);
+ relocation_skip_rest (sec);
return retval;
}
}
static bool
-check_location_expression (struct read_ctx *parent_ctx,
+check_location_expression (struct elf_file *file,
+ struct read_ctx *parent_ctx,
uint64_t init_off,
struct relocation_data *reloc,
size_t length,
struct relocation *_rel; \
if ((_rel = relocation_next (reloc, _off, \
&where, skip_mismatched))) \
- relocate_one (reloc, _rel, \
+ relocate_one (file, reloc, _rel, \
addr_64 ? 8 : 4, _ptr, &where, \
reloc_target_loc (opcode), NULL); \
} \
}
static bool
-check_loc_or_range_ref (const struct read_ctx *parent_ctx,
+check_loc_or_range_ref (struct elf_file *file,
+ const struct read_ctx *parent_ctx,
struct cu *cu,
- struct section_data *data,
+ struct sec *sec,
struct coverage *coverage,
struct coverage_map *coverage_map,
struct cu_coverage *cu_coverage,
enum message_category cat)
{
char buf[128]; // messages
- enum section_id sec = data_get_sec (data)->id;
- assert (sec == sec_loc || sec == sec_ranges);
+ assert (sec->id == sec_loc || sec->id == sec_ranges);
assert (cat == mc_loc || cat == mc_ranges);
- assert ((sec == sec_loc) == (cat == mc_loc));
+ assert ((sec->id == sec_loc) == (cat == mc_loc));
assert (coverage != NULL);
struct read_ctx ctx;
- read_ctx_init (&ctx, parent_ctx->dbg, parent_ctx->data);
+ read_ctx_init (&ctx, parent_ctx->file, parent_ctx->data);
if (!read_ctx_skip (&ctx, addr))
{
wr_error (wh, ": invalid reference outside the section "
}
bool retval = true;
- bool contains_locations = sec == sec_loc;
+ bool contains_locations = sec->id == sec_loc;
if (coverage_is_covered (coverage, addr, 1))
{
uint64_t base = cu->low_pc;
while (!read_ctx_eof (&ctx))
{
- struct where where = WHERE (sec, wh);
+ struct where where = WHERE (sec->id, wh);
where_reset_1 (&where, read_ctx_get_offset (&ctx));
#define HAVE_OVERLAP \
}
struct relocation *rel;
- if ((rel = relocation_next (&data->rel, begin_off,
+ if ((rel = relocation_next (&sec->rel, begin_off,
&where, skip_mismatched)))
{
begin_relocated = true;
- relocate_one (&data->rel, rel, addr_64 ? 8 : 4,
+ relocate_one (file, &sec->rel, rel, addr_64 ? 8 : 4,
&begin_addr, &where, rel_value, &begin_symbol);
}
return false;
}
- if ((rel = relocation_next (&data->rel, end_off,
+ if ((rel = relocation_next (&sec->rel, end_off,
&where, skip_mismatched)))
{
end_relocated = true;
- relocate_one (&data->rel, rel, addr_64 ? 8 : 4,
+ relocate_one (file, &sec->rel, rel, addr_64 ? 8 : 4,
&end_addr, &where, rel_value, &end_symbol);
if (begin_addr != escape)
{
wr_message (cat | mc_impact_2 | mc_reloc, &where,
": end of address range is relocated, but the beginning wasn't.\n");
else
- check_range_relocations (cat, &where,
- data->file,
+ check_range_relocations (cat, &where, file,
begin_symbol, end_symbol,
"begin and end address");
}
/* location expression itself */
uint64_t expr_start = read_ctx_get_offset (&ctx);
- if (!check_location_expression (&ctx, expr_start, &data->rel,
- len, &where, addr_64))
+ if (!check_location_expression (file, &ctx, expr_start,
+ &sec->rel, len, &where, addr_64))
return false;
uint64_t expr_end = read_ctx_get_offset (&ctx);
if (!overlap
}
static bool
-check_loc_or_range_structural (struct section_data *data,
+check_loc_or_range_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain,
struct cu_coverage *cu_coverage)
{
- enum section_id sec = data_get_sec (data)->id;
- assert (sec == sec_loc || sec == sec_ranges);
+ assert (sec->id == sec_loc || sec->id == sec_ranges);
assert (cu_chain != NULL);
struct read_ctx ctx;
- read_ctx_init (&ctx, data->file->dwarf, data->data);
+ read_ctx_init (&ctx, file, sec->data);
bool retval = true;
/* For .debug_ranges, we optionally do ranges vs. ELF sections
coverage analysis. */
struct coverage_map *coverage_map = NULL;
- if (do_range_coverage && sec == sec_ranges
- && (coverage_map = coverage_map_alloc_XA (data->file, sec == sec_loc)) == NULL)
+ if (do_range_coverage && sec->id == sec_ranges
+ && (coverage_map
+ = coverage_map_alloc_XA (file, sec->id == sec_loc)) == NULL)
{
- wr_error (&WHERE (sec, NULL),
+ wr_error (&WHERE (sec->id, NULL),
": couldn't read ELF, skipping coverage analysis.\n");
retval = false;
}
struct coverage coverage;
WIPE (coverage);
- enum message_category cat = sec == sec_loc ? mc_loc : mc_ranges;
+ enum message_category cat = sec->id == sec_loc ? mc_loc : mc_ranges;
/* Relocation checking in the followings assumes that all the
references are organized in monotonously increasing order. That
for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
{
struct ref_record *rec
- = sec == sec_loc ? &cu->loc_refs : &cu->range_refs;
+ = sec->id == sec_loc ? &cu->loc_refs : &cu->range_refs;
size += rec->size;
}
struct ref_cu
for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
{
struct ref_record *rec
- = sec == sec_loc ? &cu->loc_refs : &cu->range_refs;
+ = sec->id == sec_loc ? &cu->loc_refs : &cu->range_refs;
for (size_t i = 0; i < rec->size; ++i)
*refptr++ = ((struct ref_cu){.ref = rec->refs[i], .cu = cu});
}
{
if (off == last_off)
continue;
- relocation_skip (&data->rel, off,
- &WHERE (sec, NULL), skip_unref);
+ relocation_skip (&sec->rel, off,
+ &WHERE (sec->id, NULL), skip_unref);
}
/* XXX We pass cu_coverage down for all ranges. That means all
ranges get recorded, not only those belonging to CUs.
Perhaps that's undesirable. */
- if (!check_loc_or_range_ref (&ctx, refs[i].cu, data,
+ if (!check_loc_or_range_ref (file, &ctx, refs[i].cu, sec,
&coverage, coverage_map,
- sec == sec_ranges ? cu_coverage : NULL,
+ sec->id == sec_ranges ? cu_coverage : NULL,
off, refs[i].cu->address_size == 8,
&refs[i].ref.who, cat))
retval = false;
if (retval)
{
- relocation_skip_rest (data);
+ relocation_skip_rest (sec);
/* We check that all CUs have the same address size when building
the CU chain. So just take the address size of the first CU in
chain. */
coverage_find_holes (&coverage, 0, ctx.data->d_size, found_hole,
&((struct hole_info)
- {sec, cat, cu_chain->address_size,
+ {sec->id, cat, cu_chain->address_size,
ctx.data->d_buf}));
if (coverage_map)
coverage_map_find_holes (coverage_map, &coverage_map_found_hole,
&(struct coverage_map_hole_info)
- {{sec, cat, 0, NULL},
+ {{sec->id, cat, 0, NULL},
coverage_map->elf});
}
}
static bool
-read_rel (struct section_data *secdata, Elf_Data *reldata, bool elf_64)
+read_rel (struct elf_file *file,
+ struct sec *sec,
+ Elf_Data *reldata,
+ bool elf_64)
{
- assert (secdata->rel.type == SHT_REL
- || secdata->rel.type == SHT_RELA);
- bool is_rela = secdata->rel.type == SHT_RELA;
+ 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, secdata->file->dwarf, secdata->data);
+ read_ctx_init (&ctx, file, sec->data);
size_t entrysize
= elf_64
: (is_rela ? sizeof (Elf32_Rela) : sizeof (Elf32_Rel));
size_t count = reldata->d_size / entrysize;
- struct where parent = WHERE_SECDATA (secdata, NULL);
+ struct where parent = WHERE (sec->id, NULL);
struct where where = WHERE (is_rela ? sec_rela : sec_rel, NULL);
where.ref = &parent;
{
where_reset_1 (&where, i);
- REALLOC (&secdata->rel, rel);
- struct relocation *cur = secdata->rel.rel + secdata->rel.size++;
+ 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, secdata->rel.type);
+ = get_rel_or_rela (reldata, i, &rela_mem, sec->rel.type);
if (rela == NULL)
{
wr_error (&where, ": couldn't read relocation.\n");
where_reset_2 (&where, cur->offset);
- Elf_Type type = ebl_reloc_simple_type (secdata->file->ebl, cur->type);
+ Elf_Type type = ebl_reloc_simple_type (file->ebl, cur->type);
int width;
switch (type)
{
char buf[64];
wr_error (&where, ": 8 or 16-bit relocation type %s.\n",
- ebl_reloc_type_name (secdata->file->ebl,
- cur->type, buf, sizeof (buf)));
+ ebl_reloc_type_name (file->ebl, cur->type,
+ buf, sizeof (buf)));
goto skip;
}
char buf[64];
wr_error (&where, ": invalid relocation %d (%s).\n",
cur->type,
- ebl_reloc_type_name (secdata->file->ebl,
- cur->type, buf, sizeof (buf)));
+ ebl_reloc_type_name (file->ebl, cur->type,
+ buf, sizeof (buf)));
goto skip;
}
};
- if (cur->offset + width >= secdata->data->d_size)
+ if (cur->offset + width >= sec->data->d_size)
{
wr_error (&where,
": relocation doesn't fall into relocated section.\n");
uint64_t value;
if (width == 4)
- value = read_4ubyte_unaligned (secdata->file->dwarf,
- secdata->data->d_buf + cur->offset);
+ value = dwarflint_read_4ubyte_unaligned
+ (file, sec->data->d_buf + cur->offset);
else
{
assert (width == 8);
- value = read_8ubyte_unaligned (secdata->file->dwarf,
- secdata->data->d_buf + cur->offset);
+ value = dwarflint_read_8ubyte_unaligned
+ (file, sec->data->d_buf + cur->offset);
}
if (is_rela)
- ((struct relocation *)b)->offset;
}
- qsort (secdata->rel.rel, secdata->rel.size,
- sizeof (*secdata->rel.rel), &compare);
+ qsort (sec->rel.rel, sec->rel.size,
+ sizeof (*sec->rel.rel), &compare);
return true;
}
static bool
-check_line_structural (struct section_data *data,
+check_line_structural (struct elf_file *file,
+ struct sec *sec,
struct cu *cu_chain)
{
struct read_ctx ctx;
- read_ctx_init (&ctx, data->file->dwarf, data->data);
+ read_ctx_init (&ctx, file, sec->data);
bool retval = true;
struct addr_record line_tables;
while (!read_ctx_eof (&ctx))
{
- struct where where = WHERE_SECDATA (data, NULL);
+ struct where where = WHERE (sec->id, NULL);
uint64_t set_offset = read_ctx_get_offset (&ctx);
where_reset_1 (&where, set_offset);
addr_record_add (&line_tables, set_offset);
{
uint64_t ctx_offset = read_ctx_get_offset (&sub_ctx);
uint64_t addr;
- if (!read_ctx_read_offset (&sub_ctx, data->file->addr_64, &addr))
+ if (!read_ctx_read_offset (&sub_ctx,
+ file->addr_64, &addr))
{
wr_error (&where, ": can't read operand of DW_LNE_set_address.\n");
goto skip;
}
struct relocation *rel;
- if ((rel = relocation_next (&data->rel, ctx_offset,
+ if ((rel = relocation_next (&sec->rel, ctx_offset,
&where, skip_mismatched)))
- relocate_one (&data->rel, rel, data->file->addr_64 ? 8 : 4,
+ relocate_one (file, &sec->rel, rel,
+ file->addr_64 ? 8 : 4,
&addr, &where, rel_address, NULL);
- else if (data->file->ehdr.e_type == ET_REL)
+ else if (file->ehdr.e_type == ET_REL)
wr_message (mc_impact_2 | mc_line | mc_reloc, &where,
PRI_LACK_RELOCATION, "DW_LNE_set_address");
break;
if (retval)
{
- relocation_skip_rest (data);
+ relocation_skip_rest (sec);
for (struct cu *cu = cu_chain; cu != NULL; cu = cu->next)
for (size_t i = 0; i < cu->line_refs.size; ++i)