This is the mail archive of the elfutils-devel@sourceware.org mailing list for the elfutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Patch] Add support for printing SDT elf notes.


Hi,

Another small addition to make it possible to print the new sdt elf
notes that are appearing in more and more binaries these days. The
format is fairly simple to parse and has been added to the appropriate
libebl functions. ebl_object_note_type_name () has been changed to also
take the name of the note as argument, to facilitate printing the type
depending on name.

libebl/
    * libebl.h (ebl_object_note_type_name): Add const char *name arg.
    * eblhooks.h (object_note_type_name): Likewise.
    * eblopenbackend.c (default_object_note_type_name): Likewise.
    * eblobjnotetypename.c (ebl_object_note_type_name): Likewise.
    And print version if name is "stapsdt".
    * eblobjnote.c (ebl_object_note): Add output for "stapsdt" notes.
src/
    * readelf.c (handle_notes_data): Call ebl_object_note_type_name
    with note name.

Sample output of readelf -n:

Note section [35] '.note.stapsdt' of 708 bytes at offset 0x1c0:
  Owner          Data size  Type
  stapsdt               51  Version: 3
    PC: 0x2f690, Base: 0x158368, Semaphore: 0
    Provider: libc, Name: setjmp, Args: '4@%eax -4(a)4+4(%esp) 4@%ecx'
  stapsdt               44  Version: 3
    PC: 0x2f730, Base: 0x158368, Semaphore: 0
    Provider: libc, Name: setjmp, Args: '4@%eax -4@$1 4@%ecx'
  stapsdt               44  Version: 3
    PC: 0x2f772, Base: 0x158368, Semaphore: 0
    Provider: libc, Name: setjmp, Args: '4@%edx -4@$0 4@%ecx'
  stapsdt               50  Version: 3
    PC: 0x2f80e, Base: 0x158368, Semaphore: 0
    Provider: libc, Name: longjmp, Args: '4@%eax -4(a)8(%esp) 4@%edx'
  stapsdt               57  Version: 3
    PC: 0x2f81a, Base: 0x158368, Semaphore: 0
    Provider: libc, Name: longjmp_target, Args: '4@%eax -4(a)8(%esp) 4@%edx'
  stapsdt               51  Version: 3
[...]

Please let me know if you see any issues with the implementation before
I commit it. Patch attached and on the mjw/sdt git branch.

Thanks,

Mark
diff --git a/libebl/ebl-hooks.h b/libebl/ebl-hooks.h
index 82c6c64..a04b3db 100644
--- a/libebl/ebl-hooks.h
+++ b/libebl/ebl-hooks.h
@@ -111,7 +111,8 @@ const char *EBLHOOK(osabi_name) (int, char *, size_t);
 const char *EBLHOOK(core_note_type_name) (uint32_t, char *, size_t);
 
 /* Name of a note entry type for object files.  */
