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