• 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       if (strcmp ("FDO", name) == 0 && type == NT_FDO_PACKAGING_METADATA
292 	  && descsz > 0 && desc[descsz - 1] == '\0')
293 	printf("    Packaging Metadata: %.*s\n", (int) descsz, desc);
294 
295       /* Everything else should have the "GNU" owner name.  */
296       if (strcmp ("GNU", name) != 0)
297 	return;
298 
299       switch (type)
300 	{
301 	case NT_GNU_BUILD_ID:
302 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
303 	    {
304 	      printf (_("    Build ID: "));
305 	      uint_fast32_t i;
306 	      for (i = 0; i < descsz - 1; ++i)
307 		printf ("%02" PRIx8, (uint8_t) desc[i]);
308 	      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
309 	    }
310 	  break;
311 
312 	case NT_GNU_GOLD_VERSION:
313 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
314 	    /* A non-null terminated version string.  */
315 	    printf (_("    Linker version: %.*s\n"),
316 		    (int) descsz, desc);
317 	  break;
318 
319 	case NT_GNU_PROPERTY_TYPE_0:
320 	  if (strcmp (name, "GNU") == 0 && descsz > 0)
321 	    {
322 	      /* There are at least 2 words. type and datasz.  */
323 	      while (descsz >= 8)
324 		{
325 		  struct pr_prop
326 		  {
327 		    GElf_Word pr_type;
328 		    GElf_Word pr_datasz;
329 		  } prop;
330 
331 		  Elf_Data in =
332 		    {
333 		      .d_version = EV_CURRENT,
334 		      .d_type = ELF_T_WORD,
335 		      .d_size = 8,
336 		      .d_buf = (void *) desc
337 		    };
338 		  Elf_Data out =
339 		    {
340 		      .d_version = EV_CURRENT,
341 		      .d_type = ELF_T_WORD,
342 		      .d_size = descsz,
343 		      .d_buf = (void *) &prop
344 		    };
345 
346 		  if (gelf_xlatetom (ebl->elf, &out, &in,
347 				     elf_getident (ebl->elf,
348 						   NULL)[EI_DATA]) == NULL)
349 		    {
350 		      printf ("%s\n", elf_errmsg (-1));
351 		      return;
352 		    }
353 
354 		  desc += 8;
355 		  descsz -= 8;
356 
357 		  if (prop.pr_datasz > descsz)
358 		    {
359 		      printf ("BAD property datasz: %" PRId32 "\n",
360 			      prop.pr_datasz);
361 		      return;
362 		    }
363 
364 		  int elfclass = gelf_getclass (ebl->elf);
365 		  char *elfident = elf_getident (ebl->elf, NULL);
366 		  GElf_Ehdr ehdr;
367 		  gelf_getehdr (ebl->elf, &ehdr);
368 
369 		  /* Prefix.  */
370 		  printf ("    ");
371 		  if (prop.pr_type == GNU_PROPERTY_STACK_SIZE)
372 		    {
373 		      printf ("STACK_SIZE ");
374 		      union
375 			{
376 			  Elf64_Addr a64;
377 			  Elf32_Addr a32;
378 			} addr;
379 		      if ((elfclass == ELFCLASS32 && prop.pr_datasz == 4)
380 			  || (elfclass == ELFCLASS64 && prop.pr_datasz == 8))
381 			{
382 			  in.d_type = ELF_T_ADDR;
383 			  out.d_type = ELF_T_ADDR;
384 			  in.d_size = prop.pr_datasz;
385 			  out.d_size = prop.pr_datasz;
386 			  in.d_buf = (void *) desc;
387 			  out.d_buf = (elfclass == ELFCLASS32
388 				       ? (void *) &addr.a32
389 				       : (void *) &addr.a64);
390 
391 			  if (gelf_xlatetom (ebl->elf, &out, &in,
392 					     elfident[EI_DATA]) == NULL)
393 			    {
394 			      printf ("%s\n", elf_errmsg (-1));
395 			      return;
396 			    }
397 			  if (elfclass == ELFCLASS32)
398 			    printf ("%#" PRIx32 "\n", addr.a32);
399 			  else
400 			    printf ("%#" PRIx64 "\n", addr.a64);
401 			}
402 		      else
403 			printf (" (garbage datasz: %" PRIx32 ")\n",
404 				prop.pr_datasz);
405 		    }
406 		  else if (prop.pr_type == GNU_PROPERTY_NO_COPY_ON_PROTECTED)
407 		    {
408 		      printf ("NO_COPY_ON_PROTECTION");
409 		      if (prop.pr_datasz == 0)
410 			printf ("\n");
411 		      else
412 			printf (" (garbage datasz: %" PRIx32 ")\n",
413 				prop.pr_datasz);
414 		    }
415 		  else if (prop.pr_type >= GNU_PROPERTY_LOPROC
416 		      && prop.pr_type <= GNU_PROPERTY_HIPROC
417 		      && (ehdr.e_machine == EM_386
418 			  || ehdr.e_machine == EM_X86_64))
419 		    {
420 		      printf ("X86 ");
421 		      if (prop.pr_type == GNU_PROPERTY_X86_FEATURE_1_AND)
422 			{
423 			  printf ("FEATURE_1_AND: ");
424 
425 			  if (prop.pr_datasz == 4)
426 			    {
427 			      GElf_Word data;
428 			      in.d_type = ELF_T_WORD;
429 			      out.d_type = ELF_T_WORD;
430 			      in.d_size = 4;
431 			      out.d_size = 4;
432 			      in.d_buf = (void *) desc;
433 			      out.d_buf = (void *) &data;
434 
435 			      if (gelf_xlatetom (ebl->elf, &out, &in,
436 						 elfident[EI_DATA]) == NULL)
437 				{
438 				  printf ("%s\n", elf_errmsg (-1));
439 				  return;
440 				}
441 			      printf ("%08" PRIx32 " ", data);
442 
443 			      if ((data & GNU_PROPERTY_X86_FEATURE_1_IBT)
444 				  != 0)
445 				{
446 				  printf ("IBT");
447 				  data &= ~GNU_PROPERTY_X86_FEATURE_1_IBT;
448 				  if (data != 0)
449 				    printf (" ");
450 				}
451 
452 			      if ((data & GNU_PROPERTY_X86_FEATURE_1_SHSTK)
453 				  != 0)
454 				{
455 				  printf ("SHSTK");
456 				  data &= ~GNU_PROPERTY_X86_FEATURE_1_SHSTK;
457 				  if (data != 0)
458 				    printf (" ");
459 				}
460 
461 			      if (data != 0)
462 				printf ("UNKNOWN");
463 			    }
464 			  else
465 			    printf ("<bad datasz: %" PRId32 ">",
466 				    prop.pr_datasz);
467 
468 			  printf ("\n");
469 			}
470 		      else
471 			{
472 			  printf ("%#" PRIx32, prop.pr_type);
473 			  if (prop.pr_datasz > 0)
474 			    {
475 			      printf (" data: ");
476 			      size_t i;
477 			      for (i = 0; i < prop.pr_datasz - 1; i++)
478 				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
479 			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
480 			    }
481 			}
482 		    }
483 		  else if (prop.pr_type >= GNU_PROPERTY_LOPROC
484 			   && prop.pr_type <= GNU_PROPERTY_HIPROC
485 			   && ehdr.e_machine == EM_AARCH64)
486 		    {
487 		      printf ("AARCH64 ");
488 		      if (prop.pr_type == GNU_PROPERTY_AARCH64_FEATURE_1_AND)
489 			{
490 			  printf ("FEATURE_1_AND: ");
491 
492 			  if (prop.pr_datasz == 4)
493 			    {
494 			      GElf_Word data;
495 			      in.d_type = ELF_T_WORD;
496 			      out.d_type = ELF_T_WORD;
497 			      in.d_size = 4;
498 			      out.d_size = 4;
499 			      in.d_buf = (void *) desc;
500 			      out.d_buf = (void *) &data;
501 
502 			      if (gelf_xlatetom (ebl->elf, &out, &in,
503 						 elfident[EI_DATA]) == NULL)
504 				{
505 				  printf ("%s\n", elf_errmsg (-1));
506 				  return;
507 				}
508 			      printf ("%08" PRIx32 " ", data);
509 
510 			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
511 				  != 0)
512 				{
513 				  printf ("BTI");
514 				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
515 				  if (data != 0)
516 				    printf (" ");
517 				}
518 
519 			      if ((data & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
520 				  != 0)
521 				{
522 				  printf ("PAC");
523 				  data &= ~GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
524 				  if (data != 0)
525 				    printf (" ");
526 				}
527 
528 			      if (data != 0)
529 				printf ("UNKNOWN");
530 			    }
531 			  else
532 			    printf ("<bad datasz: %" PRId32 ">",
533 				    prop.pr_datasz);
534 
535 			  printf ("\n");
536 			}
537 		      else
538 			{
539 			  printf ("%#" PRIx32, prop.pr_type);
540 			  if (prop.pr_datasz > 0)
541 			    {
542 			      printf (" data: ");
543 			      size_t i;
544 			      for (i = 0; i < prop.pr_datasz - 1; i++)
545 				printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
546 			      printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
547 			    }
548 			}
549 		    }
550 		  else
551 		    {
552 		      if (prop.pr_type >= GNU_PROPERTY_LOPROC
553 			  && prop.pr_type <= GNU_PROPERTY_HIPROC)
554 			printf ("proc_type %#" PRIx32, prop.pr_type);
555 		      else if (prop.pr_type >= GNU_PROPERTY_LOUSER
556 			  && prop.pr_type <= GNU_PROPERTY_HIUSER)
557 			printf ("app_type %#" PRIx32, prop.pr_type);
558 		      else
559 			printf ("unknown_type %#" PRIx32, prop.pr_type);
560 
561 		      if (prop.pr_datasz > 0)
562 			{
563 			  printf (" data: ");
564 			  size_t i;
565 			  for (i = 0; i < prop.pr_datasz - 1; i++)
566 			    printf ("%02" PRIx8 " ", (uint8_t) desc[i]);
567 			  printf ("%02" PRIx8 "\n", (uint8_t) desc[i]);
568 			}
569 		    }
570 
571 		  if (elfclass == ELFCLASS32)
572 		    prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz);
573 		  else
574 		    prop.pr_datasz = NOTE_ALIGN8 (prop.pr_datasz);
575 
576 		  desc += prop.pr_datasz;
577 		  if (descsz > prop.pr_datasz)
578 		    descsz -= prop.pr_datasz;
579 		  else
580 		    descsz = 0;
581 		}
582 	    }
583 	  break;
584 
585 	case NT_GNU_ABI_TAG:
586 	  if (descsz >= 8 && descsz % 4 == 0)
587 	    {
588 	      Elf_Data in =
589 		{
590 		  .d_version = EV_CURRENT,
591 		  .d_type = ELF_T_WORD,
592 		  .d_size = descsz,
593 		  .d_buf = (void *) desc
594 		};
595 	      /* Normally NT_GNU_ABI_TAG is just 4 words (16 bytes).  If it
596 		 is much (4*) larger dynamically allocate memory to convert.  */
597 #define FIXED_TAG_BYTES 16
598 	      uint32_t sbuf[FIXED_TAG_BYTES];
599 	      uint32_t *buf;
600 	      if (unlikely (descsz / 4 > FIXED_TAG_BYTES))
601 		{
602 		  buf = malloc (descsz);
603 		  if (unlikely (buf == NULL))
604 		    return;
605 		}
606 	      else
607 		buf = sbuf;
608 	      Elf_Data out =
609 		{
610 		  .d_version = EV_CURRENT,
611 		  .d_type = ELF_T_WORD,
612 		  .d_size = descsz,
613 		  .d_buf = buf
614 		};
615 
616 	      if (elf32_xlatetom (&out, &in, ebl->data) != NULL)
617 		{
618 		  const char *os;
619 		  switch (buf[0])
620 		    {
621 		    case ELF_NOTE_OS_LINUX:
622 		      os = "Linux";
623 		      break;
624 
625 		    case ELF_NOTE_OS_GNU:
626 		      os = "GNU";
627 		      break;
628 
629 		    case ELF_NOTE_OS_SOLARIS2:
630 		      os = "Solaris";
631 		      break;
632 
633 		    case ELF_NOTE_OS_FREEBSD:
634 		      os = "FreeBSD";
635 		      break;
636 
637 		    default:
638 		      os = "???";
639 		      break;
640 		    }
641 
642 		  printf (_("    OS: %s, ABI: "), os);
643 		  for (size_t cnt = 1; cnt < descsz / 4; ++cnt)
644 		    {
645 		      if (cnt > 1)
646 			putchar_unlocked ('.');
647 		      printf ("%" PRIu32, buf[cnt]);
648 		    }
649 		  putchar_unlocked ('\n');
650 		}
651 	      if (descsz / 4 > FIXED_TAG_BYTES)
652 		free (buf);
653 	      break;
654 	    }
655 	  FALLTHROUGH;
656 
657 	default:
658 	  /* Unknown type.  */
659 	  break;
660 	}
661     }
662 }
663