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