summaryrefslogtreecommitdiffstats
path: root/libebl/eblobjnote.c
diff options
context:
space:
mode:
Diffstat (limited to 'libebl/eblobjnote.c')
-rw-r--r--libebl/eblobjnote.c346
1 files changed, 343 insertions, 3 deletions
diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
index ca4f155d..58ac86d7 100644
--- a/libebl/eblobjnote.c
+++ b/libebl/eblobjnote.c
@@ -1,5 +1,5 @@
/* Print contents of object file note.
- Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016 Red Hat, Inc.
+ Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016, 2018 Red Hat, Inc.
This file is part of elfutils.
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -37,9 +37,14 @@
#include <string.h>
#include <libeblP.h>
+#include "common.h"
+#include "libelfP.h"
+#include "libdwP.h"
+#include "memory-access.h"
+
void
-ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
+ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type,
uint32_t descsz, const char *desc)
{
if (! ebl->object_note (name, type, descsz, desc))
@@ -133,6 +138,160 @@ ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
return;
}
+ if (strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
+ strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0
+ && (type == NT_GNU_BUILD_ATTRIBUTE_OPEN
+ || type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
+ {
+ /* There might or might not be a pair of addresses in the desc. */
+ if (descsz > 0)
+ {
+ printf (" Address Range: ");
+
+ union
+ {
+ Elf64_Addr a64[2];
+ Elf32_Addr a32[2];
+ } addrs;
+
+ size_t addr_size = gelf_fsize (ebl->elf, ELF_T_ADDR,
+ 2, EV_CURRENT);
+ if (descsz != addr_size)
+ printf ("<unknown data>\n");
+ else
+ {
+ Elf_Data src =
+ {
+ .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+ .d_buf = (void *) desc, .d_size = descsz
+ };
+
+ Elf_Data dst =
+ {
+ .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
+ .d_buf = &addrs, .d_size = descsz
+ };
+
+ if (gelf_xlatetom (ebl->elf, &dst, &src,
+ elf_getident (ebl->elf,
+ NULL)[EI_DATA]) == NULL)
+ printf ("%s\n", elf_errmsg (-1));
+ else
+ {
+ if (addr_size == 4)
+ printf ("%#" PRIx32 " - %#" PRIx32 "\n",
+ addrs.a32[0], addrs.a32[1]);
+ else
+ printf ("%#" PRIx64 " - %#" PRIx64 "\n",
+ addrs.a64[0], addrs.a64[1]);
+ }
+ }
+ }
+
+ /* Most data actually is inside the name.
+ https://fedoraproject.org/wiki/Toolchain/Watermark */
+
+ /* We need at least 2 chars of data to describe the
+ attribute and value encodings. */
+ const char *data = (name
+ + strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX));
+ if (namesz < 2)
+ {
+ printf ("<insufficient data>\n");
+ return;
+ }
+
+ printf (" ");
+
+ /* In most cases the value comes right after the encoding bytes. */
+ const char *value = &data[2];
+ switch (data[1])
+ {
+ case GNU_BUILD_ATTRIBUTE_VERSION:
+ printf ("VERSION: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_STACK_PROT:
+ printf ("STACK_PROT: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_RELRO:
+ printf ("RELRO: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
+ printf ("STACK_SIZE: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_TOOL:
+ printf ("TOOL: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_ABI:
+ printf ("ABI: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_PIC:
+ printf ("PIC: ");
+ break;
+ case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
+ printf ("SHORT_ENUM: ");
+ break;
+ case 32 ... 126:
+ printf ("\"%s\": ", &data[1]);
+ value += strlen (&data[1]) + 1;
+ break;
+ default:
+ printf ("<unknown>: ");
+ break;
+ }
+
+ switch (data[0])
+ {
+ case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
+ {
+ /* Any numbers are always in (unsigned) little endian. */
+ static const Dwarf dbg
+ = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
+ size_t bytes = namesz - (value - name);
+ uint64_t val;
+ if (bytes == 1)
+ val = *(unsigned char *) value;
+ else if (bytes == 2)
+ val = read_2ubyte_unaligned (&dbg, value);
+ else if (bytes == 4)
+ val = read_4ubyte_unaligned (&dbg, value);
+ else if (bytes == 8)
+ val = read_8ubyte_unaligned (&dbg, value);
+ else
+ goto unknown;
+ printf ("%" PRIx64, val);
+ }
+ break;
+ case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
+ printf ("\"%s\"", value);
+ break;
+ case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
+ printf ("TRUE");
+ break;
+ case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
+ printf ("FALSE");
+ break;
+ default:
+ {
+ unknown:
+ printf ("<unknown>");
+ }
+ break;
+ }
+
+ printf ("\n");
+
+ return;
+ }
+
+ /* NT_VERSION doesn't have any info. All data is in the name. */
+ if (descsz == 0 && type == NT_VERSION)
+ return;
+
+ /* Everything else should have the "GNU" owner name. */
+ if (strcmp ("GNU", name) != 0)
+ return;
+
switch (type)
{
case NT_GNU_BUILD_ID:
@@ -153,8 +312,189 @@ ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
(int) descsz, desc);
break;
+ case NT_GNU_PROPERTY_TYPE_0:
+ if (strcmp (name, "GNU") == 0 && descsz > 0)
+ {
+ /* There are at least 2 words. type and datasz. */
+ while (descsz >= 8)
+ {
+ struct pr_prop
+ {
+ GElf_Word pr_type;
+ GElf_Word pr_datasz;
+ } prop;
+
+ Elf_Data in =
+ {
+ .d_version = EV_CURRENT,
+ .d_type = ELF_T_WORD,
+ .d_size = 8,
+ .d_buf = (void *) desc
+ };
+ Elf_Data out =
+ {
+ .d_version = EV_CURRENT,
+ .d_type = ELF_T_WORD,
+ .d_size = descsz,
+ .d_buf = (void *) &prop
+ };
+
+ if (gelf_xlatetom (ebl->elf, &out, &in,
+ elf_getident (ebl->elf,
+ NULL)[EI_DATA]) == NULL)
+ {
+ printf ("%s\n", elf_errmsg (-1));
+ return;
+ }
+
+ desc += 8;
+ descsz -= 8;
+
+ int elfclass = gelf_getclass (ebl->elf);
+ char *elfident = elf_getident (ebl->elf, NULL);
+ GElf_Ehdr ehdr;
+ gelf_getehdr (ebl->elf, &ehdr);
+
+ /* Prefix. */
+ printf (" ");
+ if (prop.pr_type == GNU_PROPERTY_STACK_SIZE)
+ {
+ printf ("STACK_SIZE ");
+ if (prop.pr_datasz == 4 || prop.pr_datasz == 8)
+ {
+ GElf_Addr addr;
+ in.d_type = ELF_T_ADDR;
+ out.d_type = ELF_T_ADDR;
+ in.d_size = prop.pr_datasz;
+ out.d_size = sizeof (addr);
+ in.d_buf = (void *) desc;
+ out.d_buf = (void *) &addr;
+
+ if (gelf_xlatetom (ebl->elf, &out, &in,
+ elfident[EI_DATA]) == NULL)
+ {
+ printf ("%s\n", elf_errmsg (-1));
+ return;
+ }
+ printf ("%#" PRIx64 "\n", addr);
+ }
+ else
+ printf (" (garbage datasz: %" PRIx32 ")\n",
+ prop.pr_datasz);
+ }
+ else if (prop.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
+ {
+ printf ("NO_COPY_ON_PROTECTION");
+ if (prop.pr_datasz == 0)
+ printf ("\n");
+ else
+ printf (" (garbage datasz: %" PRIx32 ")\n",
+ prop.pr_datasz);
+ }
+ else if (prop.pr_type >= GNU_PROPERTY_LOPROC
+ && prop.pr_type <= GNU_PROPERTY_HIPROC
+ && (ehdr.e_machine == EM_386
+ || ehdr.e_machine == EM_X86_64))
+ {
+ printf ("X86 ");
+ if (prop.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND)
+ {
+ printf ("FEATURE_1_AND: ");
+
+ if (prop.pr_datasz == 4)
+ {
+ GElf_Word data;
+ in.d_type = ELF_T_WORD;
+ out.d_type = ELF_T_WORD;
+ in.d_size = 4;
+ out.d_size = 4;
+ in.d_buf = (void *) desc;
+ out.d_buf = (void *) &data;
+
+ if (gelf_xlatetom (ebl->elf, &out, &in,
+ elfident[EI_DATA]) == NULL)
+ {
+ printf ("%s\n", elf_errmsg (-1));
+ return;
+ }
+ printf ("%08" PRIx32 " ", data);
+
+ if ((data & GNU_PROPERTY_X86_FEATURE_1_IBT)
+ != 0)
+ {
+ printf ("IBT");
+ data &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
+ if (data != 0)
+ printf (" ");
+ }
+
+ if ((data & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
+ != 0)
+ {
+ printf ("SHSTK");
+ data &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
+ if (data != 0)
+ printf (" ");
+ }
+
+ if (data != 0)
+ printf ("UNKNOWN");
+ }
+ else
+ printf ("<bad datasz: %" PRId32 ">",
+ prop.pr_datasz);
+
+ printf ("\n");
+ }
+ else
+ {
+ printf ("%#" PRIx32, prop.pr_type);
+ if (prop.pr_datasz > 0)
+ {
+ printf (" data: ");
+ size_t i;
+ for (i = 0; i < prop.pr_datasz - 1; i++)
+ printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+ printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+ }
+ }
+ }
+ else
+ {
+ if (prop.pr_type >= GNU_PROPERTY_LOPROC
+ && prop.pr_type <= GNU_PROPERTY_HIPROC)
+ printf ("proc_type %#" PRIx32, prop.pr_type);
+ else if (prop.pr_type >= GNU_PROPERTY_LOUSER
+ && prop.pr_type <= GNU_PROPERTY_HIUSER)
+ printf ("app_type %#" PRIx32, prop.pr_type);
+ else
+ printf ("unknown_type %#" PRIx32, prop.pr_type);
+
+ if (prop.pr_datasz > 0)
+ {
+ printf (" data: ");
+ size_t i;
+ for (i = 0; i < prop.pr_datasz - 1; i++)
+ printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
+ printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
+ }
+ }
+ if (elfclass == ELFCLASS32)
+ {
+ desc += NOTE_ALIGN4 (prop.pr_datasz);
+ descsz -= NOTE_ALIGN4 (prop.pr_datasz);
+ }
+ else
+ {
+ desc += NOTE_ALIGN8 (prop.pr_datasz);
+ descsz -= NOTE_ALIGN8 (prop.pr_datasz);
+ }
+ }
+ }
+ break;
+
case NT_GNU_ABI_TAG:
- if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0)
+ if (descsz >= 8 && descsz % 4 == 0)
{
Elf_Data in =
{