mirror of
https://github.com/autc04/Retro68.git
synced 2024-12-02 03:50:17 +00:00
d21be3b4e1
(from https://sourceware.org/elfutils/, GPL/LGPL licensed)
234 lines
5.6 KiB
C
234 lines
5.6 KiB
C
/* Print contents of object file note.
|
|
Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016 Red Hat, Inc.
|
|
This file is part of elfutils.
|
|
Written by Ulrich Drepper <drepper@redhat.com>, 2002.
|
|
|
|
This file is free software; you can redistribute it and/or modify
|
|
it under the terms of either
|
|
|
|
* the GNU Lesser General Public License as published by the Free
|
|
Software Foundation; either version 3 of the License, or (at
|
|
your option) any later version
|
|
|
|
or
|
|
|
|
* the GNU General Public License as published by the Free
|
|
Software Foundation; either version 2 of the License, or (at
|
|
your option) any later version
|
|
|
|
or both in parallel, as here.
|
|
|
|
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 copies of the GNU General Public License and
|
|
the GNU Lesser General Public License along with this program. If
|
|
not, see <http://www.gnu.org/licenses/>. */
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
# include <config.h>
|
|
#endif
|
|
|
|
#include <inttypes.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <libeblP.h>
|
|
|
|
|
|
void
|
|
ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
|
|
uint32_t descsz, const char *desc)
|
|
{
|
|
if (! ebl->object_note (name, type, descsz, desc))
|
|
{
|
|
/* The machine specific function did not know this type. */
|
|
|
|
if (strcmp ("stapsdt", name) == 0)
|
|
{
|
|
if (type != 3)
|
|
{
|
|
printf (gettext ("unknown SDT version %u\n"), type);
|
|
return;
|
|
}
|
|
|
|
/* Descriptor starts with three addresses, pc, base ref and
|
|
semaphore. Then three zero terminated strings provider,
|
|
name and arguments. */
|
|
|
|
union
|
|
{
|
|
Elf64_Addr a64[3];
|
|
Elf32_Addr a32[3];
|
|
} addrs;
|
|
|
|
size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
|
|
if (descsz < addrs_size + 3)
|
|
{
|
|
invalid_sdt:
|
|
printf (gettext ("invalid SDT probe descriptor\n"));
|
|
return;
|
|
}
|
|
|
|
Elf_Data src =
|
|
{
|
|
.d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
|
|
.d_buf = (void *) desc, .d_size = addrs_size
|
|
};
|
|
|
|
Elf_Data dst =
|
|
{
|
|
.d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
|
|
.d_buf = &addrs, .d_size = addrs_size
|
|
};
|
|
|
|
if (gelf_xlatetom (ebl->elf, &dst, &src,
|
|
elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
|
|
{
|
|
printf ("%s\n", elf_errmsg (-1));
|
|
return;
|
|
}
|
|
|
|
const char *provider = desc + addrs_size;
|
|
const char *pname = memchr (provider, '\0', desc + descsz - provider);
|
|
if (pname == NULL)
|
|
goto invalid_sdt;
|
|
|
|
++pname;
|
|
const char *args = memchr (pname, '\0', desc + descsz - pname);
|
|
if (args == NULL ||
|
|
memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
|
|
goto invalid_sdt;
|
|
|
|
GElf_Addr pc;
|
|
GElf_Addr base;
|
|
GElf_Addr sem;
|
|
if (gelf_getclass (ebl->elf) == ELFCLASS32)
|
|
{
|
|
pc = addrs.a32[0];
|
|
base = addrs.a32[1];
|
|
sem = addrs.a32[2];
|
|
}
|
|
else
|
|
{
|
|
pc = addrs.a64[0];
|
|
base = addrs.a64[1];
|
|
sem = addrs.a64[2];
|
|
}
|
|
|
|
printf (gettext (" PC: "));
|
|
printf ("%#" PRIx64 ",", pc);
|
|
printf (gettext (" Base: "));
|
|
printf ("%#" PRIx64 ",", base);
|
|
printf (gettext (" Semaphore: "));
|
|
printf ("%#" PRIx64 "\n", sem);
|
|
printf (gettext (" Provider: "));
|
|
printf ("%s,", provider);
|
|
printf (gettext (" Name: "));
|
|
printf ("%s,", pname);
|
|
printf (gettext (" Args: "));
|
|
printf ("'%s'\n", args);
|
|
return;
|
|
}
|
|
|
|
switch (type)
|
|
{
|
|
case NT_GNU_BUILD_ID:
|
|
if (strcmp (name, "GNU") == 0 && descsz > 0)
|
|
{
|
|
printf (gettext (" Build ID: "));
|
|
uint_fast32_t i;
|
|
for (i = 0; i < descsz - 1; ++i)
|
|
printf ("%02" PRIx8, (uint8_t) desc[i]);
|
|
printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
|
|
}
|
|
break;
|
|
|
|
case NT_GNU_GOLD_VERSION:
|
|
if (strcmp (name, "GNU") == 0 && descsz > 0)
|
|
/* A non-null terminated version string. */
|
|
printf (gettext (" Linker version: %.*s\n"),
|
|
(int) descsz, desc);
|
|
break;
|
|
|
|
case NT_GNU_ABI_TAG:
|
|
if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0)
|
|
{
|
|
Elf_Data in =
|
|
{
|
|
.d_version = EV_CURRENT,
|
|
.d_type = ELF_T_WORD,
|
|
.d_size = descsz,
|
|
.d_buf = (void *) desc
|
|
};
|
|
/* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes). If it
|
|
is much (4*) larger dynamically allocate memory to convert. */
|
|
#define FIXED_TAG_BYTES 16
|
|
uint32_t sbuf[FIXED_TAG_BYTES];
|
|
uint32_t *buf;
|
|
if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
|
|
{
|
|
buf = malloc (descsz);
|
|
if (unlikely (buf == NULL))
|
|
return;
|
|
}
|
|
else
|
|
buf = sbuf;
|
|
Elf_Data out =
|
|
{
|
|
.d_version = EV_CURRENT,
|
|
.d_type = ELF_T_WORD,
|
|
.d_size = descsz,
|
|
.d_buf = buf
|
|
};
|
|
|
|
if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
|
|
{
|
|
const char *os;
|
|
switch (buf[0])
|
|
{
|
|
case ELF_NOTE_OS_LINUX:
|
|
os = "Linux";
|
|
break;
|
|
|
|
case ELF_NOTE_OS_GNU:
|
|
os = "GNU";
|
|
break;
|
|
|
|
case ELF_NOTE_OS_SOLARIS2:
|
|
os = "Solaris";
|
|
break;
|
|
|
|
case ELF_NOTE_OS_FREEBSD:
|
|
os = "FreeBSD";
|
|
break;
|
|
|
|
default:
|
|
os = "???";
|
|
break;
|
|
}
|
|
|
|
printf (gettext (" OS: %s, ABI: "), os);
|
|
for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
|
|
{
|
|
if (cnt > 1)
|
|
putchar_unlocked ('.');
|
|
printf ("%" PRIu32, buf[cnt]);
|
|
}
|
|
putchar_unlocked ('\n');
|
|
}
|
|
if (descsz / 4 > FIXED_TAG_BYTES)
|
|
free (buf);
|
|
break;
|
|
}
|
|
/* FALLTHROUGH */
|
|
|
|
default:
|
|
/* Unknown type. */
|
|
break;
|
|
}
|
|
}
|
|
}
|