1/* Print contents of object file note.
2   Copyright (C) 2002, 2007, 2009, 2011 Red Hat, Inc.
3   This file is part of Red Hat elfutils.
4   Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
6   Red Hat elfutils is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by the
8   Free Software Foundation; version 2 of the License.
9
10   Red Hat elfutils is distributed in the hope that it will be useful, but
11   WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License along
16   with Red Hat elfutils; if not, write to the Free Software Foundation,
17   Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 USA.
18
19   In addition, as a special exception, Red Hat, Inc. gives You the
20   additional right to link the code of Red Hat elfutils with code licensed
21   under any Open Source Initiative certified open source license
22   (http://www.opensource.org/licenses/index.php) which requires the
23   distribution of source code with any binary distribution and to
24   distribute linked combinations of the two.  Non-GPL Code permitted under
25   this exception must only link to the code of Red Hat elfutils through
26   those well defined interfaces identified in the file named EXCEPTION
27   found in the source code files (the "Approved Interfaces").  The files
28   of Non-GPL Code may instantiate templates or use macros or inline
29   functions from the Approved Interfaces without causing the resulting
30   work to be covered by the GNU General Public License.  Only Red Hat,
31   Inc. may make changes or additions to the list of Approved Interfaces.
32   Red Hat's grant of this exception is conditioned upon your not adding
33   any new exceptions.  If you wish to add a new Approved Interface or
34   exception, please contact Red Hat.  You must obey the GNU General Public
35   License in all respects for all of the Red Hat elfutils code and other
36   code used in conjunction with Red Hat elfutils except the Non-GPL Code
37   covered by this exception.  If you modify this file, you may extend this
38   exception to your version of the file, but you are not obligated to do
39   so.  If you do not wish to provide this exception without modification,
40   you must delete this exception statement from your version and license
41   this file solely under the GPL without exception.
42
43   Red Hat elfutils is an included package of the Open Invention Network.
44   An included package of the Open Invention Network is a package for which
45   Open Invention Network licensees cross-license their patents.  No patent
46   license is granted, either expressly or impliedly, by designation as an
47   included package.  Should you wish to participate in the Open Invention
48   Network licensing program, please visit www.openinventionnetwork.com
49   <http://www.openinventionnetwork.com>.  */
50
51#ifdef HAVE_CONFIG_H
52# include <config.h>
53#endif
54
55#include <inttypes.h>
56#include <stdio.h>
57#include <string.h>
58#include <libeblP.h>
59
60
61void
62ebl_object_note (ebl, name, type, descsz, desc)
63     Ebl *ebl;
64     const char *name;
65     uint32_t type;
66     uint32_t descsz;
67     const char *desc;
68{
69  if (! ebl->object_note (name, type, descsz, desc))
70    /* The machine specific function did not know this type.  */
71
72    if (strcmp ("stapsdt", name) == 0)
73      {
74	if (type != 3)
75	  {
76	    printf (gettext ("unknown SDT version %u\n"), type);
77	    return;
78	  }
79
80	/* Descriptor starts with three addresses, pc, base ref and
81	   semaphore.  Then three zero terminated strings provider,
82	   name and arguments.  */
83
84	union
85	{
86	  Elf64_Addr a64[3];
87	  Elf32_Addr a32[3];
88	} addrs;
89
90	size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
91	if (descsz < addrs_size + 3)
92	  {
93	  invalid_sdt:
94	    printf (gettext ("invalid SDT probe descriptor\n"));
95	    return;
96	  }
97
98	Elf_Data src =
99	  {
100	    .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
101	    .d_buf = (void *) desc, .d_size = addrs_size
102	  };
103
104	Elf_Data dst =
105	  {
106	    .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
107	    .d_buf = &addrs, .d_size = addrs_size
108	  };
109
110	if (gelf_xlatetom (ebl->elf, &dst, &src,
111			   elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
112	  {
113	    printf ("%s\n", elf_errmsg (-1));
114	    return;
115	  }
116
117	const char *provider = desc + addrs_size;
118	const char *pname = memchr (provider, '\0', desc + descsz - provider);
119	if (pname == NULL)
120	  goto invalid_sdt;
121
122	++pname;
123	const char *args = memchr (pname, '\0', desc + descsz - pname);
124	if (args == NULL ||
125	    memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
126	  goto invalid_sdt;
127
128	GElf_Addr pc;
129	GElf_Addr base;
130	GElf_Addr sem;
131	if (gelf_getclass (ebl->elf) == ELFCLASS32)
132	  {
133	    pc = addrs.a32[0];
134	    base = addrs.a32[1];
135	    sem = addrs.a32[2];
136	  }
137	else
138	  {
139	    pc = addrs.a64[0];
140	    base = addrs.a64[1];
141	    sem = addrs.a64[2];
142	  }
143
144	printf (gettext ("    PC: "));
145	printf ("%#" PRIx64 ",", pc);
146	printf (gettext (" Base: "));
147	printf ("%#" PRIx64 ",", base);
148	printf (gettext (" Semaphore: "));
149	printf ("%#" PRIx64 "\n", sem);
150	printf (gettext ("    Provider: "));
151	printf ("%s,", provider);
152	printf (gettext (" Name: "));
153	printf ("%s,", pname);
154	printf (gettext (" Args: "));
155	printf ("'%s'\n", args);
156	return;
157      }
158
159    switch (type)
160      {
161      case NT_GNU_BUILD_ID:
162	if (strcmp (name, "GNU") == 0 && descsz > 0)
163	  {
164	    printf (gettext ("    Build ID: "));
165	    uint_fast32_t i;
166	    for (i = 0; i < descsz - 1; ++i)
167	      printf ("%02" PRIx8, (uint8_t) desc[i]);
168	    printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
169	  }
170	break;
171
172      case NT_GNU_GOLD_VERSION:
173	if (strcmp (name, "GNU") == 0 && descsz > 0)
174	  /* A non-null terminated version string.  */
175	  printf (gettext ("    Linker version: %.*s\n"),
176		  (int) descsz, desc);
177	break;
178
179      case NT_GNU_ABI_TAG:
180	if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0)
181	  {
182	    Elf_Data in =
183	      {
184		.d_version = EV_CURRENT,
185		.d_type = ELF_T_WORD,
186		.d_size = descsz,
187		.d_buf = (void *) desc
188	      };
189	    uint32_t buf[descsz / 4];
190	    Elf_Data out =
191	      {
192		.d_version = EV_CURRENT,
193		.d_type = ELF_T_WORD,
194		.d_size = descsz,
195		.d_buf = buf
196	      };
197
198	    if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
199	      {
200		const char *os;
201		switch (buf[0])
202		  {
203		  case ELF_NOTE_OS_LINUX:
204		    os = "Linux";
205		    break;
206
207		  case ELF_NOTE_OS_GNU:
208		    os = "GNU";
209		    break;
210
211		  case ELF_NOTE_OS_SOLARIS2:
212		    os = "Solaris";
213		    break;
214
215		  case ELF_NOTE_OS_FREEBSD:
216		    os = "FreeBSD";
217		    break;
218
219		  default:
220		    os = "???";
221		    break;
222		  }
223
224		printf (gettext ("    OS: %s, ABI: "), os);
225		for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
226		  {
227		    if (cnt > 1)
228		      putchar_unlocked ('.');
229		    printf ("%" PRIu32, buf[cnt]);
230		  }
231		putchar_unlocked ('\n');
232	      }
233	    break;
234	  }
235	/* FALLTHROUGH */
236
237      default:
238	/* Unknown type.  */
239	break;
240      }
241}
242