]> git.ipfire.org Git - thirdparty/elfutils.git/blame - libebl/eblobjnote.c
libebl: ebl_object_note print 32bit annobin address ranges correctly
[thirdparty/elfutils.git] / libebl / eblobjnote.c
CommitLineData
b08d5a8f 1/* Print contents of object file note.
5199e158 2 Copyright (C) 2002, 2007, 2009, 2011, 2015, 2016, 2018 Red Hat, Inc.
de2ed97f 3 This file is part of elfutils.
b08d5a8f
UD
4 Written by Ulrich Drepper <drepper@redhat.com>, 2002.
5
de2ed97f
MW
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
b08d5a8f 8
de2ed97f
MW
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
361df7da
UD
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
de2ed97f
MW
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/>. */
b08d5a8f
UD
29
30#ifdef HAVE_CONFIG_H
31# include <config.h>
32#endif
33
34#include <inttypes.h>
35#include <stdio.h>
390dd3d2 36#include <stdlib.h>
b08d5a8f
UD
37#include <string.h>
38#include <libeblP.h>
39
72e30c2e 40#include "common.h"
5199e158 41#include "libelfP.h"
72e30c2e
MW
42#include "libdwP.h"
43#include "memory-access.h"
5199e158 44
b08d5a8f
UD
45
46void
72e30c2e 47ebl_object_note (Ebl *ebl, uint32_t namesz, const char *name, uint32_t type,
1ccdfb68 48 uint32_t descsz, const char *desc)
b08d5a8f
UD
49{
50 if (! ebl->object_note (name, type, descsz, desc))
c5da7c9e
MW
51 {
52 /* The machine specific function did not know this type. */
bb9d1b4b 53
c5da7c9e 54 if (strcmp ("stapsdt", name) == 0)
bb9d1b4b 55 {
c5da7c9e
MW
56 if (type != 3)
57 {
2e0ae048 58 printf (_("unknown SDT version %u\n"), type);
c5da7c9e
MW
59 return;
60 }
bb9d1b4b 61
c5da7c9e
MW
62 /* Descriptor starts with three addresses, pc, base ref and
63 semaphore. Then three zero terminated strings provider,
64 name and arguments. */
bb9d1b4b 65
c5da7c9e 66 union
bb9d1b4b 67 {
c5da7c9e
MW
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:
2e0ae048 76 printf (_("invalid SDT probe descriptor\n"));
c5da7c9e
MW
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
2e0ae048 126 printf (_(" PC: "));
c5da7c9e 127 printf ("%#" PRIx64 ",", pc);
2e0ae048 128 printf (_(" Base: "));
c5da7c9e 129 printf ("%#" PRIx64 ",", base);
2e0ae048 130 printf (_(" Semaphore: "));
c5da7c9e 131 printf ("%#" PRIx64 "\n", sem);
2e0ae048 132 printf (_(" Provider: "));
c5da7c9e 133 printf ("%s,", provider);
2e0ae048 134 printf (_(" Name: "));
c5da7c9e 135 printf ("%s,", pname);
2e0ae048 136 printf (_(" Args: "));
c5da7c9e
MW
137 printf ("'%s'\n", args);
138 return;
139 }
140
72e30c2e
MW
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,
22085a89
MW
158 1, EV_CURRENT);
159 if (descsz != addr_size * 2)
72e30c2e
MW
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
7a3f6fe6
MW
287 /* NT_VERSION doesn't have any info. All data is in the name. */
288 if (descsz == 0 && type == NT_VERSION)
289 return;
290
1e5302ad
LB
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
7a3f6fe6
MW
295 /* Everything else should have the "GNU" owner name. */
296 if (strcmp ("GNU", name) != 0)
297 return;
298
c5da7c9e
MW
299 switch (type)
300 {
301 case NT_GNU_BUILD_ID:
302 if (strcmp (name, "GNU") == 0 && descsz > 0)
303 {
2e0ae048 304 printf (_(" Build ID: "));
c5da7c9e
MW
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. */
2e0ae048 315 printf (_(" Linker version: %.*s\n"),
c5da7c9e
MW
316 (int) descsz, desc);
317 break;
318
5199e158
MW
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
01201890
MW
357 if (prop.pr_datasz > descsz)
358 {
359 printf ("BAD property datasz: %" PRId32 "\n",
360 prop.pr_datasz);
361 return;
362 }
363
5199e158
MW
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 ");
e8b9832a
MW
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))
5199e158 381 {
5199e158
MW
382 in.d_type = ELF_T_ADDR;
383 out.d_type = ELF_T_ADDR;
384 in.d_size = prop.pr_datasz;
e8b9832a 385 out.d_size = prop.pr_datasz;
5199e158 386 in.d_buf = (void *) desc;
e8b9832a
MW
387 out.d_buf = (elfclass == ELFCLASS32
388 ? (void *) &addr.a32
389 : (void *) &addr.a64);
5199e158
MW
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 }
e8b9832a
MW
397 if (elfclass == ELFCLASS32)
398 printf ("%#" PRIx32 "\n", addr.a32);
399 else
400 printf ("%#" PRIx64 "\n", addr.a64);
5199e158
MW
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 }
18d64cd8
MW
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 }
5199e158
MW
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 }
cd7ded3d 570
5199e158 571 if (elfclass == ELFCLASS32)
cd7ded3d 572 prop.pr_datasz = NOTE_ALIGN4 (prop.pr_datasz);
5199e158 573 else
cd7ded3d
MW
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;
5199e158
MW
581 }
582 }
583 break;
584
c5da7c9e 585 case NT_GNU_ABI_TAG:
7a3f6fe6 586 if (descsz >= 8 && descsz % 4 == 0)
c5da7c9e
MW
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. */
390dd3d2 597#define FIXED_TAG_BYTES 16
c5da7c9e
MW
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
2e0ae048 642 printf (_(" OS: %s, ABI: "), os);
c5da7c9e
MW
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 }
555e15eb 655 FALLTHROUGH;
c5da7c9e
MW
656
657 default:
658 /* Unknown type. */
659 break;
660 }
661 }
b08d5a8f 662}