• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Print contents of object file note.
2    Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016 Red Hat, Inc.
3    This file is part of elfutils.
4    Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5 
6    This file is free software; you can redistribute it and/or modify
7    it under the terms of either
8 
9      * the GNU Lesser General Public License as published by the Free
10        Software Foundation; either version 3 of the License, or (at
11        your option) any later version
12 
13    or
14 
15      * the GNU General Public License as published by the Free
16        Software Foundation; either version 2 of the License, or (at
17        your option) any later version
18 
19    or both in parallel, as here.
20 
21    elfutils is distributed in the hope that it will be useful, but
22    WITHOUT ANY WARRANTY; without even the implied warranty of
23    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24    General Public License for more details.
25 
26    You should have received copies of the GNU General Public License and
27    the GNU Lesser General Public License along with this program.  If
28    not, see <http://www.gnu.org/licenses/>.  */
29 
30 #ifdef HAVE_CONFIG_H
31 # include <config.h>
32 #endif
33 
34 #include <inttypes.h>
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <libeblP.h>
39 
40 
41 void
ebl_object_note(Ebl * ebl,const char * name,uint32_t type,uint32_t descsz,const char * desc)42 ebl_object_note (Ebl *ebl, const char *name, uint32_t type,
43 		 uint32_t descsz, const char *desc)
44 {
45   if (! ebl->object_note (name, type, descsz, desc))
46     {
47       /* The machine specific function did not know this type.  */
48 
49       if (strcmp ("stapsdt", name) == 0)
50 	{
51 	  if (type != 3)
52 	    {
53 	      printf (gettext ("unknown SDT version %u\n"), type);
54 	      return;
55 	    }
56 
57 	  /* Descriptor starts with three addresses, pc, base ref and
58 	     semaphore.  Then three zero terminated strings provider,
59 	     name and arguments.  */
60 
61 	  union
62 	  {
63 	    Elf64_Addr a64[3];
64 	    Elf32_Addr a32[3];
65 	  } addrs;
66 
67 	  size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
68 	  if (descsz < addrs_size + 3)
69 	    {
70 	    invalid_sdt:
71 	      printf (gettext ("invalid SDT probe descriptor\n"));
72 	      return;
73 	    }
74 
75 	  Elf_Data src =
76 	    {
77 	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
78 	      .d_buf = (void *) desc, .d_size = addrs_size
79 	    };
80 
81 	  Elf_Data dst =
82 	    {
83 	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
84 	      .d_buf = &addrs, .d_size = addrs_size
85 	    };
86 
87 	  if (gelf_xlatetom (ebl->elf, &dst, &src,
88 			     elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
89 	    {
90 	      printf ("%s\n", elf_errmsg (-1));
91 	      return;
92 	    }
93 
94 	  const char *provider = desc + addrs_size;
95 	  const char *pname = memchr (provider, '\0', desc + descsz - provider);
96 	  if (pname == NULL)
97 	    goto invalid_sdt;
98 
99 	  ++pname;
100 	  const char *args = memchr (pname, '\0', desc + descsz - pname);
101 	  if (args == NULL ||
102 	      memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
103 	    goto invalid_sdt;
104 
105 	  GElf_Addr pc;
106 	  GElf_Addr base;
107 	  GElf_Addr sem;
108 	  if (gelf_getclass (ebl->elf) == ELFCLASS32)
109 	    {
110 	      pc = addrs.a32[0];
111 	      base = addrs.a32[1];
112 	      sem = addrs.a32[2];
113 	    }
114 	  else
115 	    {
116 	      pc = addrs.a64[0];
117 	      base = addrs.a64[1];
118 	      sem = addrs.a64[2];
119 	    }
120 
121 	  printf (gettext ("    PC: "));
122 	  printf ("%#" PRIx64 ",", pc);
123 	  printf (gettext (" Base: "));
124 	  printf ("%#" PRIx64 ",", base);
125 	  printf (gettext (" Semaphore: "));
126 	  printf ("%#" PRIx64 "\n", sem);
127 	  printf (gettext ("    Provider: "));
128 	  printf ("%s,", provider);
129 	  printf (gettext (" Name: "));
130 	  printf ("%s,", pname);
131 	  printf (gettext (" Args: "));
132 	  printf ("'%s'\n", args);
133 	  return;
134 	}
135 
136       switch (type)
137 	{
138 	case NT_GNU_BUILD_ID:
139 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
140 	    {
141 	      printf (gettext ("    Build ID: "));
142 	      uint_fast32_t i;
143 	      for (i = 0; i < descsz - 1; ++i)
144 		printf ("%02" PRIx8, (uint8_t) desc[i]);
145 	      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
146 	    }
147 	  break;
148 
149 	case NT_GNU_GOLD_VERSION:
150 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
151 	    /* A non-null terminated version string.  */
152 	    printf (gettext ("    Linker version: %.*s\n"),
153 		    (int) descsz, desc);
154 	  break;
155 
156 	case NT_GNU_ABI_TAG:
157 	  if (strcmp (name, "GNU") == 0 && descsz >= 8 && descsz % 4 == 0)
158 	    {
159 	      Elf_Data in =
160 		{
161 		  .d_version = EV_CURRENT,
162 		  .d_type = ELF_T_WORD,
163 		  .d_size = descsz,
164 		  .d_buf = (void *) desc
165 		};
166 	      /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes).  If it
167 		 is much (4*) larger dynamically allocate memory to convert.  */
168 #define FIXED_TAG_BYTES 16
169 	      uint32_t sbuf[FIXED_TAG_BYTES];
170 	      uint32_t *buf;
171 	      if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
172 		{
173 		  buf = malloc (descsz);
174 		  if (unlikely (buf == NULL))
175 		    return;
176 		}
177 	      else
178 		buf = sbuf;
179 	      Elf_Data out =
180 		{
181 		  .d_version = EV_CURRENT,
182 		  .d_type = ELF_T_WORD,
183 		  .d_size = descsz,
184 		  .d_buf = buf
185 		};
186 
187 	      if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
188 		{
189 		  const char *os;
190 		  switch (buf[0])
191 		    {
192 		    case ELF_NOTE_OS_LINUX:
193 		      os = "Linux";
194 		      break;
195 
196 		    case ELF_NOTE_OS_GNU:
197 		      os = "GNU";
198 		      break;
199 
200 		    case ELF_NOTE_OS_SOLARIS2:
201 		      os = "Solaris";
202 		      break;
203 
204 		    case ELF_NOTE_OS_FREEBSD:
205 		      os = "FreeBSD";
206 		      break;
207 
208 		    default:
209 		      os = "???";
210 		      break;
211 		    }
212 
213 		  printf (gettext ("    OS: %s, ABI: "), os);
214 		  for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
215 		    {
216 		      if (cnt > 1)
217 			putchar_unlocked ('.');
218 		      printf ("%" PRIu32, buf[cnt]);
219 		    }
220 		  putchar_unlocked ('\n');
221 		}
222 	      if (descsz / 4 > FIXED_TAG_BYTES)
223 		free (buf);
224 	      break;
225 	    }
226 	  /* FALLTHROUGH */
227 
228 	default:
229 	  /* Unknown type.  */
230 	  break;
231 	}
232     }
233 }
234