• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* Print contents of object file note.
2    Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016, 2018 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 #include "common.h"
41 #include "libelfP.h"
42 #include "libdwP.h"
43 #include "memory-access.h"
44 
45 
46 void
ebl_object_note(Ebl * ebl,uint32_t namesz,const char * name,uint32_t type,uint32_t descsz,const char * desc)47 ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type,
48 		 uint32_t descsz, const char *desc)
49 {
50   if (! ebl->object_note (name, type, descsz, desc))
51     {
52       /* The machine specific function did not know this type.  */
53 
54       if (strcmp ("stapsdt", name) == 0)
55 	{
56 	  if (type != 3)
57 	    {
58 	      printf (gettext ("unknown SDT version %u\n"), type);
59 	      return;
60 	    }
61 
62 	  /* Descriptor starts with three addresses, pc, base ref and
63 	     semaphore.  Then three zero terminated strings provider,
64 	     name and arguments.  */
65 
66 	  union
67 	  {
68 	    Elf64_Addr a64[3];
69 	    Elf32_Addr a32[3];
70 	  } addrs;
71 
72 	  size_t addrs_size = gelf_fsize (ebl->elf, ELF_T_ADDR, 3, EV_CURRENT);
73 	  if (descsz < addrs_size + 3)
74 	    {
75 	    invalid_sdt:
76 	      printf (gettext ("invalid SDT probe descriptor\n"));
77 	      return;
78 	    }
79 
80 	  Elf_Data src =
81 	    {
82 	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
83 	      .d_buf = (void *) desc, .d_size = addrs_size
84 	    };
85 
86 	  Elf_Data dst =
87 	    {
88 	      .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
89 	      .d_buf = &addrs, .d_size = addrs_size
90 	    };
91 
92 	  if (gelf_xlatetom (ebl->elf, &dst, &src,
93 			     elf_getident (ebl->elf, NULL)[EI_DATA]) == NULL)
94 	    {
95 	      printf ("%s\n", elf_errmsg (-1));
96 	      return;
97 	    }
98 
99 	  const char *provider = desc + addrs_size;
100 	  const char *pname = memchr (provider, '\0', desc + descsz - provider);
101 	  if (pname == NULL)
102 	    goto invalid_sdt;
103 
104 	  ++pname;
105 	  const char *args = memchr (pname, '\0', desc + descsz - pname);
106 	  if (args == NULL ||
107 	      memchr (++args, '\0', desc + descsz - pname) != desc + descsz - 1)
108 	    goto invalid_sdt;
109 
110 	  GElf_Addr pc;
111 	  GElf_Addr base;
112 	  GElf_Addr sem;
113 	  if (gelf_getclass (ebl->elf) == ELFCLASS32)
114 	    {
115 	      pc = addrs.a32[0];
116 	      base = addrs.a32[1];
117 	      sem = addrs.a32[2];
118 	    }
119 	  else
120 	    {
121 	      pc = addrs.a64[0];
122 	      base = addrs.a64[1];
123 	      sem = addrs.a64[2];
124 	    }
125 
126 	  printf (gettext ("    PC: "));
127 	  printf ("%#" PRIx64 ",", pc);
128 	  printf (gettext (" Base: "));
129 	  printf ("%#" PRIx64 ",", base);
130 	  printf (gettext (" Semaphore: "));
131 	  printf ("%#" PRIx64 "\n", sem);
132 	  printf (gettext ("    Provider: "));
133 	  printf ("%s,", provider);
134 	  printf (gettext (" Name: "));
135 	  printf ("%s,", pname);
136 	  printf (gettext (" Args: "));
137 	  printf ("'%s'\n", args);
138 	  return;
139 	}
140 
141       if (strncmp (name, ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX,
142 		   strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX)) == 0
143 	  && (type == NT_GNU_BUILD_ATTRIBUTE_OPEN
144 	      || type == NT_GNU_BUILD_ATTRIBUTE_FUNC))
145 	{
146 	  /* There might or might not be a pair of addresses in the desc.  */
147 	  if (descsz > 0)
148 	    {
149 	      printf ("    Address Range: ");
150 
151 	      union
152 	      {
153 		Elf64_Addr a64[2];
154 		Elf32_Addr a32[2];
155 	      } addrs;
156 
157 	      size_t addr_size = gelf_fsize (ebl->elf, ELF_T_ADDR,
158 					     2, EV_CURRENT);
159 	      if (descsz != addr_size)
160 		printf ("<unknown data>\n");
161 	      else
162 		{
163 		  Elf_Data src =
164 		    {
165 		     .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
166 		     .d_buf = (void *) desc, .d_size = descsz
167 		    };
168 
169 		  Elf_Data dst =
170 		    {
171 		     .d_type = ELF_T_ADDR, .d_version = EV_CURRENT,
172 		     .d_buf = &addrs, .d_size = descsz
173 		    };
174 
175 		  if (gelf_xlatetom (ebl->elf, &dst, &src,
176 				     elf_getident (ebl->elf,
177 						   NULL)[EI_DATA]) == NULL)
178 		    printf ("%s\n", elf_errmsg (-1));
179 		  else
180 		    {
181 		      if (addr_size == 4)
182 			printf ("%#" PRIx32 " - %#" PRIx32 "\n",
183 				addrs.a32[0], addrs.a32[1]);
184 		      else
185 			printf ("%#" PRIx64 " - %#" PRIx64 "\n",
186 				addrs.a64[0], addrs.a64[1]);
187 		    }
188 		}
189 	    }
190 
191 	  /* Most data actually is inside the name.
192 	     https://fedoraproject.org/wiki/Toolchain/Watermark  */
193 
194 	  /* We need at least 2 chars of data to describe the
195 	     attribute and value encodings.  */
196 	  const char *data = (name
197 			      + strlen (ELF_NOTE_GNU_BUILD_ATTRIBUTE_PREFIX));
198 	  if (namesz < 2)
199 	    {
200 	      printf ("<insufficient data>\n");
201 	      return;
202 	    }
203 
204 	  printf ("    ");
205 
206 	  /* In most cases the value comes right after the encoding bytes.  */
207 	  const char *value = &data[2];
208 	  switch (data[1])
209 	    {
210 	    case GNU_BUILD_ATTRIBUTE_VERSION:
211 	      printf ("VERSION: ");
212 	      break;
213 	    case GNU_BUILD_ATTRIBUTE_STACK_PROT:
214 	      printf ("STACK_PROT: ");
215 	      break;
216 	    case GNU_BUILD_ATTRIBUTE_RELRO:
217 	      printf ("RELRO: ");
218 	      break;
219 	    case GNU_BUILD_ATTRIBUTE_STACK_SIZE:
220 	      printf ("STACK_SIZE: ");
221 	      break;
222 	    case GNU_BUILD_ATTRIBUTE_TOOL:
223 	      printf ("TOOL: ");
224 	      break;
225 	    case GNU_BUILD_ATTRIBUTE_ABI:
226 	      printf ("ABI: ");
227 	      break;
228 	    case GNU_BUILD_ATTRIBUTE_PIC:
229 	      printf ("PIC: ");
230 	      break;
231 	    case GNU_BUILD_ATTRIBUTE_SHORT_ENUM:
232 	      printf ("SHORT_ENUM: ");
233 	      break;
234 	    case 32 ... 126:
235 	      printf ("\"%s\": ", &data[1]);
236 	      value += strlen (&data[1]) + 1;
237 	      break;
238 	    default:
239 	      printf ("<unknown>: ");
240 	      break;
241 	    }
242 
243 	  switch (data[0])
244 	    {
245 	    case GNU_BUILD_ATTRIBUTE_TYPE_NUMERIC:
246 	      {
247 		/* Any numbers are always in (unsigned) little endian.  */
248 		static const Dwarf dbg
249 		  = { .other_byte_order = MY_ELFDATA != ELFDATA2LSB };
250 		size_t bytes = namesz - (value - name);
251 		uint64_t val;
252 		if (bytes == 1)
253 		  val = *(unsigned char *) value;
254 		else if (bytes == 2)
255 		  val = read_2ubyte_unaligned (&dbg, value);
256 		else if (bytes == 4)
257 		  val = read_4ubyte_unaligned (&dbg, value);
258 		else if (bytes == 8)
259 		  val = read_8ubyte_unaligned (&dbg, value);
260 		else
261 		  goto unknown;
262 		printf ("%" PRIx64, val);
263 	      }
264 	      break;
265 	    case GNU_BUILD_ATTRIBUTE_TYPE_STRING:
266 	      printf ("\"%s\"", value);
267 	      break;
268 	    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_TRUE:
269 	      printf ("TRUE");
270 	      break;
271 	    case GNU_BUILD_ATTRIBUTE_TYPE_BOOL_FALSE:
272 	      printf ("FALSE");
273 	      break;
274 	    default:
275 	      {
276 	      unknown:
277 		printf ("<unknown>");
278 	      }
279 	      break;
280 	    }
281 
282 	  printf ("\n");
283 
284 	  return;
285 	}
286 
287       /* NT_VERSION doesn't have any info.  All data is in the name.  */
288       if (descsz == 0 && type == NT_VERSION)
289 	return;
290 
291       /* Everything else should have the "GNU" owner name.  */
292       if (strcmp ("GNU", name) != 0)
293 	return;
294 
295       switch (type)
296 	{
297 	case NT_GNU_BUILD_ID:
298 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
299 	    {
300 	      printf (gettext ("    Build ID: "));
301 	      uint_fast32_t i;
302 	      for (i = 0; i < descsz - 1; ++i)
303 		printf ("%02" PRIx8, (uint8_t) desc[i]);
304 	      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
305 	    }
306 	  break;
307 
308 	case NT_GNU_GOLD_VERSION:
309 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
310 	    /* A non-null terminated version string.  */
311 	    printf (gettext ("    Linker version: %.*s\n"),
312 		    (int) descsz, desc);
313 	  break;
314 
315 	case NT_GNU_PROPERTY_TYPE_0:
316 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
317 	    {
318 	      /* There are at least 2 words. type and datasz.  */
319 	      while (descsz >= 8)
320 		{
321 		  struct pr_prop
322 		  {
323 		    GElf_Word pr_type;
324 		    GElf_Word pr_datasz;
325 		  } prop;
326 
327 		  Elf_Data in =
328 		    {
329 		      .d_version = EV_CURRENT,
330 		      .d_type = ELF_T_WORD,
331 		      .d_size = 8,
332 		      .d_buf = (void *) desc
333 		    };
334 		  Elf_Data out =
335 		    {
336 		      .d_version = EV_CURRENT,
337 		      .d_type = ELF_T_WORD,
338 		      .d_size = descsz,
339 		      .d_buf = (void *) &prop
340 		    };
341 
342 		  if (gelf_xlatetom (ebl->elf, &out, &in,
343 				     elf_getident (ebl->elf,
344 						   NULL)[EI_DATA]) == NULL)
345 		    {
346 		      printf ("%s\n", elf_errmsg (-1));
347 		      return;
348 		    }
349 
350 		  desc += 8;
351 		  descsz -= 8;
352 
353 		  if (prop.pr_datasz > descsz)
354 		    {
355 		      printf ("BAD property datasz: %" PRId32 "\n",
356 			      prop.pr_datasz);
357 		      return;
358 		    }
359 
360 		  int elfclass = gelf_getclass (ebl->elf);
361 		  char *elfident = elf_getident (ebl->elf, NULL);
362 		  GElf_Ehdr ehdr;
363 		  gelf_getehdr (ebl->elf, &ehdr);
364 
365 		  /* Prefix.  */
366 		  printf ("    ");
367 		  if (prop.pr_type == GNU_PROPERTY_STACK_SIZE)
368 		    {
369 		      printf ("STACK_SIZE ");
370 		      union
371 			{
372 			  Elf64_Addr a64;
373 			  Elf32_Addr a32;
374 			} addr;
375 		      if ((elfclass == ELFCLASS32 && prop.pr_datasz == 4)
376 			  || (elfclass == ELFCLASS64 && prop.pr_datasz == 8))
377 			{
378 			  in.d_type = ELF_T_ADDR;
379 			  out.d_type = ELF_T_ADDR;
380 			  in.d_size = prop.pr_datasz;
381 			  out.d_size = prop.pr_datasz;
382 			  in.d_buf = (void *) desc;
383 			  out.d_buf = (elfclass == ELFCLASS32
384 				       ? (void *) &addr.a32
385 				       : (void *) &addr.a64);
386 
387 			  if (gelf_xlatetom (ebl->elf, &out, &in,
388 					     elfident[EI_DATA]) == NULL)
389 			    {
390 			      printf ("%s\n", elf_errmsg (-1));
391 			      return;
392 			    }
393 			  if (elfclass == ELFCLASS32)
394 			    printf ("%#" PRIx32 "\n", addr.a32);
395 			  else
396 			    printf ("%#" PRIx64 "\n", addr.a64);
397 			}
398 		      else
399 			printf (" (garbage datasz: %" PRIx32 ")\n",
400 				prop.pr_datasz);
401 		    }
402 		  else if (prop.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
403 		    {
404 		      printf ("NO_COPY_ON_PROTECTION");
405 		      if (prop.pr_datasz == 0)
406 			printf ("\n");
407 		      else
408 			printf (" (garbage datasz: %" PRIx32 ")\n",
409 				prop.pr_datasz);
410 		    }
411 		  else if (prop.pr_type >= GNU_PROPERTY_LOPROC
412 		      && prop.pr_type <= GNU_PROPERTY_HIPROC
413 		      && (ehdr.e_machine == EM_386
414 			  || ehdr.e_machine == EM_X86_64))
415 		    {
416 		      printf ("X86 ");
417 		      if (prop.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND)
418 			{
419 			  printf ("FEATURE_1_AND: ");
420 
421 			  if (prop.pr_datasz == 4)
422 			    {
423 			      GElf_Word data;
424 			      in.d_type = ELF_T_WORD;
425 			      out.d_type = ELF_T_WORD;
426 			      in.d_size = 4;
427 			      out.d_size = 4;
428 			      in.d_buf = (void *) desc;
429 			      out.d_buf = (void *) &data;
430 
431 			      if (gelf_xlatetom (ebl->elf, &out, &in,
432 						 elfident[EI_DATA]) == NULL)
433 				{
434 				  printf ("%s\n", elf_errmsg (-1));
435 				  return;
436 				}
437 			      printf ("%08" PRIx32 " ", data);
438 
439 			      if ((data & GNU_PROPERTY_X86_FEATURE_1_IBT)
440 				  != 0)
441 				{
442 				  printf ("IBT");
443 				  data &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
444 				  if (data != 0)
445 				    printf (" ");
446 				}
447 
448 			      if ((data & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
449 				  != 0)
450 				{
451 				  printf ("SHSTK");
452 				  data &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
453 				  if (data != 0)
454 				    printf (" ");
455 				}
456 
457 			      if (data != 0)
458 				printf ("UNKNOWN");
459 			    }
460 			  else
461 			    printf ("<bad datasz: %" PRId32 ">",
462 				    prop.pr_datasz);
463 
464 			  printf ("\n");
465 			}
466 		      else
467 			{
468 			  printf ("%#" PRIx32, prop.pr_type);
469 			  if (prop.pr_datasz > 0)
470 			    {
471 			      printf (" data: ");
472 			      size_t i;
473 			      for (i = 0; i < prop.pr_datasz - 1; i++)
474 				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
475 			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
476 			    }
477 			}
478 		    }
479 		  else
480 		    {
481 		      if (prop.pr_type >= GNU_PROPERTY_LOPROC
482 			  && prop.pr_type <= GNU_PROPERTY_HIPROC)
483 			printf ("proc_type %#" PRIx32, prop.pr_type);
484 		      else if (prop.pr_type >= GNU_PROPERTY_LOUSER
485 			  && prop.pr_type <= GNU_PROPERTY_HIUSER)
486 			printf ("app_type %#" PRIx32, prop.pr_type);
487 		      else
488 			printf ("unknown_type %#" PRIx32, prop.pr_type);
489 
490 		      if (prop.pr_datasz > 0)
491 			{
492 			  printf (" data: ");
493 			  size_t i;
494 			  for (i = 0; i < prop.pr_datasz - 1; i++)
495 			    printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
496 			  printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
497 			}
498 		    }
499 
500 		  if (elfclass == ELFCLASS32)
501 		    prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz);
502 		  else
503 		    prop.pr_datasz = NOTE_ALIGN8 (prop.pr_datasz);
504 
505 		  desc += prop.pr_datasz;
506 		  if (descsz > prop.pr_datasz)
507 		    descsz -= prop.pr_datasz;
508 		  else
509 		    descsz = 0;
510 		}
511 	    }
512 	  break;
513 
514 	case NT_GNU_ABI_TAG:
515 	  if (descsz >= 8 && descsz % 4 == 0)
516 	    {
517 	      Elf_Data in =
518 		{
519 		  .d_version = EV_CURRENT,
520 		  .d_type = ELF_T_WORD,
521 		  .d_size = descsz,
522 		  .d_buf = (void *) desc
523 		};
524 	      /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes).  If it
525 		 is much (4*) larger dynamically allocate memory to convert.  */
526 #define FIXED_TAG_BYTES 16
527 	      uint32_t sbuf[FIXED_TAG_BYTES];
528 	      uint32_t *buf;
529 	      if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
530 		{
531 		  buf = malloc (descsz);
532 		  if (unlikely (buf == NULL))
533 		    return;
534 		}
535 	      else
536 		buf = sbuf;
537 	      Elf_Data out =
538 		{
539 		  .d_version = EV_CURRENT,
540 		  .d_type = ELF_T_WORD,
541 		  .d_size = descsz,
542 		  .d_buf = buf
543 		};
544 
545 	      if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
546 		{
547 		  const char *os;
548 		  switch (buf[0])
549 		    {
550 		    case ELF_NOTE_OS_LINUX:
551 		      os = "Linux";
552 		      break;
553 
554 		    case ELF_NOTE_OS_GNU:
555 		      os = "GNU";
556 		      break;
557 
558 		    case ELF_NOTE_OS_SOLARIS2:
559 		      os = "Solaris";
560 		      break;
561 
562 		    case ELF_NOTE_OS_FREEBSD:
563 		      os = "FreeBSD";
564 		      break;
565 
566 		    default:
567 		      os = "???";
568 		      break;
569 		    }
570 
571 		  printf (gettext ("    OS: %s, ABI: "), os);
572 		  for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
573 		    {
574 		      if (cnt > 1)
575 			putchar_unlocked ('.');
576 		      printf ("%" PRIu32, buf[cnt]);
577 		    }
578 		  putchar_unlocked ('\n');
579 		}
580 	      if (descsz / 4 > FIXED_TAG_BYTES)
581 		free (buf);
582 	      break;
583 	    }
584 	  FALLTHROUGH;
585 
586 	default:
587 	  /* Unknown type.  */
588 	  break;
589 	}
590     }
591 }
592