-const char *EBLHOOK(object_note_type_name) (uint32_t, char *, size_t);
+const char *EBLHOOK(object_note_type_name) (const char *, uint32_t,
+					    char *, size_t);
 
 /* Describe core note format.  */
 int EBLHOOK(core_note) (const GElf_Nhdr *, const char *,
diff --git a/libebl/eblobjnote.c b/libebl/eblobjnote.c
index b56c6cb..ec5bb7d 100644
--- a/libebl/eblobjnote.c
+++ b/libebl/eblobjnote.c
@@ -1,5 +1,5 @@
 /* Print contents of object file note.
-   Copyright (C) 2002, 2007, 2009 Red Hat, Inc.
+   Copyright (C) 2002, 2007, 2009, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -68,6 +68,94 @@ ebl_object_note (ebl, name, type, descsz, 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:
diff --git a/libebl/eblobjnotetypename.c b/libebl/eblobjnotetypename.c
index 8e99dbb..0ceb5a8 100644
--- a/libebl/eblobjnotetypename.c
+++ b/libebl/eblobjnotetypename.c
@@ -1,5 +1,5 @@
 /* Return note type name.
-   Copyright (C) 2002, 2007, 2009 Red Hat, Inc.
+   Copyright (C) 2002, 2007, 2009, 2011 Red Hat, Inc.
    This file is part of Red Hat elfutils.
    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
 
@@ -54,20 +54,28 @@
 
 #include <inttypes.h>
 #include <stdio.h>
+#include <string.h>
 #include <libeblP.h>
 
 
 const char *
-ebl_object_note_type_name (ebl, type, buf, len)
+ebl_object_note_type_name (ebl, name, type, buf, len)
      Ebl *ebl;
+     const char *name;
      uint32_t type;
      char *buf;
      size_t len;
 {
-  const char *res = ebl->object_note_type_name (type, buf, len);
+  const char *res = ebl->object_note_type_name (name, type, buf, len);
 
   if (res == NULL)
     {
+      if (strcmp (name, "stapsdt") == 0)
+	{
+	  snprintf (buf, len, "Version: %" PRIu32, type);
+	  return buf;
+	}
+
       static const char *knowntypes[] =
 	{
 #define KNOWNSTYPE(name) [NT_##name] = #name
diff --git a/libebl/eblopenbackend.c b/libebl/eblopenbackend.c
index 24f472c..60e7f84 100644
--- a/libebl/eblopenbackend.c
+++ b/libebl/eblopenbackend.c
@@ -184,8 +184,8 @@ static const char *default_osabi_name (int ignore, char *buf, size_t len);
 static void default_destr (struct ebl *ignore);
 static const char *default_core_note_type_name (uint32_t, char *buf,
 						size_t len);
-static const char *default_object_note_type_name (uint32_t, char *buf,
-						  size_t len);
+static const char *default_object_note_type_name (const char *name, uint32_t,
+						  char *buf, size_t len);
 static int default_core_note (const GElf_Nhdr *nhdr, const char *name,
 			      GElf_Word *regs_offset, size_t *nregloc,
 			      const Ebl_Register_Location **reglocs,
@@ -619,7 +619,8 @@ default_core_note (const GElf_Nhdr *nhdr __attribute__ ((unused)),
 }
 
 static const char *
-default_object_note_type_name (uint32_t ignore __attribute__ ((unused)),
+default_object_note_type_name (const char *name __attribute__ ((unused)),
+			       uint32_t ignore __attribute__ ((unused)),
 			       char *buf __attribute__ ((unused)),
 			       size_t len __attribute__ ((unused)))
 {
diff --git a/libebl/libebl.h b/libebl/libebl.h
index b430728..3a33402 100644
--- a/libebl/libebl.h
+++ b/libebl/libebl.h
@@ -184,8 +184,9 @@ extern const char *ebl_core_note_type_name (Ebl *ebl, uint32_t type, char *buf,
 					    size_t len);
 
 /* Return name of the note section type for an object file.  */
-extern const char *ebl_object_note_type_name (Ebl *ebl, uint32_t type,
-					      char *buf, size_t len);
+extern const char *ebl_object_note_type_name (Ebl *ebl, const char *name,
+					      uint32_t type, char *buf,
+					      size_t len);
 
 /* Print information about object note if available.  */
 extern void ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
diff --git a/src/readelf.c b/src/readelf.c
index f2c4800..efc3571 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -7904,7 +7904,7 @@ handle_notes_data (Ebl *ebl, const GElf_Ehdr *ehdr,
 	      ehdr->e_type == ET_CORE
 	      ? ebl_core_note_type_name (ebl, nhdr.n_type,
 					 buf, sizeof (buf))
-	      : ebl_object_note_type_name (ebl, nhdr.n_type,
+	      : ebl_object_note_type_name (ebl, name, nhdr.n_type,
 					   buf2, sizeof (buf2)));
 
       /* Filter out invalid entries.  */

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]