]>
Commit | Line | Data |
---|---|---|
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 | |
46 | void | |
72e30c2e | 47 | ebl_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 | } |