447 lines
15 KiB
Diff
447 lines
15 KiB
Diff
|
commit 6ba977ed6c7ac6e51350f2093ebe0b90ff89f90c
|
||
|
Author: Mark Wielaard <mark@klomp.org>
|
||
|
Date: Sun Jul 23 23:14:31 2023 +0200
|
||
|
|
||
|
libelf, readelf, elflint: Add RELR support
|
||
|
|
||
|
Handle RELR as defined here:
|
||
|
https://groups.google.com/g/generic-abi/c/bX460iggiKg/m/YT2RrjpMAwAJ
|
||
|
|
||
|
Introduce new ELF_T_RELR Elf_Type and handle it for SHT_RELR. Check
|
||
|
various properties in elflint. Print RELR relocations in
|
||
|
readelf. Just the entries with -U. Just the addresses with -N. And
|
||
|
addresses pluse symbol/offsets by default.
|
||
|
|
||
|
* libebl/eblsectiontypename.c (ebl_section_type_name): Add RELR
|
||
|
to knownstype.
|
||
|
* libelf/elf32_updatenull.c (updatenull_wrlock): Handle
|
||
|
sh_entsize for SHT_RELR.
|
||
|
* libelf/gelf.h (Gelf_Relr): New typedef for Elf64_Relr.
|
||
|
* libelf/gelf_fsize.c (__libelf_type_sizes): Add ELF_T_RELR.
|
||
|
* libelf/gelf_xlate.c (__elf_xfctstom): Likewise.
|
||
|
* libelf/gelf_xlate.h: Add RELR as FUNDAMENTAL.
|
||
|
* libelf/libelf.h (Elf_Type): Add ELF_T_RELR.
|
||
|
* libelf/libelfP.h: Define ELF32_FSZ_RELR and ELF64_FSZ_RELR.
|
||
|
* src/elflint.c (check_reloc_shdr): Check she_entsize for
|
||
|
ELF_T_RELR.
|
||
|
(check_relr): New function.
|
||
|
(check_dynamic): Handle DT_RELR.
|
||
|
(special_sections): Add SHT_RELR.
|
||
|
(check_sections): Call check_relr.
|
||
|
* src/readelf.c (print_relocs): Also accept a Dwfl_Module.
|
||
|
(handle_relocs_relr): New function.
|
||
|
(print_dwarf_addr): Make static and declare early.
|
||
|
(process_elf_file): Pass dwflmod to print_relocs.
|
||
|
(handle_dynamic): Handle DT_RELRSZ and DTRELRENT.
|
||
|
|
||
|
Signed-off-by: Mark Wielaard <mark@klomp.org>
|
||
|
|
||
|
diff --git a/libebl/eblsectiontypename.c b/libebl/eblsectiontypename.c
|
||
|
index 2008b95a..ade25d4a 100644
|
||
|
--- a/libebl/eblsectiontypename.c
|
||
|
+++ b/libebl/eblsectiontypename.c
|
||
|
@@ -61,7 +61,8 @@ ebl_section_type_name (Ebl *ebl, int section, char *buf, size_t len)
|
||
|
KNOWNSTYPE (FINI_ARRAY),
|
||
|
KNOWNSTYPE (PREINIT_ARRAY),
|
||
|
KNOWNSTYPE (GROUP),
|
||
|
- KNOWNSTYPE (SYMTAB_SHNDX)
|
||
|
+ KNOWNSTYPE (SYMTAB_SHNDX),
|
||
|
+ KNOWNSTYPE (RELR)
|
||
|
};
|
||
|
|
||
|
/* Handle standard names. */
|
||
|
diff --git a/libelf/elf32_updatenull.c b/libelf/elf32_updatenull.c
|
||
|
index 6c06e5e4..c5d26b00 100644
|
||
|
--- a/libelf/elf32_updatenull.c
|
||
|
+++ b/libelf/elf32_updatenull.c
|
||
|
@@ -256,6 +256,9 @@ __elfw2(LIBELFBITS,updatenull_wrlock) (Elf *elf, int *change_bop, size_t shnum)
|
||
|
case SHT_SUNW_syminfo:
|
||
|
sh_entsize = elf_typesize (LIBELFBITS, ELF_T_SYMINFO, 1);
|
||
|
break;
|
||
|
+ case SHT_RELR:
|
||
|
+ sh_entsize = elf_typesize (LIBELFBITS, ELF_T_RELR, 1);
|
||
|
+ break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
diff --git a/libelf/gelf.h b/libelf/gelf.h
|
||
|
index 7a3c87aa..f032d7e1 100644
|
||
|
--- a/libelf/gelf.h
|
||
|
+++ b/libelf/gelf.h
|
||
|
@@ -82,6 +82,9 @@ typedef Elf64_Rel GElf_Rel;
|
||
|
/* Relocation table entry with addend (in section of type SHT_RELA). */
|
||
|
typedef Elf64_Rela GElf_Rela;
|
||
|
|
||
|
+/* Relative relocation entry (in section of type SHT_RELR). */
|
||
|
+typedef Elf64_Relr Gelf_Relr;
|
||
|
+
|
||
|
/* Program segment header. */
|
||
|
typedef Elf64_Phdr GElf_Phdr;
|
||
|
|
||
|
diff --git a/libelf/gelf_fsize.c b/libelf/gelf_fsize.c
|
||
|
index 493d7916..63bcbae5 100644
|
||
|
--- a/libelf/gelf_fsize.c
|
||
|
+++ b/libelf/gelf_fsize.c
|
||
|
@@ -69,7 +69,8 @@ const size_t __libelf_type_sizes[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||
|
[ELF_T_LIB] = sizeof (ElfW2(LIBELFBITS, Ext_Lib)), \
|
||
|
[ELF_T_AUXV] = sizeof (ElfW2(LIBELFBITS, Ext_auxv_t)), \
|
||
|
[ELF_T_CHDR] = sizeof (ElfW2(LIBELFBITS, Ext_Chdr)), \
|
||
|
- [ELF_T_GNUHASH] = ELFW2(LIBELFBITS, FSZ_WORD)
|
||
|
+ [ELF_T_GNUHASH] = ELFW2(LIBELFBITS, FSZ_WORD), \
|
||
|
+ [ELF_T_RELR] = ELFW2(LIBELFBITS, FSZ_RELR)
|
||
|
TYPE_SIZES (32)
|
||
|
},
|
||
|
[ELFCLASS64 - 1] = {
|
||
|
diff --git a/libelf/gelf_xlate.c b/libelf/gelf_xlate.c
|
||
|
index d8ad0634..749da1a1 100644
|
||
|
--- a/libelf/gelf_xlate.c
|
||
|
+++ b/libelf/gelf_xlate.c
|
||
|
@@ -204,7 +204,8 @@ const xfct_t __elf_xfctstom[ELFCLASSNUM - 1][ELF_T_NUM] =
|
||
|
[ELF_T_MOVE] = ElfW2(Bits, cvt_Move), \
|
||
|
[ELF_T_LIB] = ElfW2(Bits, cvt_Lib), \
|
||
|
[ELF_T_AUXV] = ElfW2(Bits, cvt_auxv_t), \
|
||
|
- [ELF_T_CHDR] = ElfW2(Bits, cvt_chdr)
|
||
|
+ [ELF_T_CHDR] = ElfW2(Bits, cvt_chdr), \
|
||
|
+ [ELF_T_RELR] = ElfW2(Bits, cvt_Relr)
|
||
|
define_xfcts (32),
|
||
|
[ELF_T_GNUHASH] = Elf32_cvt_Word
|
||
|
},
|
||
|
diff --git a/libelf/gelf_xlate.h b/libelf/gelf_xlate.h
|
||
|
index 3c0e4bf6..d5511c34 100644
|
||
|
--- a/libelf/gelf_xlate.h
|
||
|
+++ b/libelf/gelf_xlate.h
|
||
|
@@ -36,6 +36,7 @@ FUNDAMENTAL (WORD, Word, LIBELFBITS);
|
||
|
FUNDAMENTAL (SWORD, Sword, LIBELFBITS);
|
||
|
FUNDAMENTAL (XWORD, Xword, LIBELFBITS);
|
||
|
FUNDAMENTAL (SXWORD, Sxword, LIBELFBITS);
|
||
|
+FUNDAMENTAL (RELR, Relr, LIBELFBITS);
|
||
|
|
||
|
/* The structured types. */
|
||
|
TYPE (Ehdr, LIBELFBITS)
|
||
|
diff --git a/libelf/libelf.h b/libelf/libelf.h
|
||
|
index 2374a48a..2837db72 100644
|
||
|
--- a/libelf/libelf.h
|
||
|
+++ b/libelf/libelf.h
|
||
|
@@ -124,6 +124,7 @@ typedef enum
|
||
|
ELF_T_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */
|
||
|
ELF_T_NHDR8, /* Special GNU Properties note. Same as Nhdr,
|
||
|
except padding. */
|
||
|
+ ELF_T_RELR, /* Relative relocation entry. */
|
||
|
/* Keep this the last entry. */
|
||
|
ELF_T_NUM
|
||
|
} Elf_Type;
|
||
|
diff --git a/libelf/libelfP.h b/libelf/libelfP.h
|
||
|
index d3c241e5..96476064 100644
|
||
|
--- a/libelf/libelfP.h
|
||
|
+++ b/libelf/libelfP.h
|
||
|
@@ -63,6 +63,7 @@
|
||
|
#define ELF32_FSZ_SWORD 4
|
||
|
#define ELF32_FSZ_XWORD 8
|
||
|
#define ELF32_FSZ_SXWORD 8
|
||
|
+#define ELF32_FSZ_RELR 4
|
||
|
|
||
|
/* Same for 64 bits objects. */
|
||
|
#define ELF64_FSZ_ADDR 8
|
||
|
@@ -72,6 +73,7 @@
|
||
|
#define ELF64_FSZ_SWORD 4
|
||
|
#define ELF64_FSZ_XWORD 8
|
||
|
#define ELF64_FSZ_SXWORD 8
|
||
|
+#define ELF64_FSZ_RELR 8
|
||
|
|
||
|
|
||
|
/* This is an extension of the ELF_F_* enumeration. The values here are
|
||
|
diff --git a/src/elflint.c b/src/elflint.c
|
||
|
index dd42dcb4..864de710 100644
|
||
|
--- a/src/elflint.c
|
||
|
+++ b/src/elflint.c
|
||
|
@@ -1,5 +1,6 @@
|
||
|
/* Pedantic checking of ELF files compliance with gABI/psABI spec.
|
||
|
Copyright (C) 2001-2015, 2017, 2018 Red Hat, Inc.
|
||
|
+ Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
|
||
|
This file is part of elfutils.
|
||
|
Written by Ulrich Drepper <drepper@redhat.com>, 2001.
|
||
|
|
||
|
@@ -1291,10 +1292,20 @@ section [%2d] '%s': no relocations for merge-able string sections possible\n"),
|
||
|
|
||
|
size_t sh_entsize = gelf_fsize (ebl->elf, reltype, 1, EV_CURRENT);
|
||
|
if (shdr->sh_entsize != sh_entsize)
|
||
|
- ERROR (_(reltype == ELF_T_RELA ? "\
|
||
|
-section [%2d] '%s': section entry size does not match ElfXX_Rela\n" : "\
|
||
|
-section [%2d] '%s': section entry size does not match ElfXX_Rel\n"),
|
||
|
- idx, section_name (ebl, idx));
|
||
|
+ {
|
||
|
+ if (reltype == ELF_T_RELA)
|
||
|
+ ERROR ("\
|
||
|
+section [%2d] '%s': section entry size does not match ElfXX_Rela\n",
|
||
|
+ idx, section_name (ebl, idx));
|
||
|
+ else if (reltype == ELF_T_REL)
|
||
|
+ ERROR ("\
|
||
|
+section [%2d] '%s': section entry size does not match ElfXX_Rel\n",
|
||
|
+ idx, section_name (ebl, idx));
|
||
|
+ else
|
||
|
+ ERROR ("\
|
||
|
+section [%2d] '%s': section entry size does not match ElfXX_Relr\n",
|
||
|
+ idx, section_name (ebl, idx));
|
||
|
+ }
|
||
|
|
||
|
/* In preparation of checking whether relocations are text
|
||
|
relocations or not we need to determine whether the file is
|
||
|
@@ -1590,6 +1601,32 @@ section [%2d] '%s': cannot get relocation %zu: %s\n"),
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+static void
|
||
|
+check_relr (Ebl *ebl, GElf_Ehdr *ehdr, GElf_Shdr *shdr, int idx)
|
||
|
+{
|
||
|
+ Elf_Data *data = elf_getdata (elf_getscn (ebl->elf, idx), NULL);
|
||
|
+ if (data == NULL)
|
||
|
+ {
|
||
|
+ ERROR (_("section [%2d] '%s': cannot get section data\n"),
|
||
|
+ idx, section_name (ebl, idx));
|
||
|
+ return;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Check the fields of the section header. */
|
||
|
+ GElf_Shdr destshdr_mem;
|
||
|
+ GElf_Shdr *destshdr = NULL;
|
||
|
+ struct loaded_segment *loaded = NULL;
|
||
|
+ check_reloc_shdr (ebl, ehdr, shdr, idx, ELF_T_RELR, &destshdr,
|
||
|
+ &destshdr_mem, &loaded);
|
||
|
+
|
||
|
+ /* Just throw them away. */
|
||
|
+ while (loaded != NULL)
|
||
|
+ {
|
||
|
+ struct loaded_segment *old = loaded;
|
||
|
+ loaded = loaded->next;
|
||
|
+ free (old);
|
||
|
+ }
|
||
|
+}
|
||
|
|
||
|
/* Number of dynamic sections. */
|
||
|
static int ndynamic;
|
||
|
@@ -1780,6 +1817,7 @@ section [%2d] '%s': entry %zu: pointer does not match address of section [%2d] '
|
||
|
case DT_PLTGOT:
|
||
|
case DT_REL:
|
||
|
case DT_RELA:
|
||
|
+ case DT_RELR:
|
||
|
case DT_SYMBOLIC:
|
||
|
case DT_SYMTAB:
|
||
|
case DT_VERDEF:
|
||
|
@@ -3660,6 +3698,7 @@ static const struct
|
||
|
{ ".plt", 5, SHT_PROGBITS, unused, 0, 0 }, // XXX more tests
|
||
|
{ ".preinit_array", 15, SHT_PREINIT_ARRAY, exact, SHF_ALLOC | SHF_WRITE, 0 },
|
||
|
{ ".rela", 5, SHT_RELA, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
|
||
|
+ { ".relr", 5, SHT_RELR, atleast, 0, SHF_ALLOC }, // XXX more tests
|
||
|
{ ".rel", 4, SHT_REL, atleast, 0, SHF_ALLOC | SHF_INFO_LINK }, // XXX more tests
|
||
|
{ ".rodata", 8, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
|
||
|
{ ".rodata1", 9, SHT_PROGBITS, atleast, SHF_ALLOC, SHF_MERGE | SHF_STRINGS },
|
||
|
@@ -4182,6 +4221,10 @@ section [%2zu] '%s': relocatable files cannot have dynamic symbol tables\n"),
|
||
|
check_rel (ebl, ehdr, shdr, cnt);
|
||
|
break;
|
||
|
|
||
|
+ case SHT_RELR:
|
||
|
+ check_relr (ebl, ehdr, shdr, cnt);
|
||
|
+ break;
|
||
|
+
|
||
|
case SHT_DYNAMIC:
|
||
|
check_dynamic (ebl, ehdr, shdr, cnt);
|
||
|
break;
|
||
|
diff --git a/src/readelf.c b/src/readelf.c
|
||
|
index eda0ce09..db31ad09 100644
|
||
|
--- a/src/readelf.c
|
||
|
+++ b/src/readelf.c
|
||
|
@@ -1,5 +1,6 @@
|
||
|
/* Print information from ELF file in human-readable form.
|
||
|
Copyright (C) 1999-2018 Red Hat, Inc.
|
||
|
+ Copyright (C) 2023 Mark J. Wielaard <mark@klomp.org>
|
||
|
This file is part of elfutils.
|
||
|
|
||
|
This file is free software; you can redistribute it and/or modify
|
||
|
@@ -302,11 +302,13 @@
|
||
|
static void print_phdr (Ebl *ebl, GElf_Ehdr *ehdr);
|
||
|
static void print_scngrp (Ebl *ebl);
|
||
|
static void print_dynamic (Ebl *ebl);
|
||
|
-static void print_relocs (Ebl *ebl, GElf_Ehdr *ehdr);
|
||
|
+static void print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr);
|
||
|
static void handle_relocs_rel (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
|
||
|
GElf_Shdr *shdr);
|
||
|
static void handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn,
|
||
|
GElf_Shdr *shdr);
|
||
|
+static void handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn,
|
||
|
+ GElf_Shdr *shdr);
|
||
|
static bool print_symtab (Ebl *ebl, int type);
|
||
|
static void handle_symtab (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr);
|
||
|
static void print_verinfo (Ebl *ebl);
|
||
|
@@ -336,6 +339,8 @@ static void dump_data (Ebl *ebl);
|
||
|
static void dump_strings (Ebl *ebl);
|
||
|
static void print_strings (Ebl *ebl);
|
||
|
static void dump_archive_index (Elf *, const char *);
|
||
|
+static void print_dwarf_addr (Dwfl_Module *dwflmod, int address_size,
|
||
|
+ Dwarf_Addr address, Dwarf_Addr raw);
|
||
|
|
||
|
enum dyn_idx
|
||
|
{
|
||
|
@@ -1052,7 +1057,7 @@ process_elf_file (Dwfl_Module *dwflmod, int fd)
|
||
|
if (print_dynamic_table)
|
||
|
print_dynamic (ebl);
|
||
|
if (print_relocations)
|
||
|
- print_relocs (pure_ebl, ehdr);
|
||
|
+ print_relocs (pure_ebl, dwflmod, ehdr);
|
||
|
if (print_histogram)
|
||
|
handle_hash (ebl);
|
||
|
if (print_symbol_table || print_dynsym_table)
|
||
|
@@ -1971,9 +1976,11 @@ handle_dynamic (Ebl *ebl, Elf_Scn *scn, GElf_Shdr *shdr, GElf_Phdr *phdr)
|
||
|
case DT_RELASZ:
|
||
|
case DT_STRSZ:
|
||
|
case DT_RELSZ:
|
||
|
+ case DT_RELRSZ:
|
||
|
case DT_RELAENT:
|
||
|
case DT_SYMENT:
|
||
|
case DT_RELENT:
|
||
|
+ case DT_RELRENT:
|
||
|
case DT_PLTPADSZ:
|
||
|
case DT_MOVEENT:
|
||
|
case DT_MOVESZ:
|
||
|
@@ -2049,7 +2056,7 @@ print_dynamic (Ebl *ebl)
|
||
|
|
||
|
/* Print relocations. */
|
||
|
static void
|
||
|
-print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
|
||
|
+print_relocs (Ebl *ebl, Dwfl_Module *mod, GElf_Ehdr *ehdr)
|
||
|
{
|
||
|
/* Find all relocation sections and handle them. */
|
||
|
Elf_Scn *scn = NULL;
|
||
|
@@ -2066,6 +2073,8 @@ print_relocs (Ebl *ebl, GElf_Ehdr *ehdr)
|
||
|
handle_relocs_rel (ebl, ehdr, scn, shdr);
|
||
|
else if (shdr->sh_type == SHT_RELA)
|
||
|
handle_relocs_rela (ebl, ehdr, scn, shdr);
|
||
|
+ else if (shdr->sh_type == SHT_RELR)
|
||
|
+ handle_relocs_relr (ebl, mod, scn, shdr);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
@@ -2454,6 +2463,114 @@ handle_relocs_rela (Ebl *ebl, GElf_Ehdr *ehdr, Elf_Scn *scn, GElf_Shdr *shdr)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+/* Handle a relocation section. */
|
||
|
+static void
|
||
|
+handle_relocs_relr (Ebl *ebl, Dwfl_Module *mod, Elf_Scn *scn, GElf_Shdr *shdr)
|
||
|
+{
|
||
|
+ int class = gelf_getclass (ebl->elf);
|
||
|
+ size_t sh_entsize = gelf_fsize (ebl->elf, ELF_T_RELR, 1, EV_CURRENT);
|
||
|
+ int nentries = shdr->sh_size / sh_entsize;
|
||
|
+
|
||
|
+ /* Get the data of the section. */
|
||
|
+ Elf_Data *data = elf_getdata (scn, NULL);
|
||
|
+ if (data == NULL)
|
||
|
+ return;
|
||
|
+
|
||
|
+ /* Get the section header string table index. */
|
||
|
+ size_t shstrndx;
|
||
|
+ if (unlikely (elf_getshdrstrndx (ebl->elf, &shstrndx) < 0))
|
||
|
+ error_exit (0, _("cannot get section header string table index"));
|
||
|
+
|
||
|
+ /* A .relr.dyn section does not refer to a specific section. */
|
||
|
+ printf (ngettext ("\
|
||
|
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entry:\n",
|
||
|
+ "\
|
||
|
+\nRelocation section [%2u] '%s' at offset %#0" PRIx64 " contains %d entries:\n",
|
||
|
+ nentries),
|
||
|
+ (unsigned int) elf_ndxscn (scn),
|
||
|
+ elf_strptr (ebl->elf, shstrndx, shdr->sh_name),
|
||
|
+ shdr->sh_offset,
|
||
|
+ nentries);
|
||
|
+
|
||
|
+ if (class == ELFCLASS32)
|
||
|
+ {
|
||
|
+ uint32_t base = 0;
|
||
|
+ for (int cnt = 0; cnt < nentries; ++cnt)
|
||
|
+ {
|
||
|
+ Elf32_Word *words = data->d_buf;
|
||
|
+ Elf32_Word entry = words[cnt];
|
||
|
+
|
||
|
+ /* Just the raw entries? */
|
||
|
+ if (print_unresolved_addresses)
|
||
|
+ printf (" %#010" PRIx32 "%s\n", entry,
|
||
|
+ (entry & 1) == 0 ? " *" : "");
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* A real address, also sets base. */
|
||
|
+ if ((entry & 1) == 0)
|
||
|
+ {
|
||
|
+ printf (" ");
|
||
|
+ print_dwarf_addr (mod, 4, entry, entry);
|
||
|
+ printf (" *\n");
|
||
|
+
|
||
|
+ base = entry + 4;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Untangle address from base and bits. */
|
||
|
+ uint32_t addr;
|
||
|
+ for (addr = base; (entry >>= 1) != 0; addr += 4)
|
||
|
+ if ((entry & 1) != 0)
|
||
|
+ {
|
||
|
+ printf (" ");
|
||
|
+ print_dwarf_addr (mod, 4, addr, addr);
|
||
|
+ printf ("\n");
|
||
|
+ }
|
||
|
+ base += 4 * (4 * 8 - 1);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ uint64_t base = 0;
|
||
|
+ for (int cnt = 0; cnt < nentries; ++cnt)
|
||
|
+ {
|
||
|
+ Elf64_Xword *xwords = data->d_buf;
|
||
|
+ Elf64_Xword entry = xwords[cnt];
|
||
|
+
|
||
|
+ /* Just the raw entries? */
|
||
|
+ if (print_unresolved_addresses)
|
||
|
+ printf (" %#018" PRIx64 "%s\n", entry,
|
||
|
+ (entry & 1) == 0 ? " *" : "");
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* A real address, also sets base. */
|
||
|
+ if ((entry & 1) == 0)
|
||
|
+ {
|
||
|
+ printf (" ");
|
||
|
+ print_dwarf_addr (mod, 8, entry, entry);
|
||
|
+ printf (" *\n");
|
||
|
+
|
||
|
+ base = entry + 8;
|
||
|
+ }
|
||
|
+ else
|
||
|
+ {
|
||
|
+ /* Untangle address from base and bits. */
|
||
|
+ uint64_t addr;
|
||
|
+ for (addr = base; (entry >>= 1) != 0; addr += 8)
|
||
|
+ if ((entry & 1) != 0)
|
||
|
+ {
|
||
|
+ printf (" ");
|
||
|
+ print_dwarf_addr (mod, 8, addr, addr);
|
||
|
+ printf ("\n");
|
||
|
+ }
|
||
|
+ base += 8 * (8 * 8 - 1);
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+ }
|
||
|
+}
|
||
|
|
||
|
/* Print the program header. Return true if a symtab is printed,
|
||
|
false otherwise. */
|
||
|
@@ -4107,7 +4224,7 @@ get_debug_elf_data (Dwarf *dbg, Ebl *ebl, int idx, Elf_Scn *scn)
|
||
|
return elf_getdata (scn, NULL);
|
||
|
}
|
||
|
|
||
|
-void
|
||
|
+static void
|
||
|
print_dwarf_addr (Dwfl_Module *dwflmod,
|
||
|
int address_size, Dwarf_Addr address, Dwarf_Addr raw)
|
||
|
{
|