• 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 (_("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 (_("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 (_("    PC: "));
127 	  printf ("%#" PRIx64 ",", pc);
128 	  printf (_(" Base: "));
129 	  printf ("%#" PRIx64 ",", base);
130 	  printf (_(" Semaphore: "));
131 	  printf ("%#" PRIx64 "\n", sem);
132 	  printf (_("    Provider: "));
133 	  printf ("%s,", provider);
134 	  printf (_(" Name: "));
135 	  printf ("%s,", pname);
136 	  printf (_(" 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 (_("    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 (_("    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 if (prop.pr_type >= GNU_PROPERTY_LOPROC
480 			   && prop.pr_type <= GNU_PROPERTY_HIPROC
481 			   && ehdr.e_machine == EM_AARCH64)
482 		    {
483 		      printf ("AARCH64 ");
484 		      if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
485 			{
486 			  printf ("FEATURE_1_AND: ");
487 
488 			  if (prop.pr_datasz == 4)
489 			    {
490 			      GElf_Word data;
491 			      in.d_type = ELF_T_WORD;
492 			      out.d_type = ELF_T_WORD;
493 			      in.d_size = 4;
494 			      out.d_size = 4;
495 			      in.d_buf = (void *) desc;
496 			      out.d_buf = (void *) &data;
497 
498 			      if (gelf_xlatetom (ebl->elf, &out, &in,
499 						 elfident[EI_DATA]) == NULL)
500 				{
501 				  printf ("%s\n", elf_errmsg (-1));
502 				  return;
503 				}
504 			      printf ("%08" PRIx32 " ", data);
505 
506 			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
507 				  != 0)
508 				{
509 				  printf ("BTI");
510 				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
511 				  if (data != 0)
512 				    printf (" ");
513 				}
514 
515 			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
516 				  != 0)
517 				{
518 				  printf ("PAC");
519 				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
520 				  if (data != 0)
521 				    printf (" ");
522 				}
523 
524 			      if (data != 0)
525 				printf ("UNKNOWN");
526 			    }
527 			  else
528 			    printf ("<bad datasz: %" PRId32 ">",
529 				    prop.pr_datasz);
530 
531 			  printf ("\n");
532 			}
533 		      else
534 			{
535 			  printf ("%#" PRIx32, prop.pr_type);
536 			  if (prop.pr_datasz > 0)
537 			    {
538 			      printf (" data: ");
539 			      size_t i;
540 			      for (i = 0; i < prop.pr_datasz - 1; i++)
541 				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
542 			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
543 			    }
544 			}
545 		    }
546 		  else
547 		    {
548 		      if (prop.pr_type >= GNU_PROPERTY_LOPROC
549 			  && prop.pr_type <= GNU_PROPERTY_HIPROC)
550 			printf ("proc_type %#" PRIx32, prop.pr_type);
551 		      else if (prop.pr_type >= GNU_PROPERTY_LOUSER
552 			  && prop.pr_type <= GNU_PROPERTY_HIUSER)
553 			printf ("app_type %#" PRIx32, prop.pr_type);
554 		      else
555 			printf ("unknown_type %#" PRIx32, prop.pr_type);
556 
557 		      if (prop.pr_datasz > 0)
558 			{
559 			  printf (" data: ");
560 			  size_t i;
561 			  for (i = 0; i < prop.pr_datasz - 1; i++)
562 			    printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
563 			  printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
564 			}
565 		    }
566 
567 		  if (elfclass == ELFCLASS32)
568 		    prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz);
569 		  else
570 		    prop.pr_datasz = NOTE_ALIGN8 (prop.pr_datasz);
571 
572 		  desc += prop.pr_datasz;
573 		  if (descsz > prop.pr_datasz)
574 		    descsz -= prop.pr_datasz;
575 		  else
576 		    descsz = 0;
577 		}
578 	    }
579 	  break;
580 
581 	case NT_GNU_ABI_TAG:
582 	  if (descsz >= 8 && descsz % 4 == 0)
583 	    {
584 	      Elf_Data in =
585 		{
586 		  .d_version = EV_CURRENT,
587 		  .d_type = ELF_T_WORD,
588 		  .d_size = descsz,
589 		  .d_buf = (void *) desc
590 		};
591 	      /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes).  If it
592 		 is much (4*) larger dynamically allocate memory to convert.  */
593 #define FIXED_TAG_BYTES 16
594 	      uint32_t sbuf[FIXED_TAG_BYTES];
595 	      uint32_t *buf;
596 	      if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
597 		{
598 		  buf = malloc (descsz);
599 		  if (unlikely (buf == NULL))
600 		    return;
601 		}
602 	      else
603 		buf = sbuf;
604 	      Elf_Data out =
605 		{
606 		  .d_version = EV_CURRENT,
607 		  .d_type = ELF_T_WORD,
608 		  .d_size = descsz,
609 		  .d_buf = buf
610 		};
611 
612 	      if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
613 		{
614 		  const char *os;
615 		  switch (buf[0])
616 		    {
617 		    case ELF_NOTE_OS_LINUX:
618 		      os = "Linux";
619 		      break;
620 
621 		    case ELF_NOTE_OS_GNU:
622 		      os = "GNU";
623 		      break;
624 
625 		    case ELF_NOTE_OS_SOLARIS2:
626 		      os = "Solaris";
627 		      break;
628 
629 		    case ELF_NOTE_OS_FREEBSD:
630 		      os = "FreeBSD";
631 		      break;
632 
633 		    default:
634 		      os = "???";
635 		      break;
636 		    }
637 
638 		  printf (_("    OS: %s, ABI: "), os);
639 		  for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
640 		    {
641 		      if (cnt > 1)
642 			putchar_unlocked ('.');
643 		      printf ("%" PRIu32, buf[cnt]);
644 		    }
645 		  putchar_unlocked ('\n');
646 		}
647 	      if (descsz / 4 > FIXED_TAG_BYTES)
648 		free (buf);
649 	      break;
650 	    }
651 	  FALLTHROUGH;
652 
653 	default:
654 	  /* Unknown type.  */
655 	  break;
656 	}
657     }
658 }
659